The purpose of this post is to describe different Ubuntu installer tools and to present Ubuntu 22.04 (Jammy) installing methods for desktop and server.

Ubuntu installer ecosystem

Debian Installer (d-i)
Classic installer that has been used until 18.04, deprecated in 20.04.
Ubiquity
Graphical desktop installer. D-i preseed based auto install is available. See manual also. LiveCD can be booted from nfsroot (alternate documentation). There are a number of arguments that you can pass to the installer on the kernel command line.
Ubuntu Desktop Installer
New desktop installer, that replaces Ubiquity. GitHub repo is here. Discussion on Ubuntu Discourse about the new preview build. Refreshing the Ubuntu Desktop Installer thread.
Subiquity
Server installer frontend. GitHub repo can be found here.
Casper
An initramfs hook to boot live, preinstalled systems from read-only media. See Casper manpage. Ubiquity desktop and subiquity server install ISO medias relies on it.
Curtin
The curt installer is written in Python. Subiquity runs curtin in the background.
Cloud-init
Final configuration in the running system. Subiquity creates initial user, sets up ssh authorized key in the target system through cloud-init.

DHCP, TFTP, HTTP server

I assume you have functional DHCP, TFTP, HTTP server.

This example shows how to configure ISC DHCP server to boot a machine using a TFTP server.

allow booting;
allow bootp;
option arch code 93 = unsigned integer 16;
host ubuntu {
             hardware ethernet xx:xx:xx:xx:xx:xx;
             if option arch = 00:07 {
                     filename "boot/bootx64.efi";
             } else {
                     filename "boot/pxelinux.0";
             }
             next-server x.x.x.x;
             fixed-address x.x.x.x;
     }

Get installer ISO file and copy the following grub files to the TFTP directory.

Jammy ISO:
/boot/fonts/unicode.pf2
/EFI/boot/bootx64.efi
/EFI/boot/grubx64.efi

Download pxelinux packages and extract the following files to the TFTP directory.

$ apt download pxelinux syslinux-common

pxelinux:
/usr/lib/PXELINUX/pxelinux.0

syslinux-common:
/usr/lib/syslinux/modules/bios/ldlinux.c32
/usr/lib/syslinux/modules/bios/libutil.c32
/usr/lib/syslinux/modules/bios/menu.c32

The following example file layout can be used on the TFTP server.

.
├── boot
│   ├── bootx64.efi
│   ├── grubx64.efi
│   ├── grub
│   │   ├── font.pf2
│   │   ├── grub.cfg
│   │   └── x86_64-efi
│   │       ├── command.lst
│   │       ├── crypto.lst
│   │       ├── fs.lst
│   │       └── terminal.lst
│   ├── jammy
│   │   ├── initrd
│   │   └── vmlinuz
│   ├── ldlinux.c32 -> syslinux/bios/ldlinux.c32
|   ├── libutil.c32 -> syslinux/bios/libutil.c32
|   ├── menu.c32 -> syslinux/bios/menu.c32
│   ├── pxelinux.cfg
│   │   └── default
│   ├── pxelinux.0
|   └── syslinux
|       └── bios
│           ├── ldlinux.c32
│           ├── libutil.c32
│           └── menu.c32
└── grub -> boot/grub

Sample configuration for grub in grub.cfg.

set timeout=30

loadfont unicode

set menu_color_normal=white/black
set menu_color_highlight=black/light-gray

menuentry "Install Ubuntu Jammy (22.04)" {
        set gfxpayload=keep
        linux   /boot/jammy/vmlinuz ip=dhcp cloud-config-url=/dev/null url=http://x.x.x.x/jammy-live-server-amd64.iso autoinstall ds="nocloud-net;s=http://x.x.x.x/jammy/" --- # Don't forget the slash at the end.
        initrd  /boot/jammy/initrd
}

An example configuration in pxelinux.cfg/default.

default menu.c32
menu title Ubuntu installer

label jammy
        menu label Install Ubuntu J^ammy (22.04)
        menu default
        kernel jammy/vmlinuz
        initrd jammy/initrd
        append ip=dhcp cloud-config-url=/dev/null url=http://x.x.x.x/jammy-live-server-amd64.iso autoinstall ds=nocloud-net;s=http://x.x.x.x/jammy/ # Don't forget the slash at the end.

prompt 0
timeout 300

At least two files needs to be placed on the webserver.

  • http://x.x.x.x/jammy/user-data contains the autoinstaller configuration, see below.
  • http://x.x.x.x/jammy/meta-data can be empty, but must exists.

