Our Blog

Ongoing observations by End Point people

Installing Ubuntu 18.04 to a different partition from an existing Ubuntu installation

By Bharathi Ponnusamy
April 6, 2020

Clean setup

Photo by Patryk Grądys on Unsplash

Our Liquid Galaxy systems are running on Ubuntu 14.04 LTS (Trusty). We decided to upgrade them to Ubuntu 18.04 LTS (Bionic) since Ubuntu 14.04 LTS reached its end of life on April 30, 2019.

Upgrading from Ubuntu 14.04 LTS

The recommended way to upgrade from Ubuntu 14.04 LTS is to first upgrade to 16.04 LTS, then to 18.04 LTS, which will continue to receive support until April 2023:

14.04 LTS → 16.04 LTS → 18.04 LTS

Ubuntu has LTS → LTS upgrades, allowing you to skip intermediate non-LTS releases, but we can’t skip intermediate LTS releases; we have to go via 16.04, unless we want to do a fresh install of 18.04 LTS.

For a little more longevity, we decided to do a fresh install of Ubuntu 18.04 LTS. Not only is this release supported into 2023 but it will offer a direct upgrade route to Ubuntu 20.04 LTS when it’s released in April 2020.

Installing Clean Ubuntu 18.04 LTS from Ubuntu 14.04 LTS

Install debootstrap

The debootstrap utility installs a very minimal Debian system. Debootstrap will install a Debian-based OS into a sub-directory. You don’t need an installation CD for this. However, you need to have access to the corresponding Linux distribution repository (e.g. Debian or Ubuntu).

apt-get update
apt-get -y install debootstrap

Creating a new root partition

Create a logical volume with size 12G and format the filesystem to ext4:

lvcreate -L12G -n ROOT_VG/ROOT_VOLUME
mkfs.ext4 /dev/ROOT_VG/ROOT_VOLUME

Mounting the new root partition

Mount the partition at /mnt/root18. This will be the root (/) of your new system.

mkdir -p /mnt/root18
mount /dev/ROOT_VG/ROOT_VOLUME /mnt/root18

Bootstrapping the new root partition

Debootstrap can download the necessary files directly from the repository. You can substitute any Ubuntu archive mirror for ports.ubuntu.com/ubuntu-ports in the command example below. Mirrors are listed here.

Replace $ARCH below with your architecture: amd64, arm64, armhf, i386, powerpc, ppc64el, or s390x.

debootstrap --arch $ARCH $DISTRO $ROOT_MOUNTPOINT
debootstrap --arch amd64 bionic /mnt/root18

Installing fstab

This just changes the root (/) partition path in the new installation while keeping the /boot partition intact. For example, /dev/mapper/headVG-root //dev/mapper/headVG-root18 /. Since device names are not guaranteed to be the same after rebooting or when a new device is connected, we use UUIDs (Universally Unique Identifiers) to refer to partitions in fstab. We don’t need to use UUIDs for logical volumes since their device names won’t change.

OLD_ROOT_PATH="$(awk '$2 == "/" { print $1 }' /etc/fstab)"
sed "s:^${OLD_ROOT_PATH}\s:/dev/mapper/headVG-root18 :" /etc/fstab > /mnt/root18/etc/fstab

Mounting things in the new root partition

Bind /dev to the new location, then mount /sys, /proc, and /dev/pts from your host system to the target system.

mount --bind /dev /mnt/root18/dev
mount -t sysfs none /mnt/root18/sys
mount -t proc none /mnt/root18/proc
mount -t devpts none /mnt/root18/dev/pts

Configuring apt

Debootstrap will have created a very basic /mnt/root18/etc/apt/sources.list that will allow installing additional packages. However, I suggest that you add some additional sources, such as the following, for source packages and security updates:

echo "deb http://us.archive.ubuntu.com/ubuntu bionic main universe
deb-src http://us.archive.ubuntu.com/ubuntu bionic main universe
deb http://security.ubuntu.com/ubuntu bionic-security main universe
deb-src http://security.ubuntu.com/ubuntu bionic-security main universe" > /mnt/root18/etc/apt/sources.list

Make sure to run apt update with chroot after you have made changes to the target system sources list.

Now we’ve got a real Ubuntu system, if a rather small one, on disk. chroot into it to set up the base configurations.

LANG=C.UTF-8 chroot /mnt/root18 /bin/bash

Installing required packages and running chef-client

As we are maintaining most of the Liquid Galaxy configuration and packages with Chef, we need to install chef-client, configure it on the new target system, and run chef-client to complete the setup.

