Ubuntu 22.04 Server Autoinstall ISO

Introduction

This post is a follow up to How-To: Make Ubuntu Autoinstall ISO with Cloud-init written in Sept. 2021. We will look at changes needed for Ubuntu 22.04.

The Ubuntu sever autoinstall method changed with the release of 20.04. Prior to that the old Debian pre-seed method was used. The new autoinstall method uses a “user-data” file similar in usage to what is done with cloud-init. The Ubuntu installer, ubiquity, was modified for this and became subiquity (server ubiquity).

The autoinstall “user-data” YAML file is a superset of the cloud-init user-data file and contains directives for the install tool curtin. The only real guide for what can go in this file is Automated Server Installs Config File Reference and that is not great reference. Actual usage requires considerable web searching, guess work and trial and error.

My personal feeling is that it’s a poorly documented, convoluted mess. The cloud-init and curtin are good tools but the overall experience of trying to work with these for the special case of the Ubuntu autoinstall is not good. Hopefully this post will help those trying get something working.

While researching for this post I found a delightful post by Jim Angel. He does a respectable job of illuminating the concepts involved. I recommend the post as a good-read.

Step 0) Prerequisites

I am building the autoinstall ISO on an Ubuntu 22.04 system. Here are a few packages you will need,

  • 7z sudo apt install p7zip for unpacking the source ISO (including mbr and efi partition images)
  • wget sudo apt install wget to download a fresh daily build of the 22.04 service ISO
  • xorriso sudo apt install xorriso for building the modified ISO

Two of the biggest sources of trouble when you are creating the user-data file for an autoinstall ISO are,

Step 1) Set up the build environment

Make a directory to work in and get a fresh copy of the server ISO.

mkdir u22.04-autoinstall-ISO
cd u22.04-autoinstall-ISO
mkdir source-files
wget https://cdimage.ubuntu.com/ubuntu-server/jammy/daily-live/current/jammy-live-server-amd64.iso

Step 2) Unpack files and partition images from the Ubuntu 22.04 live server ISO

The Ubuntu 22.04 server ISO layout differs from the 20.04 ISO. 20.04 used a single partition on the ISO but 22.04 has separate gpt partitions for mbr, efi, and the install root image.

7zip is very nice for unpacking the ISO since it will create image files for the mbr and efi partitions for you!

7z -y x jammy-live-server-amd64.iso -osource-files

Note, there is no space in -osource-files

In the source-files directory you will see the ISO files plus a directory named ‘[BOOT]’. That directory contains the the files 1-Boot-NoEmul.img 2-Boot-NoEmul.img those are are, respectively, the mbr (master boot record) and efi (UEFI) partition images from the ISO. Those will be used when we create the modified ISO. There is no reason to leave the raw image files on the new ISO, so move them out of the way and give the directory a better name,

mv  '[BOOT]' ../BOOT

Step 3) Edit the ISO grub.cfg file

Edit source-files/boot/grub/grub.cfg and add the following stanza above the existing menu entries,

menuentry "Autoinstall Ubuntu Server" {
    set gfxpayload=keep
    linux   /casper/vmlinuz quiet autoinstall ds=nocloud\;s=/cdrom/server/  ---
    initrd  /casper/initrd
}

Note the backslash “\” in front of the semi-colon. That is needed to escape the “;”, otherwise grub would treat the rest of the line as a comment!

This menu entry adds the autoinstall kernel directive and the “data source” (ds) for cloud-init of type “nocloud”. s=/cdrom/server/ is a reference to the directory where we will add user-data and meta-data files that contain the installer configuration yaml. /cdrom is the top level directory of the ISO.

…add the directory for the user-data and meta-data files

mkdir source-files/server

Note; you can create other directories to contain alternative user-data file configurations and add extra grub menu entries pointing to those directories. That way you could have multiple install configurations on the same ISO and select the appropriate one from the boot menu during install.

Step 4) Create and add your custom autoinstall user-data files

This is where you will need to read the documentation for the user-data syntax and format. I will provide a sample file to get you started.

Note; the meta-data file is just an empty file that cloud-init expects to be present (it would be populated with data needed when using cloud services)

touch source-files/server/meta-data

user-data example file