Ubuntu automated installation

While Canonical announces autoinstall as a server installer, it can be used to install both server and desktop systems.

Two important differencies from Debian Installer, d-i:

  1. YAML configuration format.
  2. When a question is not answered in the configuation file, this installer tries to use default values. It fails only when there is no default value.

An easy way to obtain a working user-data autoinstall configuration file is installing a machine by hand. Then copy the /var/log/installer/autoinstall-user-data file onto the webserver and customize it.

The following configuration examples are made using a QEMU virtual machine:

  • 4 GiB memory (ISO file needs to be fit in the memory in case of TFTP install method)
  • VGA graphic adapter
  • Two e1000 ethernet card
  • Two disks

Kernel parameters

  • ip=dhcp Linux tries to obtain IP address via dhcp.
  • cloud-config-url=/dev/null Workaround to download install media only once, see cloud-init kernel-cmdline documentation.
  • url=http://x.x.x.x/jammy-live-server-amd64.iso Defines the location of the installer media.
  • autoinstall Tells the installer to begin the automatic installation process.
  • ds=nocloud-net;s=http://x.x.x.x/jammy/ Location of installer configuration data source. Should be a directory on a webserver, ended with a slash '/' and containing user-data and meta-data files.

Partitioning examples are made with UEFI, go to BIOS boot disk layout if you have BIOS.

Minimal install

#cloud-config
autoinstall:
  identity:
    hostname: jammy-minimal
    password: $6$gnqbMUzHhQzpDEw.$.cCNVVDsDfj5Feebh.5O4VbOmib7tyjmeI2ZsFP7VK2kWwgJFbfjvXo3chpeAqCgXWVIW9oNQ/Ag85PR0IsKD/
    username: ubuntu
  version: 1

The password is ubuntu. And that can be generated using the following command.

mkpasswd --method=sha-512 ubuntu

Simple desktop

#cloud-config
autoinstall:
  identity:
    hostname: jammy-desktop
    password: $6$5lpwCLsKLEzMkSJc$keOAhA6aO/5RocGThmhVA7LSNuW911Rx5HHXFEa75oGK20cEdAAgn14H5f5nGeq6QgcSyLPrWcg1.JvjXbhrN/
    realname: Ubuntu user
    username: ubuntu
  keyboard:
    layout: hu
    toggle: null
    variant: ''
  locale: hu_HU.UTF-8
  storage:
    config:
# Partition table
    - { ptable: gpt, path: /dev/vda, wipe: superblock, preserve: false, name: '', grub_device: false, type: disk, id: disk-vda }
# EFI boot partition
    - { device: disk-vda, size: 536870912, wipe: superblock, flag: boot, number: 1, preserve: false, grub_device: true, type: partition, id: partition-0 }
    - { fstype: fat32, volume: partition-0, preserve: false, type: format, id: format-0 }
# Linux boot partition
    - { device: disk-vda, size: 1073741824, wipe: superblock, flag: '', number: 2, preserve: false, grub_device: false, type: partition, id: partition-1 }
    - { fstype: ext4, volume: partition-1, preserve: false, type: format, id: format-1 }
# Partition for LVM, VG
    - { device: disk-vda, size: -1, wipe: superblock, flag: '', number: 3, preserve: false, grub_device: false, type: partition, id: partition-2 }
    - { name: ubuntu-vg, devices: [ partition-2 ], preserve: false, type: lvm_volgroup, id: lvm_volgroup-0 }
# LV for root
    - { name: ubuntu-lv, volgroup: lvm_volgroup-0, size: -1, wipe: superblock, preserve: false, type: lvm_partition, id: lvm_partition-0 }
    - { fstype: ext4, volume: lvm_partition-0, preserve: false, type: format, id: format-2 }
# Mount points
    - { path: /, device: format-2, type: mount, id: mount-2 }
    - { path: /boot, device: format-1, type: mount, id: mount-1 }
    - { path: /boot/efi, device: format-0, type: mount, id: mount-0 }
# Swapfile on root volume
    swap:
      swap: 1G
  late-commands:
  - 'echo "ubuntu ALL=(ALL) NOPASSWD:ALL" > /target/etc/sudoers.d/ubuntu-nopw'
  - chmod 440 /target/etc/sudoers.d/ubuntu-nopw
  - curtin in-target --target=/target -- sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT=""/GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"/' /etc/default/grub
  - curtin in-target --target=/target -- apt-get install -y ubuntu-desktop plymouth-theme-ubuntu-logo grub-gfxpayload-lists
  version: 1

