Automated Ubuntu Installation
Ubuntu supports major version upgrades using the
do-release-upgrade
utility, but in my experience this is not a reliable means of updating the
operating system. Automating installation facilitates testing and iterative
design of systems configuration.
Although Ubuntu is a derivative of Debian, it doesn't follow the same convetions for an automated install.
x86_64 hardware and hypervisors usually don't provide a means of picking a one-time boot device. To force a reinstall wipe the first part of the disk.
# reinstall # use with caution! dd if=/dev/zero of=/dev/sda bs=1M count=100 reboot
BIOS PXE Boot
The initial ramdisk and kernel can be taken from the install ISO
mkdir -p /tftpboot/ubuntu22 cp casper/{vmlinuz,initrd} /tftpboot/ubuntu22/
# /tftpboot/pxelinux.cfg/01-00-0c-29-f9-6d-4e
DEFAULT menu.c32
PROMPT 0
TIMEOUT 10
MENU TITLE PXE Menu
LABEL Install Ubuntu 22 Server
KERNEL ubuntu22/vmlinuz
APPEND initrd=ubuntu22/initrd ip=dhcp cloud-config-url=/dev/null url=http://192.168.2.20/ubuntu-22.04.1-live-server-amd64.iso autoinstall ds=nocloud-net;s=http://192.168.2.20/ubuntu-srv/
Setting
cloud-config-url
is not required, but avoids a redundant fetch of the install image.
iPXE Loader
If the machine is booting with UEFI and iPXE the configuration is similar
#!ipxe set base-url http://192.168.2.20/pub kernel /ubuntu20/vmlinuz initrd=initrd ip=dhcp cloud-config-url=/dev/null url=http://192.168.2.20/ubuntu-20.04.5-live-server-amd64.iso autoinstall ds=nocloud-net;s=http://192.168.2.20/ubuntu-srv/ initrd /ubuntu20/initrd boot
Server Config
Create two empty files
touch /var/www/htdocs/meta-data touch /var/www/htdocs/vendor-data
As well as a file called
user-data
#cloud-config autoinstall: identity: hostname: ubuntu-srv password: $crypted_pass username: ubuntu locale: en_US.UTF-8 ssh: allow-pw: false authorized-keys: ['ssh-ed25519 ...'] install-server: true packages: - tmux user-data: timezone: America/New_York late-commands: - | awk -F= '/HOSTNAME/ { print $2 }' /var/run/systemd/netif/leases/? > /target/etc/hostname - | echo 'eradman ALL=(ALL) NOPASSWD:ALL' > /target/etc/sudoers.d/ubuntu-nopw chmod 440 /target/etc/sudoers.d/ubuntu-nopw version: 1
Notes
-
#cloud-config
is a YAML comment, but seems to be required! The installer will not report the cause of the failure if it is omitted. -
hostname
is required, and unfortunately cannot be set using DHCPoption host-name
. To work around this we useawk
to find the hostname in the DHCP leases file at the end of the installation.
Minimal Workstation
#cloud-config autoinstall: identity: hostname: ubuntu-wks password: $crypted_pass username: ubuntu locale: en_US.UTF-8 ssh: allow-pw: false authorized-keys: ['ssh-ed25519 ...'] install-server: true packages: - adwaita-icon-theme-full - efibootmgr - gnome-control-center - gnome-session - gnome-shell-extension-ubuntu-dock - gnome-shell-extensions - gnome-terminal - nautilus late-commands: - | awk -F= '/HOSTNAME/ { print $2 }' /var/run/systemd/netif/leases/? > /target/etc/hostname - | echo 'eradman ALL=(ALL) NOPASSWD:ALL' > /target/etc/sudoers.d/ubuntu-nopw chmod 440 /target/etc/sudoers.d/ubuntu-nopw - | /target/bin/efibootmgr | awk '/Boot.+ ubuntu/ { print substr($1, 5, 4) }' | xargs -n1 /target/bin/efibootmgr -o true version: 1
Notes
-
autoinstall
will not set the boot order on UEFI systems.
A manual workaround is to find the
ubuntu
label and make this item first in the boot list. Each item identifier is four hex digits.
Oddly the install on Ubuntu 20 may not use all available space. Expand the root volume using
lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv