Repartition SSDNodes VPS

PURPOSE

Repartition the massive 640GiB ext4 partition given to me in my SSDNodes node (I've named it deltachunk). This procedure creates an initial ramdisk to hold everything in RAM on boot. The Debian VPS has 32GiB of RAM, and the 640GiB root partition only has less than 2GiB of storage actually used.

On boot the initial ramdisk temporarily mounts the root partition, copies all of its contents to RAM, and then unmounts the root partition before continuing to boot. /etc/fstab is edited so /dev/sda1 is not mounted on boot. That way it can be manipulated, resized (shrunk), and then using a partitioning tool (fdisk or parted), having the underlying partition resized (deleted and recreated, smaller). I managed to execute this flawlessly on the first try. I never needed to restore one of the daily backup images provided to me by SSDNodes.

My goal was to set up partitions with Btrfs for /home and the Docker persistent container volumes I intend to run on this VPS. Btrfs allows me to make read-only snapshots which I can then back up using Borg backup. This article documents the first step, repartitioning the VPS. After this, I was able to install Arch Linux, with an up-to-date kernel (main reason for Arch instead of Debian, Btrfs practically requires the latest kernel to be fully supportable).

DISCLAIMER SSDNodes Technical Support told me this couldn't be done, but never satisfactorily told me why. To my knowledge, it's a QEMU virtual machine image, I can replace the virtual BIOS bootloader and everything but the partition label itself within it, without SSDNodes' help. Because I don't yet have access to the virtual BIOS or UEFI system, I can't totally replace the DOS/MBR partition table given to me by SSDNodes, so this procedure doesn't attempt that. Also, to be CLEAR: know that SSDNodes will not help if you try this procedure. I cannot be held accountable if you don't get it right. Be sure you have the SSDNode backup images to start over from scratch. If at first you don't succeed, restore from the SSDNodes backup image to start over from the absolute beginning and wait for the next backup image to be automatically taken by SSDNodes before trying again. Subscribers currently don't have any control on when these images are taken, and you only get a week's worth (a total of seven), if you have the same plan I have. I was prepared for this to take weeks, through trial and error. But as it turns out I only made the one attempt.

PREREQUISITES

  • SSDNode Performance VPS, with one 640G ext4 partition on /dev/sda1
  • Debian 10.9 (or later version) installed
  • At least one backup image provided by SSDNodes, so you can start over if something goes wrong.

PROCEDURE

  1. Create an inititial ramdisk and boot from it, leaving the partition at /dev/sda1 unmounted on boot. I followed this guide.
    a. I first made a backup of /etc/fstab
# cp /etc/fstab{,.bak2021-06-15}

 b.  Then, I commented out the root ( / ) line from /etc/fstab, adding this line instead:

# /dev/sda1
#UUID=091c1e62-8d65-4e52-8324-ce37ecf3552f /	ext4	rw,relatime 0 0
none / tmpfs defaults 0 0

      c.  Next, I edited the initramfs-tools local file after taking a backup.

    # cd /usr/share/initramfs-tools/scripts/
    # cp local{,.bak2021-06-15}

      d.  Find the local_mount_root() function definition, modifying the conditional at the end of the function:

# Mount root
mkdir /ramboottmp
# shellcheck disable=SC2086
if ! mount ${roflag} ${FSTYPE:+-t "${FSTYPE}"} ${ROOTFLAGS} "${ROOT}" /ramboottmp; then
    panic "Failed to mount ${ROOT} as root file system."
else
    mount -t tmpfs -o size=100% none ${rootmnt}
    cd ${rootmnt}
    cp -rfa /ramboottmp/* ${rootmnt}
    umount /ramboottmp
fi

    e.  Create the initial root ramdisk image and make a backup copy of /boot/grub/grub.cfg:

# mkinitramfs -o /boot/initrd.img-ramboot
# cp /boot/grub/grub.cfg{,.bak2021-06-15}

     f.  Edit /boot/grub/grub.cfg.  There's probably a better way to do this with /etc/default/grub, the files in /etc/grub.d/, and grub-mkconfig.  I'm not a grub master, so this was easier to ensure my custom initram root filesystem was mounted to RAM.  I don't have access to the UEFI/BIOS menu, so if the entry doesn't boot by default this whole effort won't work.  Copy and paste the first menuentry and submenu definitions, and add 'RAMBOOT' to the top-level menuentry/submenu.  Then change the initrd line to point to the initrd.img-ramboot ramdisk image:

# GRUB.CFG SETUP NOT INCLUDED FOR BREVITY
menuentry 'RAMBOOT Debian GNU/Linux' --class debian --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-091c1e62-8d65-4e52-8324-ce37ecf3552f' {
    load_video
    set gfxpayload=keep
    insmod gzio
    insmod part_msdos
    insmod ext2
    set root='hd0,msdos1'
    if [ x$feature_platform_search_hint = xy ]; then
      search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1  091c1e62-8d65-4e52-8324-ce37ecf3552f
    else
      search --no-floppy --fs-uuid --set=root 091c1e62-8d65-4e52-8324-ce37ecf3552f
    fi
    echo    'Loading Linux linux ...'
    linux   /boot/vmlinuz-linux root=UUID=091c1e62-8d65-4e52-8324-ce37ecf3552f rw  loglevel=3 quiet
    echo    'Loading initial ramdisk ...'
    # CHANGE THIS LINE
    #initrd  /boot/initramfs-linux.img
    initrd	/boot/initrd.img-ramboot
}
submenu 'Advanced options for RAMBOOT Debian GNU/Linux' $menuentry_id_option 'gnulinux-advanced-091c1e62-8d65-4e52-8324-ce37ecf3552f' {
    menuentry 'Debian GNU/Linux, with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-091c1e62-8d65-4e52-8324-ce37ecf3552f' {
        load_video
        set gfxpayload=keep
        insmod gzio
        insmod part_msdos
        insmod ext2
        set root='hd0,msdos1'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1  091c1e62-8d65-4e52-8324-ce37ecf3552f
        else
          search --no-floppy --fs-uuid --set=root 091c1e62-8d65-4e52-8324-ce37ecf3552f
        fi
        echo    'Loading Linux linux ...'
        linux   /boot/vmlinuz-linux root=UUID=091c1e62-8d65-4e52-8324-ce37ecf3552f rw  loglevel=3 quiet
        echo    'Loading initial ramdisk ...'
        # CHANGE THE FOLLOWING
        #initrd  /boot/initramfs-linux.img
        initrd /boot/initrd.img-ramboot
    }
    menuentry 'Debian GNU/Linux, with Linux linux (fallback initramfs)' # rest of initial submenu
#
# Original menuentry and submenu
menuentry 'Debian GNU/Linux' #rest of menuentry...
### AND ###
submenu 'Advanced options for Debian GNU/Linux' #rest of submenu...

    g.  Reboot

# systemctl reboot

    h.  The VPS will take a few moments to reboot.  Test it with:

$ ping <VPS IP address>

     i.  Once booted, log in and make sure /dev/sda1 isn't mounted anymore.

mount | grep sda

          This should return nothing, and exit status/$? should be 1.

2.  Resize the filesystem (ext4) on /dev/sda1.

a.  First, run e2fsck on /dev/sda1

# e2fsck -f /dev/sda1

    If this step isn't performed, resize2fs will complain, and will not resize the filesystem.

   b.  Resize the filesystem on /dev/sda1 (I set it to 30GiB, down from 640GiB)

# resize2fs /dev/sda1 30G

3.  Repartition /dev/sda.  I chose fdisk interactively to do this, but parted could also be used.  

# fdisk /dev/sda

    a.  Use m to display the list of available commands.
    b.  I made sure NOT to delete or overwrite the partition table (SSDNodes had selected a DOS/MBR partition table).
    c.  Use p to display the current partition table, to see the start and end of the original 640GiB partition.

Disk /dev/sda: 640 GiB, 687194767360 bytes, 1342177280 sectors
Disk model: QEMU HARDDISK
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x2589bd01

Device     Boot     Start          End     Sectors  Size Id Type
/dev/sda1  *         2048   1342177279  1342175232  640G 83 Linux

     d.  Use d to delete the primary partition.
     e.  Use n to create a new partition.
             i.  Choose p for a primary
             ii.  Set the start sector to 2048 to match the original position.
             iii.  Set the end sector to 62916608 for 30GiB.  I calculated this with bc <<< "(30 * 1024^3)/512 + 2048", which is 2048 sectors past the end of the 30GiB filesystem created in the previous steps.  This is to ensure we don't corrupt the ext4 filesystem by making the partition slightly larger.  This might not be totally necessary, but I wanted to play it safe.
             iv.  Set the type to 83 (Linux).
             v.  fdisk found the ext4 filesystem signature at this location, I chose "No" to the question,"Do you want to remove this signature?"  This is the whole point of the exercise, we don't want to lose the existing ext4 filesystem.
     f.  Use b to set the bootable flag on the new partition.
     g.  Create an extended DOS/MBR partition.  Use n to create a new partition.
             i.  Use e to create an extended partition.
             ii.  Select partition number 2.
             iii.  Select the default sector for the start.
             iv.   Select the default sector for the end (should be the rest of the disk).
     h.  Create the remaining logical partitions, 5, 6, and 7, using the extended partition created above.  In the end, the partition table looks like this:

Disk /dev/sda: 640 GiB, 687194767360 bytes, 1342177280 sectors
Disk model: QEMU HARDDISK
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x2589bd01

Device     Boot     Start        End    Sectors  Size Id Type
/dev/sda1  *         2048   62916608   62914561   30G 83 Linux
/dev/sda2        62918656 1342177279 1279258624  610G  5 Extended
/dev/sda5        62920704  197138431  134217728   64G 82 Linux swap / Solaris
/dev/sda6       197140480  260055039   62914560   30G 83 Linux
/dev/sda7       260057088 1342177279 1082120192  516G 83 Linux

      i.  Use w to write the partition table to the disk.  This will exit fdisk.  Note:  many times there is a warning that the kernel is using the old partition table.  This did not happen to me with this QEMU VPS image, but if it does:
            1.  Install parted

# apt install parted

             2.  Run partprobe

# partprobe

4.  Restore all of the backed up files from step 1.
      a.  First, mount the shrunken root filesystem:

mount /dev/sda1 /mnt

      b.  Follow these commands to restore the original files, saving the ramboot options for later:

# mv /mnt/etc/fstab{,.ramboot2021-06-15}
# cp /mnt/etc/fstab{.bak2021-06-15,}
# mv /mnt/usr/share/initramfs-tools/scripts/local{,.ramboot2021-06-15}
# cp /mnt/usr/share/initramfs-tools/scripts/local{.bak2021-06-15,}
# mv /mnt/boot/grub/grub.cfg{,.ramboot2021-06-15}
# cp /mnt/boot/grub/grub.cfg{.bak2021-06-15,}

5.  Reboot.

# systemctl reboot

And that's it! Once I had my disk repartitioned, I was able to proceed with bootstrapping Arch Linux over this Debian installation.