Size of the LVM partition and size of the root LV is -1 which instruct the installer to use all the remaining space. A partition or volume with size: -1 must be the last in the config. In the above example: installer creates the last partition on all the available space and creates the last defined logical volume on all the available space in the volume group.

Desktop with LVM crypto

#cloud-config
autoinstall:
  identity:
    hostname: jammy-desktop-crypt
    password: $6$5lpwCLsKLEzMkSJc$keOAhA6aO/5RocGThmhVA7LSNuW911Rx5HHXFEa75oGK20cEdAAgn14H5f5nGeq6QgcSyLPrWcg1.JvjXbhrN/
    realname: Ubuntu user
    username: ubuntu
  keyboard:
    layout: hu
    toggle: null
    variant: ''
  locale: hu_HU.UTF-8
  storage:
    config:
    - { ptable: gpt, path: /dev/vda, wipe: superblock, preserve: false, name: '', grub_device: false, type: disk, id: disk-vda }
    - { device: disk-vda, size: 536870912, wipe: superblock, flag: boot, number: 1, preserve: false, grub_device: true, type: partition, id: partition-0 }
    - { fstype: fat32, volume: partition-0, preserve: false, type: format, id: format-0 }
    - { device: disk-vda, size: 1073741824, wipe: superblock, flag: '', number: 2, preserve: false, grub_device: false, type: partition, id: partition-1 }
    - { fstype: ext4, volume: partition-1, preserve: false, type: format, id: format-1 }
    - { device: disk-vda, size: -1, wipe: superblock, flag: '', number: 3, preserve: false, grub_device: false, type: partition, id: partition-2 }
# DM crypt
    - { volume: partition-2, key: ubuntu, preserve: false, type: dm_crypt, id: dm_crypt-0 }
    - { name: ubuntu-vg, devices: [ dm_crypt-0 ], preserve: false, type: lvm_volgroup, id: lvm_volgroup-0 }
    - { name: ubuntu-lv, volgroup: lvm_volgroup-0, size: -1, wipe: superblock, preserve: false, type: lvm_partition, id: lvm_partition-0 }
    - { fstype: ext4, volume: lvm_partition-0, preserve: false, type: format, id: format-2 }
    - { path: /, device: format-2, type: mount, id: mount-2 }
    - { path: /boot, device: format-1, type: mount, id: mount-1 }
    - { path: /boot/efi, device: format-0, type: mount, id: mount-0 }
    swap:
      swap: 1G
  late-commands:
  - 'echo "ubuntu ALL=(ALL) NOPASSWD:ALL" > /target/etc/sudoers.d/ubuntu-nopw'
  - chmod 440 /target/etc/sudoers.d/ubuntu-nopw
  - curtin in-target --target=/target -- sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT=""/GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"/' /etc/default/grub
  - curtin in-target --target=/target -- apt-get install -y ubuntu-desktop plymouth-theme-ubuntu-logo grub-gfxpayload-lists
  version: 1

The DM crypt key is ubuntu in cleartext.

Simple server

#cloud-config
autoinstall:
  identity:
    hostname: jammy-server
    password: $6$5lpwCLsKLEzMkSJc$keOAhA6aO/5RocGThmhVA7LSNuW911Rx5HHXFEa75oGK20cEdAAgn14H5f5nGeq6QgcSyLPrWcg1.JvjXbhrN/
    realname: Ubuntu user
    username: ubuntu
  keyboard:
    layout: hu
    toggle: null
    variant: ''
  locale: hu_HU.UTF-8
  ssh:
    allow-pw: false
    authorized-keys: [ '<SSH KEY>' ]
    install-server: true
  storage:
    config:
    - { ptable: gpt, path: /dev/vda, wipe: superblock, preserve: false, name: '', grub_device: false, type: disk, id: disk-vda }
    - { device: disk-vda, size: 536870912, wipe: superblock, flag: boot, number: 1, preserve: false, grub_device: true, type: partition, id: partition-0 }
    - { fstype: fat32, volume: partition-0, preserve: false, type: format, id: format-0 }
    - { device: disk-vda, size: 1073741824, wipe: superblock, flag: '', number: 2, preserve: false, grub_device: false, type: partition, id: partition-1 }
    - { fstype: ext4, volume: partition-1, preserve: false, type: format, id: format-1 }
    - { device: disk-vda, size: -1, wipe: superblock, flag: '', number: 3, preserve: false, grub_device: false, type: partition, id: partition-2 }
    - { name: ubuntu-vg, devices: [ partition-2 ], preserve: false, type: lvm_volgroup, id: lvm_volgroup-0 }
    - { name: ubuntu-lv, volgroup: lvm_volgroup-0, size: 10G, wipe: superblock, preserve: false, type: lvm_partition, id: lvm_partition-0 }
    - { fstype: ext4, volume: lvm_partition-0, preserve: false, type: format, id: format-2 }
    - { path: /, device: format-2, type: mount, id: mount-2 }
    - { path: /boot, device: format-1, type: mount, id: mount-1 }
    - { path: /boot/efi, device: format-0, type: mount, id: mount-0 }
