Install Ubuntu from ISO on IPv6-only KVM Server in SolusIO

I recently obtained a KVM virtual server on SolusIO platform, and I want to install Ubuntu 20.04 Server from the official ISO image. This is not as easy as I hoped, but I figured it out.

Note: if you are in a hurry, skip the "Background" and start from "Part 1" section.

Background: SolusIO cannot Mount ISO Image

SolusIO is a virtual infrastructure management solution published by Plesk International Gmbh, the same company behind the popular SolusVM software. They describe SolusIO to be the successor of SolusVM, with more focus on the self-service approach for end users.

SolusIO inherits the same clean user interface from SolusVM, and is easy to use. However, as a power user, I notice several features are missing in SolusIO. One of these features is the ability to install the operating system from an ISO image.

Presently, SolusIO only supports installing operating systems from the provided templates. While a template installation is convenient, I prefer to install from official ISO images so that I can have better control over what goes into my system, and avoid vulnerabilities such as the debianuser backdoor.

An easy way to load a ISO installer is through netboot.xyz, a hosted service that can boot a server over the Internet and download the installer of many Linux and BSD distributions. Even if the VPS hosting platform does not support mounting ISO images, it is possible to install iPXE bootloader per Tip: Install OS via netboot.xyz without ISO support, and then start netboot.xyz from there.

However, this method did not work for me. The iPXE package, as distributed in most operating systems, only supports IPv4. To make it work on my IPv6-only server, I would have to recompile iPXE with IPv6 enabled, which could be a complicated task. I need another way.

Part 1: Boot from ISO on Hard Disk

I thought: can I download the ISO image and load it from hard disk, and start the installer, just like netboot.xyz does, but without going through the network? I searched for "how to boot ISO from hard disk", and found a helpful guide from Ubuntu documentation site: Grub2/ISOBoot. Piecing together the information, I found the exact steps to start the Ubuntu installer.

  1. Install Debian 10 from SolusIO template.

    As much as I love Ubuntu, it does not work for some reason.

  2. SSH into the server as root, and download official Ubuntu ISO image.

    wget https://releases.ubuntu.com/focal/ubuntu-20.04.2-live-server-amd64.iso
    
  3. Modify /etc/grub.d/40_custom file, and append the following text:

    menuentry "Ubuntu 20.04 ISO" {
      set isofile="/root/ubuntu-20.04.2-live-server-amd64.iso"
      rmmod tpm
      loopback loop (hd0,1)$isofile
      linux (loop)/casper/vmlinuz boot=casper iso-scan/filename=$isofile noprompt noeject toram
      initrd (loop)/casper/initrd
    }
    

    In this snippet:

    • The path after isofile= is where we downloaded the ISO image.
    • (hd0,1) is /dev/sda1 written in a syntax recognized by the GRUB bootloader. If the ISO image file is on a different disk partition, you may need different numbers. Search for "drive number" on Grub2/ISOBoot page for more information.
    • The toram option copies the ISO image from the hard drive to the memory, which is necessary because the installer needs to reformat and overwrite the hard drive. This implies that this method would only work on a machine with large enough memory to fit the entire ISO image, and would not work on 1GB or smaller systems.
  4. Run update-grub.

    This command generates /boot/grub/grub.cfg that is directly used by the GRUB bootloader. It would include the menuentry entered in the last step.

  5. Open VNC window in SolusIO.

  6. Type reboot in SSH session.

  7. A blue screen titled "GNU GRUB" should appear in VNC, but only for 3 seconds. Quickly press the ⬇️ key, select "Ubuntu 20.04 ISO" menu, and press ENTER.

    GNU GRUB version 2.02, Debian GNU/Linux, Advanced Options for Debian GNU/Linux, Ubuntu 20.04 ISO

  8. You might see a message:

    error: no such module.

    Press any key to continue..._

    This is harmless, and you can press ENTER to bypass it.

  9. A minute later, the Ubuntu installer should start, and display the "Please choose you preferred language" screen.

Part 2: Install Ubuntu from In-Memory ISO

Now that we have the installer started, but we need to take care of one more detail before proceeding.

  1. On the very first "Please choose you preferred language" screen, press F2 key, which opens a shell.

  2. Type the following commands:

    losetup -d /dev/loop0
    umount /isodevice
    

    These commands umount the ISO image, so that the same hard drive can be used as an installation target.

  3. Type exit to return to the installer.

  4. The installer would attempt to detect the network, and it will probably fail because the KVM server is IPv6-only and the network does not support IPv6 autoconfiguration.

    Here I select "Continue without network", because the downloaded ISO image contains all the essential packages.

    Network connections, Configure at least one interface this server can use to talk to other machines, and which preferably provides sufficient access for updates, Continue without network

  5. The rest of installation process is same as any other Ubuntu Server installation.

  6. The installed system will be without network configuration. It's necessary to login via VNC, add IP address and routes with ip addr add and ip route add commands, before I can SSH into the server and upload my expertly written Netplan configuration.

Common Errors

Temporary failure in name resolution

When I'm downloading the official Ubuntu ISO image, I encountered this error:

# wget https://releases.ubuntu.com/focal/ubuntu-20.04.2-live-server-amd64.iso
--2021-04-28 01:48:26--  https://releases.ubuntu.com/focal/ubuntu-20.04.2-live-server-amd64.iso
Resolving releases.ubuntu.com (releases.ubuntu.com)... failed: Temporary failure in name resolution.
wget: unable to resolve host address ‘releases.ubuntu.com’

It turns out that the Debian 10 template from SolusIO has configured an IPv4 address as the DNS server, which does not work in an IPv6-only network:

# cat /etc/resolv.conf
nameserver 10.0.2.3

To resolve the error, configure an IPv6 DNS server such as Cloudflare DNS, before downloading the ISO image:

echo 'nameserver 2606:4700:4700::1111' >/etc/resolv.conf

/etc/grub.d/40_custom: menuentry: not found

When I run update-grub command, I encountered this error:

# update-grub
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-4.19.0-16-amd64
Found initrd image: /boot/initrd.img-4.19.0-16-amd64
/etc/grub.d/40_custom: 2: /etc/grub.d/40_custom: menuentry: not found
done

This is because I mistakenly deleted the original content of /etc/grub.d/40_custom file, which starts with:

#!/bin/sh
exec tail -n +3 $0

The update-grub command expects every file in /etc/grub.d directory to be a bash script. What the exec tail line does is that, it prints the content of this file starting from the third line, which happens to be our menuentry. If this line is deleted, bash would interpret menuentry as a command name, which does not exist, thus causing the error.

To resolve the error, put these two lines back to the top of /etc/grub.d/40_custom.

Block probing did not discover any disks

The Ubuntu installer fails with this message:

Guided storage configuration

Block probing did not discover any disks. Unfortunately this means that
installation will not be possible.

This is because I did not run the commands to umount the ISO, so that the installer is unable to write to the hard drive that contains the ISO image. Apparently this is a decade old bug.

To resolve the error, restart the server, enter the installer again, and remember to run the umount commands in a shell on the first screen.

Final Words

This article describes how to install Ubuntu 20.04 Server from the official ISO image on an IPv6-only KVM server managed by SolusIO platform. The steps are verified on Hosterlabs IPv6 only servers - IPv6 Plus plan.