1. Provision with the latest Ubuntu template from the control panel. At the time of writing this was ubuntu18img.
  2. Once the machine is booted, login as root over the noVNC console (you may wish to SSH in to easy copy&paste but have a noVNC console open as you'll need it at points) and run:
    apt update && apt -y dist-upgrade && apt -y autoremove
    
  3. Stop the cloud init scripts running and setup grub so you can see the boot menu easily:
    1
    2
    3
    4
    mv /etc/cloud /etc/cloud.bak
    rm /etc/default/grub.d/50-cloudimg-settings.cfg 
    sed -e 's/GRUB_TIMEOUT_STYLE=hidden/GRUB_TIMEOUT_STYLE=menu/g'    -e 's/GRUB_TIMEOUT=0/GRUB_TIMEOUT=10/g'    -i.bak /etc/default/grub
    update-grub
    
  4. We then create a simple script to ease tasks when we drop to the initramfs shell
    1
    2
    3
    4
    5
    6
    7
    cat <<EOF>/script.sh
    cp /run/mnt/sbin/resize2fs /run/mnt/sbin/e2fsck /run/mnt/script.sh /
    umount /run/mnt
    /e2fsck -f /dev/sda1
    /resize2fs /dev/sda1 3G
    sync; reboot
    EOF
    
  5. Time for the first reboot - keep an eye on the noVNC as you'll need it to get into the initramfs
    reboot
    
  6. Go to 'Advanced options for Ubuntu' and press 'e' when the latest kernel's recovery mode option is selected.
  7. Edit the 'linux' line and remove all options but add 'ro init=/bin/sh'
  8. Press Ctrl-X to boot
  9. You'll now be at an initramfs prompt
  10. Once here you'll need to make a directory, mount the root drive, copy the script we made earlier and run it. After running it the machine will reboot.
    1
    2
    3
    4
    mkdir /run/mnt
    mount /dev/sda1 /run/mnt
    cp /run/mnt/script.sh /
    sh /script.sh
    
  11. Reboot to your previous ubuntu install. On logging in you'll now see you have a small root (/) partition of only a few gig rather than the previous one that took the whole disk.
    1
    2
    3
    root@system:~# df -hP /
    Filesystem      Size  Used Avail Use% Mounted on
    /dev/sda1       2.9G  1.5G  1.4G  52% /
    
  12. We'll now shrink the partition table to match this size, and create a new partition to hold a copy of the current install. Because we are working on an active disk we'll need to reboot after this
    1
    2
    3
    4
    5
    6
    7
    8
    9
    start=$(sfdisk -d /dev/sda | grep '^/dev/sda1 :' | awk '{print $4}' | cut -f 1 -d \,)
    uuid=$(sfdisk -d /dev/sda | grep '^/dev/sda1 :' | awk '{print $8}' | cut -f 1 -d \,)
    (sfdisk -d /dev/sda | grep -v '^/dev/sda'; echo "/dev/sda1 : start=$start, size=3G, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, $uuid"; sfdisk -d /dev/sda | grep '^/dev/sda1[45]') | sfdisk --force /dev/sda
    
    size=$(sfdisk -d /dev/sda | grep '^/dev/sda1 ' | awk '{print $6}' | cut -f 1 -d \,)
    last=$(sfdisk -d /dev/sda | grep ^last-lba | awk '{print $2}')
    delta=0
    (sfdisk -d /dev/sda | grep -v '^/dev/sda' ; sfdisk -d /dev/sda | grep '^/dev/sda1 :'; echo "/dev/sda13 : start=$(($(($last-$size))-$delta)), size=$(($size+$delta)), type=0FC63DAF-8483-4772-8E79-3D69D8477DE4"; sfdisk -d /dev/sda | grep '^/dev/sda1[45] :') | sfdisk --force /dev/sda
    reboot
    
  13. Now we have sda1 - the shrunk root from the initial install, sda13 - a bare parition to copy the initial install to along with sda14 and sda15 for Boot and EFI. Lets copy sda1 to sda13:
    root@system:~# dd if=/dev/sda1 of=/dev/sda13 bs=4M 
    768+0 records in
    768+0 records out
    3221225472 bytes (3.2 GB, 3.0 GiB) copied, 7.27464 s, 443 MB/s
    root@system:~# e2fsck -y /dev/sda13
    e2fsck 1.44.1 (24-Mar-2018)
    cloudimg-rootfs: recovering journal
    Setting free inodes count to 288387 (was 288395)
    Setting free blocks count to 360142 (was 360214)
    cloudimg-rootfs: clean, 98685/387072 files, 426290/786432 blocks
    root@system:~# tune2fs -O metadata_csum_seed /dev/sda13
    tune2fs 1.44.1 (24-Mar-2018)
    root@system:~# tune2fs -U random /dev/sda13
    tune2fs 1.44.1 (24-Mar-2018)
    root@system:~# e2fsck -fy /dev/sda13
    e2fsck 1.44.1 (24-Mar-2018)
    Pass 1: Checking inodes, blocks, and sizes
    Pass 2: Checking directory structure
    Pass 3: Checking directory connectivity
    Pass 4: Checking reference counts
    Pass 5: Checking group summary information
    cloudimg-rootfs: 98685/387072 files (0.3% non-contiguous), 426290/786432 blocks
    root@system:~# tune2fs -O ^metadata_csum_seed /dev/sda13
    tune2fs 1.44.1 (24-Mar-2018)
    Recalculating checksums could take some time.
    Proceed anyway (or wait 5 seconds to proceed) ? (y,N) <proceeding>
    root@system:~# tune2fs -L cloudimg-orig /dev/sda13
    tune2fs 1.44.1 (24-Mar-2018)
    root@system:~# e2fsck -y /dev/sda13
    e2fsck 1.44.1 (24-Mar-2018)
    cloudimg-orig: clean, 98685/387072 files, 426290/786432 blocks
    
  14. We'll then mount sda13 and make some changes to make it bootable
    mount /dev/sda13 /mnt/
    for i in sys proc dev boot/efi; do mount --bind /$i /mnt/$i; done
    rm /mnt/etc/resolv.conf
    cp /etc/resolv.conf /mnt/etc/resolv.conf
    chroot /mnt
    sed -i.bak -e 's/LABEL=cloudimg-rootfs/LABEL=cloudimg-orig/g' /etc/fstab 
    apt -y install grub-pc
    update-initramfs -k all -u
    update-grub
    grub-install /dev/sda
    exit
    
    for i in sys proc dev boot/efi; do umount /mnt/$i; done
    umount /mnt
    
  15. Now for another reboot, this time you should find yourself on sda13 as the root - you can confirm with df. It's an exact copy so you shouldn't see anything different other than this.
    1
    2
    3
    root@system:~# df -hP /
    Filesystem      Size  Used Avail Use% Mounted on
    /dev/sda13      2.9G  1.5G  1.4G  53% /
    
  16. So now we can re-use sda1 so lets delete it first
    1
    2
    3
    4
    sfdisk --delete /dev/sda 1
    update-initramfs -k all -u
    update-grub
    grub-install /dev/sda
    
  17. Optional Step: Having the partitions in a strange order (sda14 and 15) seems odd to me so I re-number them also. Another reboot here to make sure we have a clean working system
    sfdisk -d /dev/sda | sed -e 's/sda14/sda1/g' -e 's/sda15/sda2/g' | sfdisk --force /dev/sda
    reboot
    
  18. Now lets create the new partition for LUKS and LVM. Again, because it's an active disk we'll need to reboot :-(
    echo ",,," | sfdisk -a --force /dev/sda
    reboot
    
  19. Now we setup LUKS and LVM - you might want a different layout here:
    cryptsetup luksFormat /dev/sda3 
    cryptsetup luksOpen /dev/sda3 cryptroot
    pvcreate /dev/mapper/cryptroot 
    vgcreate system_vg /dev/mapper/cryptroot 
    lvcreate -L4G -n ROOT system_vg
    lvcreate -L2G -n VAR system_vg
    lvcreate -L4G -n DOCKER system_vg
    lvcreate -L1G -n HOME system_vg
    lvcreate -L4G -n SWAP system_vg 
    mkswap /dev/system_vg/SWAP
    for i in ROOT VAR DOCKER HOME; do mkfs.ext4 /dev/system_vg/$i; done
    
  20. Now is the time to reinstall to the new structure. First step mount it all:
    1
    2
    3
    4
    5
    6
    mount /dev/system_vg/ROOT /mnt/
    mkdir /mnt/var /mnt/home
    mount /dev/system_vg/VAR /mnt/var
    mount /dev/system_vg/HOME /mnt/home
    mkdir -p /mnt/var/lib/docker
    mount /dev/system_vg/DOCKER /mnt/var/lib/docker
    
  21. Next step install debootstrap and install a base system to it. I'm using groovy here:
    apt install debootstrap
    debootstrap --arch amd64 groovy /mnt/ https://mirrors.chroot.ro/ubuntu
    
  22. We can now chroot into that install and create an apt sources file, generate an fstab and install some required packages:
    mkdir /mnt/boot/efi
    for i in sys proc dev boot/efi; do mount --bind /$i /mnt/$i; done
    chroot /mnt/
    
    cat<<EOF>/etc/apt/sources.list
    deb http://archive.ubuntu.com/ubuntu groovy main multiverse universe
    deb http://security.ubuntu.com/ubuntu groovy-security main multiverse universe
    EOF
    
    ( mount | grep ^/ | while read line; do  uuid=$(blkid -o value --match-tag UUID $(echo $line | cut -f 1));  echo UUID=$uuid $(echo $line | cut -f 3 -d ' ') $(echo $line | cut -f 5 -d ' ') defaults 0 0; done ; echo "tmpfs /tmp tmpfs size=4G 0 0") > /etc/fstab
    
    apt -y install linux-virtual lvm2 grub-pc cryptsetup openssh-server
    sed -e 's/GRUB_TIMEOUT_STYLE=hidden/GRUB_TIMEOUT_STYLE=menu/g'    -e 's/GRUB_TIMEOUT=0/GRUB_TIMEOUT=10/g'    -i.bak /etc/default/grub
    
  23. Because I'm using LUKS I also setup CRYPTODISK settings for grub and create the keyfile script
    echo 'GRUB_ENABLE_CRYPTODISK=y' >> /etc/default/grub
    
    dd bs=512 count=4 if=/dev/urandom of=/crypto_keyfile.bin
    cryptsetup luksAddKey /dev/sda3 /crypto_keyfile.bin
    chmod 000 /crypto_keyfile.bin
    echo "cryptroot UUID=$(blkid /dev/sda3 -o value | head -n 1) /crypto_keyfile.bin luks,keyscript=/bin/cat" >> /etc/crypttab 
    
    cat <<EOF>/etc/initramfs-tools/hooks/crypto_keyfile
    #!/bin/sh
    cp /crypto_keyfile.bin "\${DESTDIR}"
    EOF
    chmod +x /etc/initramfs-tools/hooks/crypto_keyfile
    
  24. Now time to regenerate the initramfs, update grub and install it
    1
    2
    3
    update-initramfs -k all -u
    update-grub
    grub-install /dev/sda
    
  25. At this point I also update the root passwd and generate some users and configure the network
    passwd root
    adduser --ingroup users jamesr
    adduser jamesr adm 
    adduser jamesr sudo
    cat <<EOF>/etc/netplan/01-netcfg.yaml
    network:
      version: 2
      renderer: networkd
      ethernets:
        ens18:
          dhcp4: false
          dhcp6: false
          addresses: [ "w.x.y.z/22" ]
          gateway4: "w.x.y.z"
          nameservers:
            addresses:
              - "1.1.1.1"
              - "1.0.0.1"
    EOF
    
  26. You can now drop out of the chroot, unmount everything, delete the old install, grow the paritions to fullsize and do a final reboot into your new system
    1
    2
    3
    4
    5
    6
    7
    8
    exit # To leave the chroot
    for i in sys proc dev boot/efi; do umount /mnt/$i; done
    for i in var/lib/docker/ home var; do umount /mnt/$i; done
    umount /mnt
    apt install cloud-guest-utils fdisk
    sfdisk --delete /dev/sda 13
    growpart /dev/sda 3
    reboot
    
  27. You'll just want to max on the PV Size like so as the final step... no reboot needed this time! :D
    pvresize /dev/mapper/cryptroot
    
Edit
Pub: 21 Mar 2021 17:57 UTC
Views: 581