# Swap LV
    - { name: swap, volgroup: lvm_volgroup-0, size: 1073741824B, wipe: superblock, preserve: false, type: lvm_partition, id: lvm_partition-1 }
    - { fstype: swap, volume: lvm_partition-1, preserve: false, type: format, id: format-3 }
    - { path: '', device: format-3, type: mount, id: mount-3 }
  late-commands:
  - 'echo "ubuntu ALL=(ALL) NOPASSWD:ALL" > /target/etc/sudoers.d/ubuntu-nopw'
  - chmod 440 /target/etc/sudoers.d/ubuntu-nopw
  version: 1

An ssh public key can be copied to the newly installed machine. Just replace <SSH KEY> placeholder with your ssh public key (for example with the output of cat ~/.ssh/id_rsa.pub). Password SSH authentication is disabled.

This example describes the setup of a swap LV instead of a swapfile on root volume.

Server with RAID

#cloud-config
autoinstall:
  identity:
    hostname: jammy-server-raid
    password: $6$5lpwCLsKLEzMkSJc$keOAhA6aO/5RocGThmhVA7LSNuW911Rx5HHXFEa75oGK20cEdAAgn14H5f5nGeq6QgcSyLPrWcg1.JvjXbhrN/
    realname: Ubuntu user
    username: ubuntu
  keyboard:
    layout: hu
    toggle: null
    variant: ''
  locale: hu_HU.UTF-8
  ssh:
    allow-pw: false
    authorized-keys: [ '<SSH KEY>' ]
    install-server: true
  storage:
    config:
# Partition table of two disks
    - { ptable: gpt, path: /dev/vda, wipe: superblock-recursive, preserve: false, name: '', grub_device: false, type: disk, id: disk-vda }
    - { ptable: gpt, path: /dev/vdb, wipe: superblock-recursive, preserve: false, name: '', grub_device: false, type: disk, id: disk-vdb }
# Install GRUB on first disk
    - { device: disk-vda, size: 536870912, wipe: superblock, flag: boot, number: 1, preserve: false, grub_device: true, type: partition, id: partition-3 }
    - { fstype: fat32, volume: partition-3, preserve: false, type: format, id: format-2 }
# Install GRUB on second disk
    - { device: disk-vdb, size: 536870912, wipe: superblock, flag: boot, number: 1, preserve: false, grub_device: true, type: partition, id: partition-8 }
    - { fstype: fat32, volume: partition-8, preserve: false, type: format, id: format-5 }
    - { device: disk-vda, size: 1073741824, wipe: superblock, flag: '', number: 2, preserve: false, grub_device: false, type: partition, id: partition-9 }
    - { device: disk-vdb, size: 1073741824, wipe: superblock, flag: '', number: 2, preserve: false, grub_device: false, type: partition, id: partition-10 }
    - { device: disk-vda, size: -1, wipe: superblock, flag: '', number: 3, preserve: false, grub_device: false, type: partition, id: partition-11 }
    - { device: disk-vdb, size: -1, wipe: superblock, flag: '', number: 3, preserve: false, grub_device: false, type: partition, id: partition-12 }
# RAID1 for boot partition and root volume
    - { name: md0, raidlevel: raid1, devices: [ partition-10, partition-9 ], spare_devices: [], preserve: false, wipe: superblock, type: raid, id: raid-0 }
    - { name: md1, raidlevel: raid1, devices: [ partition-11, partition-12 ], spare_devices: [], preserve: false, wipe: superblock, type: raid, id: raid-1 }
# An ext4 boot filesystem on MD
    - { fstype: ext4, volume: raid-0, preserve: false, type: format, id: format-3 }