Copy the chef configuration and persistent net udev rules into place:

cp -a /etc/chef /mnt/root18/etc/
cp /etc/udev/rules.d/70-persistent-net.rules /mnt/root18/etc/udev/rules.d/

Install and run chef-client and let it set up our user login:

cat <<EOF | chroot /mnt/root18
apt-get update && apt-get install -y curl wget
curl -L https://omnitruck.chef.io/install.sh | bash -s -- -v 12.5.1
chef-client -E production_trusty -o 'recipe[users]'
EOF

Next, chroot and install the required packages:

cat <<EOF | chroot /mnt/root18
mount /boot
apt-get update && apt-get install -y --no-install-recommends linux-image-generic lvm2 openssh-server ifupdown net-tools
locale-gen en_US.UTF-8
EOF

Set Ubuntu 14.04 to boot default

Create file 42_custom_template_trusty:

#!/bin/sh
# Entry for trusty system
menuentry 'TRUSTY' --class liquid --class gnu-linux --class gnu --class os {
        # Skipped lines
        linux   /trusty/vmlinuz-$trusty_kernel_version root=/dev/mapper/headVG-root ro nomodeset biosdevname=0 modprobe.blacklist=gma500_gfx quiet
        initrd  /trusty/initrd.img-$trusty_kernel_version
}

Create file 42_custom_template_bionic:

#!/bin/sh
# Entry for bionic system
menuentry 'BIONIC' --class liquid --class gnu-linux --class gnu --class os {
        # Skipped lines
        linux   /vmlinuz-$bionic_kernel_version-generic root=/dev/mapper/headVG-root18 ro nomodeset net.ifnames=0 biosdevname=0 modprobe.blacklist=gma500_gfx quiet
        initrd  /initrd.img-$bionic_kernel_version-generic
}

On the Current system (Trusty):

Back up the current Trusty kernel files into /boot/trusty and create a custom menu entry configuration for Ubuntu 14.04 on 42_custom_trusty. Update /etc/default/grub to set Ubuntu 14.04 as the default menu entry and run update-grub to apply it to the current system. This will be used as a fail-safe method to run Trusty again if there is a problem with the new installation.

mkdir -vp /boot/trusty
cp -v /boot/*-generic /boot/trusty/

envsubst '${trusty_kernel_version}' < 42_custom_template_trusty > /etc/grub.d/42_custom_template_trusty
chmod +x /etc/grub.d/42_custom_template_trusty

sed -i 's/GRUB_DEFAULT=.*/GRUB_DEFAULT="TRUSTY"/' /etc/default/grub
update-grub

On the target system (Bionic):

Create the custom menu entry for Ubuntu 14.04 and Ubuntu 18.04 on the target system.

mkdir -p /mnt/root18/etc/grub.d
envsubst '${trusty_kernel_version}' < 42_custom_template_trusty > /mnt/root18/etc/grub.d/42_custom_template_trusty
envsubst '${bionic_kernel_version}' < 42_custom_template_bionic > /mnt/root18/etc/grub.d/42_custom_template_bionic
chmod +x /mnt/root18/etc/grub.d/42_custom_template_{trusty,bionic}

chroot into the target system and update /etc/default/grub to set Ubuntu 14.04 as the default menu entry and run update-grub. This will also update the GRUB configuration to boot Ubuntu 14.04 as default and update the 0th menu entry to Ubuntu 18.04 (Bionic).

cat <<EOF | chroot /mnt/root18
sed -i 's/GRUB_DEFAULT=.*/GRUB_DEFAULT="TRUSTY"/' /etc/default/grub
update-grub
EOF

Boot into Bionic

To boot into Ubuntu 18.04 (Bionic), reboot the system after grub-reboot bionic and test if the bionic system is working as expected.

$ grub-reboot bionic
$ reboot

Reboot and test our new 0th GRUB entry:

$ grub-reboot 0
$ reboot

A normal reboot returns to Ubuntu 14.04 (Trusty) since the default menu entry is still set to Ubuntu 14.04 (Trusty).

Set Ubuntu 18.04 to boot default

To set our new Ubuntu 18.04 installation as the default menu entry, change GRUB_DEFAULT to 0 in /etc/default/grub and run update-grub to apply it. The next reboot will boot into Ubuntu 18.04.

sed -i 's/GRUB_DEFAULT=.*/GRUB_DEFAULT=0/' /etc/default/grub
update-grub

Congratulations! You now have a freshly installed Ubuntu 18.04 system.

linux ubuntu update sysadmin devops chef


Comments

Popular Tags


Archive


Search our blog