#cloud-config
autoinstall:
  version: 1
  interactive-sections:  # Install groups listed here will wait for user input
   - storage
  storage:  # This should set the interactive (lvm set) default
    layout:
      name: lvm
      match:
        size: largest  
  locale: en_US.UTF-8
  keyboard:
    layout: us
  identity:
    hostname: puget-000
    password: $6$PiTL.ZmMVYG6U4q4$qa8lkOtlAAioKLKqt1q1Ci03HUAE4xRnhrvNd1x1oaSVoma2sTRCHtvt2/QV61tn0QQF6m2e/n0Uf1fQ/3yid0
    username: ubuntu
  ssh:
    allow-pw: true
    install-server: true
  apt:
    primary:
      - arches: [default]
        uri: http://us.archive.ubuntu.com/ubuntu/
 #   sources:     # Example for adding a ppa source
 #     ignored1:  # This is here to get the yaml formatting right when adding a ppa
 #       source: ppa:graphics-drivers/ppa
  packages: 
    - build-essential
    - network-manager
    - dkms
    - emacs-nox
    # - ubuntu-desktop-minimal^  # uncomment to add a minimal desktop
  package_update: true
  package_upgrade: true
  late-commands:
    # Changing from networkd to NetworkManager
    # move existing config out of the way
    - find /target/etc/netplan/ -name "*.yaml" -exec sh -c 'mv "$1" "$1-orig"' _ {} \;
    # Create a new netplan and enable it
    - |
      cat <<EOF | sudo tee /target/etc/netplan/01-netcfg.yaml
      network:
        version: 2
        renderer: NetworkManager
      EOF
    - curtin in-target --target /target netplan generate
    - curtin in-target --target /target netplan apply
    - curtin in-target --target /target systemctl enable NetworkManager.service
    # Install NVIDIA driver (with apt-get flags)
    - curtin in-target -- apt-get -y install --no-install-recommends nvidia-driver-520 
  #user-data: # Commands here run during first boot (cannot be interactive)
  #  runcmd:
  #    # Install the NVIDIA driver from the ppa we setup earlier
  #    - [apt-get, install, --yes,  nvidia-driver-510, --no-install-recommends] 

This gist from my older post has some other ideas for a user-data config along with some useful comments by helpful readers.

Getting the user-data file right is where most of your effort will go. It will likely require trial-and-error iterations to get it right!

Step 5) Generate a new Ubuntu 22.04 server autoinstall ISO

The following command is helpful when trying to setup the arguments for building an ISO. It will give flags and data to closely reproduce the source base install ISO.

xorriso -indev jammy-live-server-amd64.iso -report_el_torito as_mkisofs

Editing the report from the above I was able to come up with the command below for creating the autoinstall ISOs.

cd source-files

xorriso -as mkisofs -r \
  -V 'Ubuntu 22.04 LTS AUTO (EFIBIOS)' \
  -o ../ubuntu-22.04-autoinstall.iso \
  --grub2-mbr ../BOOT/1-Boot-NoEmul.img \
  -partition_offset 16 \
  --mbr-force-bootable \
  -append_partition 2 28732ac11ff8d211ba4b00a0c93ec93b ../BOOT/2-Boot-NoEmul.img \
  -appended_part_as_gpt \
  -iso_mbr_part_type a2a0d0ebe5b9334487c068b6b72699c7 \
  -c '/boot.catalog' \
  -b '/boot/grub/i386-pc/eltorito.img' \
    -no-emul-boot -boot-load-size 4 -boot-info-table --grub2-boot-info \
  -eltorito-alt-boot \
  -e '--interval:appended_partition_2:::' \
  -no-emul-boot \
  .

Note; the “.” at the end. That is indicating the path to the current directory i.e. “use the current directory for the source files to build the ISO”.

The partition images that 7z extracted for us are being added back to the recreated ISO.

Test and debug your new autoinstall ISO

You will almost certainly have debugging to do! It’s hard to get a user-data file right on the first attempt. To mke testing easier I recommend using Virtualbox to setup a simple VM that you can use for autoinstall testing. After a trial you create a new debugged ISO and use the Virtualbox VM settings to point at the new ISO and repeat.

When you get a working user-data in the VM then move to real hardware for validation.

Conclusion

Hopefully this updated guide will save you some time and headaches while building an autoinstall ISO for Ubuntu 22.04 server.

I’m not sure if Canonical/Ubuntu will move the desktop installer to this method in the future. For automating the desktop install you could do a procedure similar to what we did for server but substituting the appropriate Debian preseed file for the user-data file. I have an older post that has a, hopefully, useful pressed file example. Note: Auto-Install Ubuntu with Custom Preseed ISO I have not tested this with the Ubuntu 22.04 desktop installer.

Happy computing! -dbk @dbkinghorn

Tags: ,