# LVM on MD
    - { name: vg0, devices: [ raid-1 ], preserve: false, type: lvm_volgroup, id: lvm_volgroup-0 }
    - { name: lv-0, volgroup: lvm_volgroup-0, size: 10737418240B, wipe: superblock, preserve: false, type: lvm_partition, id: lvm_partition-0 }
    - { fstype: ext4, volume: lvm_partition-0, preserve: false, type: format, id: format-4 }
    - { path: /, device: format-4, type: mount, id: mount-4 }
    - { path: /boot, device: format-3, type: mount, id: mount-3 }
# Install GRUB on both disks
    - { path: /boot/efi, device: format-2, type: mount, id: mount-2 }
    - { path: /boot/efi2, device: format-5, type: mount, id: mount-5 }
# Swap
    - { name: swap, volgroup: lvm_volgroup-0, size: 1073741824B, wipe: superblock, preserve: false, type: lvm_partition, id: lvm_partition-1 }
    - { fstype: swap, volume: lvm_partition-1, preserve: false, type: format, id: format-6 }
    - { path: '', device: format-6, type: mount, id: mount-6 }
  late-commands:
  - 'echo "ubuntu ALL=(ALL) NOPASSWD:ALL" > /target/etc/sudoers.d/ubuntu-nopw'
  - chmod 440 /target/etc/sudoers.d/ubuntu-nopw
  version: 1

GRUB is installed on both disks and then the two EFI partitions are also mounted under /boot.

An MD RAID1 array is configured for boot and for LVM.

Server with multiple network card

#cloud-config
autoinstall:
  identity:
    hostname: jammy-server-raid-bond
    password: $6$5lpwCLsKLEzMkSJc$keOAhA6aO/5RocGThmhVA7LSNuW911Rx5HHXFEa75oGK20cEdAAgn14H5f5nGeq6QgcSyLPrWcg1.JvjXbhrN/
    realname: Ubuntu user
    username: ubuntu
  keyboard:
    layout: hu
    toggle: null
    variant: ''
  locale: hu_HU.UTF-8
  network:
    bonds:
      bond0:
        addresses:
        - 192.168.1.5/24
        gateway4: 192.168.1.1
        interfaces:
        - ens10
        - ens3
        nameservers:
          addresses:
          - 192.168.1.2
          search:
          - example.com
        parameters:
          mode: balance-rr
    ethernets:
      ens10: {}
      ens3: {}
    version: 2
  ssh:
    allow-pw: false
    authorized-keys: [ '<SSH KEY>' ]
    install-server: true
  storage:
    config:
    - { ptable: gpt, path: /dev/vda, wipe: superblock-recursive, preserve: false, name: '', grub_device: false, type: disk, id: disk-vda }
    - { ptable: gpt, path: /dev/vdb, wipe: superblock-recursive, preserve: false, name: '', grub_device: false, type: disk, id: disk-vdb }
    - { device: disk-vda, size: 536870912, wipe: superblock, flag: boot, number: 1, preserve: false, grub_device: true, type: partition, id: partition-3 }
    - { fstype: fat32, volume: partition-3, preserve: false, type: format, id: format-2 }
    - { device: disk-vdb, size: 536870912, wipe: superblock, flag: boot, number: 1, preserve: false, grub_device: true, type: partition, id: partition-8 }
    - { fstype: fat32, volume: partition-8, preserve: false, type: format, id: format-5 }
    - { device: disk-vda, size: 1073741824, wipe: superblock, flag: '', number: 2, preserve: false, grub_device: false, type: partition, id: partition-9 }
    - { device: disk-vdb, size: 1073741824, wipe: superblock, flag: '', number: 2, preserve: false, grub_device: false, type: partition, id: partition-10 }
    - { device: disk-vda, size: -1, wipe: superblock, flag: '', number: 3, preserve: false, grub_device: false, type: partition, id: partition-11 }
    - { device: disk-vdb, size: -1, wipe: superblock, flag: '', number: 3, preserve: false, grub_device: false, type: partition, id: partition-12 }
    - { name: md0, raidlevel: raid1, devices: [ partition-10, partition-9 ], spare_devices: [], preserve: false, wipe: superblock, type: raid, id: raid-0 }
    - { name: md1, raidlevel: raid1, devices: [ partition-11, partition-12 ], spare_devices: [], preserve: false, wipe: superblock, type: raid, id: raid-1 }
    - { fstype: ext4, volume: raid-0, preserve: false, type: format, id: format-3 }
    - { name: vg0, devices: [ raid-1 ], preserve: false, type: lvm_volgroup, id: lvm_volgroup-0 }
    - { name: lv-0, volgroup: lvm_volgroup-0, size: 10737418240B, wipe: superblock, preserve: false, type: lvm_partition, id: lvm_partition-0 }
    - { fstype: ext4, volume: lvm_partition-0, preserve: false, type: format, id: format-4 }
    - { path: /, device: format-4, type: mount, id: mount-4 }
    - { path: /boot, device: format-3, type: mount, id: mount-3 }
    - { path: /boot/efi, device: format-2, type: mount, id: mount-2 }
    - { path: /boot/efi2, device: format-5, type: mount, id: mount-5 }
    - { name: swap, volgroup: lvm_volgroup-0, size: 1073741824B, wipe: superblock, preserve: false, type: lvm_partition, id: lvm_partition-1 }
    - { fstype: swap, volume: lvm_partition-1, preserve: false, type: format, id: format-6 }
    - { path: '', device: format-6, type: mount, id: mount-6 }
  late-commands:
  - 'echo "ubuntu ALL=(ALL) NOPASSWD:ALL" > /target/etc/sudoers.d/ubuntu-nopw'
  - chmod 440 /target/etc/sudoers.d/ubuntu-nopw
  version: 1

A complete netplan configuration is found in this autoinstall example using two cards in bond.

BIOS boot disk layout

Partition layout needs to be changed when system firmware is BIOS. Partition table type is still GPT, but first partition is a special BIOS boot partition.

storage:
  config:
# Install GRUB in MBR
  - { ptable: gpt, path: /dev/vda, wipe: superblock, preserve: false, name: '', grub_device: true, type: disk, id: disk-vda }
# BIOS boot partition
  - { device: disk-vda, size: 1048576, flag: bios_grub, number: 1, preserve: false, grub_device: false, type: partition, id: partition-0 }
# boot
  - { device: disk-vda, size: 1073741824, wipe: superblock, flag: '', number: 2, preserve: false, grub_device: false, type: partition, id: partition-1 }
  - { fstype: ext4, volume: partition-1, preserve: false, type: format, id: format-1 }
  - { device: disk-vda, size: -1, wipe: superblock, flag: '', number: 3, preserve: false, grub_device: false, type: partition, id: partition-2 }
  - { name: ubuntu-vg, devices: [ partition-2 ], preserve: false, type: lvm_volgroup, id: lvm_volgroup-0 }
  - { name: ubuntu-lv, volgroup: lvm_volgroup-0, size: -1, wipe: superblock, preserve: false, type: lvm_partition, id: lvm_partition-0 }
  - { fstype: ext4, volume: lvm_partition-0, preserve: false, type: format, id: format-2 }
  - { path: /, device: format-2, type: mount, id: mount-2 }
  - { path: /boot, device: format-1, type: mount, id: mount-1 }

SSH access during installation

#cloud-config
chpasswd:
  list:
    - installer:$6$gnqbMUzHhQzpDEw.$.cCNVVDsDfj5Feebh.5O4VbOmib7tyjmeI2ZsFP7VK2kWwgJFbfjvXo3chpeAqCgXWVIW9oNQ/Ag85PR0IsKD/
ssh_authorized_keys:
  - <SSH KEY>
autoinstall:
  identity:
    hostname: jammy-minimal
    password: $6$gnqbMUzHhQzpDEw.$.cCNVVDsDfj5Feebh.5O4VbOmib7tyjmeI2ZsFP7VK2kWwgJFbfjvXo3chpeAqCgXWVIW9oNQ/Ag85PR0IsKD/
    username: ubuntu
  version: 1

The chpasswd and ssh_authorized_keys cloud-init modules configure installer credentials. Be aware, that chpasswd, ssh_authorized_keys and autoinstall are on the same level. Password is ubuntu.

Other interesting features

  • early-commands: a list of shell commands to invoke before probing for block and network devices. The autoinstall config is at /autoinstall.yaml and it will be re-read after early-commands have run.
  • late-commands: make possible to run commands in the target (installed) system using curtin in-target --target=/target -- <SHELL COMMAND> syntax.
  • error-commands: a list of shell commands to run after the installing process has failed. Target system is available at /target (if it is possible) and logs at /var/log/installer.
  • reporting: the installer can be configured to send progress information to local and serial console, rsyslog and even to a webhook.