Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Adurol/2eb8d23c11bd1c714f16ebfdbe19f415 to your computer and use it in GitHub Desktop.
Save Adurol/2eb8d23c11bd1c714f16ebfdbe19f415 to your computer and use it in GitHub Desktop.
Automated local install with cloud-init for Ubuntu Server

Automated local install with cloud-init for Ubuntu Server

TLDR: Plug in a usb drive to install Ubuntu Server automagical.

Requirements

A good start is the autoinstall file that the server installer created at /var/log/installer/autoinstall-user-data. For more information see Resources.

Seed image creation

Create an image file to hold the configuration:

truncate --size 2M ubuntu-server-cloud-init.img
mkfs.vfat -n cidata ubuntu-server-cloud-init.img

Create empty meta-data file:

touch meta-data

I'm not in the know what content meta-data should include. For me an empty file worked; your mileage may vary.

Copy the configuration to the seed image:

mcopy -oi ubuntu-server-cloud-init.img user-data meta-data ::

The seed image is completed.

Prepare USB Drive

Create a Ventoy USB Drive

Please see the official documentation for how to create a Ventoy USB drive.

The created drive will be have (at least) 2 partitions. One partition with the boot loader (VTOYEFI) and one partition was formatted per default with exFAT to hold iso images ("iso partition").

Copy files

Create the folder /iso on the iso partition and place the ubuntu iso image(s) inside it.

Create the folder /persistence on the iso partition and copy the ubuntu-server-cloud-init.img to /persistence/ubuntu-server-cloud-init.img

Configuring Ventoy

Create the folder /ventoy on the iso partition and have a /ventoy/ventoy.json file. This is the main config for Ventoy. Take care to have valid JSON, use an online validation tool if unsure.

Configure Ventoy to search only in /iso for iso images so it doesn't clutter the menu with additional files. (See documentation for more options.)

  "control": [
    { "VTOY_DEFAULT_SEARCH_ROOT": "/iso" }
  ]

To pass along the seed image to the ubuntu server image, use Persistence Plugin of Ventoy and at the following to the Ventoy configuration: (Feel free to adjust as needed and pay attention to the nesting!)

  "persistence": [
    {
      "image": "/iso/ubuntu-**.**-live-server-amd64.iso",
      "backend": "/persistence/ubuntu-server-cloud-init.img"
    },
    {
      "image": "/iso/ubuntu-**.**.*-live-server-amd64.iso",
      "backend": "/persistence/ubuntu-server-cloud-init.img"
    }
  ]

Use Autoinstall

Boot the ubuntu server image with Ventoy and select boot with persistence image in the prompt.

Should the installer interface pop up, don't interact with it and just let it do it's thing. Wait until the the storage configuration. That will have to be done manually if no storage: is defined. For every section listed in interactive-sections: the graphical interface will also be used.

Fully noninteractive autoinstall

WARNING: Total data loss possible! Use with care!

The installer will not be asking for confirmation to format the disk!

To use fully noninteractive autoinstall:

  • provide a storage: object in the user-data config
  • set autoinstall in the kernel command line

Ventoy provides a Boot Conf Replace Plugin that makes it possible to provide a custom configuration with autoinstall already set. (Take also a look at the original /boot/grub/grub.cfg within the iso.)

Create a /ventoy/ubuntu-server-autoinstall-grub.cfg with the following content:

# ubuntu defaults
set menu_color_normal=white/black
set menu_color_highlight=black/light-gray

# boot second menu entry after timout
set default=1
set timeout=5

menuentry "Install Ubuntu Server" {
  set gfxpayload=keep
  linux /casper/vmlinuz  ---
  initrd  /casper/initrd
}
menuentry "Install Ubuntu Server (Autoinstall)" {
  set gfxpayload=keep
  linux /casper/vmlinuz  autoinstall  ---
  initrd  /casper/initrd
}

# commonly available beginning with the second point release for the lts series
menuentry "Install Ubuntu Server with the HWE kernel" {
  set gfxpayload=keep
  linux /casper/hwe-vmlinuz  ---
  initrd  /casper/hwe-initrd
}
menuentry "Install Ubuntu Server with the HWE kernel (Autoinstall)" {
  set gfxpayload=keep
  linux /casper/hwe-vmlinuz  autoinstall  ---
  initrd  /casper/hwe-initrd
}

Add to the ventoy configuration:

  "conf_replace": [
    {
      "iso": "/iso/ubuntu-**.**-live-server-amd64.iso",
      "org": "/boot/grub/grub.cfg",
      "new": "/ventoy/ubuntu-server-autoinstall-grub.cfg"
    },
    {
      "iso": "/iso/ubuntu-**.**.*-live-server-amd64.iso",
      "org": "/boot/grub/grub.cfg",
      "new": "/ventoy/ubuntu-server-autoinstall-grub.cfg"
    }
  ]

Boot ubuntu server image with Ventoy.

Resources

# ubuntu defaults
set menu_color_normal=white/black
set menu_color_highlight=black/light-gray
# boot second menu entry after timout
set default=1
set timeout=5
menuentry "Install Ubuntu Server" {
set gfxpayload=keep
linux /casper/vmlinuz ---
initrd /casper/initrd
}
menuentry "Install Ubuntu Server (Autoinstall)" {
set gfxpayload=keep
linux /casper/vmlinuz autoinstall ---
initrd /casper/initrd
}
# commonly available beginning with the second point release for the lts series
menuentry "Install Ubuntu Server with the HWE kernel" {
set gfxpayload=keep
linux /casper/hwe-vmlinuz ---
initrd /casper/hwe-initrd
}
menuentry "Install Ubuntu Server with the HWE kernel (Autoinstall)" {
set gfxpayload=keep
linux /casper/hwe-vmlinuz autoinstall ---
initrd /casper/hwe-initrd
}
#cloud-config
autoinstall:
version: 1
# netplan formatted network configuration
network:
version: 2
ethernets:
enp0s31f6:
dhcp4: true
proxy: null # don't use a proxy
refresh-installer: # update installer first
update: true
# initial user setup
identity:
hostname: hostname
realname: Username
username: username
password: $crypted_pass
# ssh setup
ssh:
install-server: true # install and start OpenSSH server
authorized-keys: # public key for ansible
- §pub-key
allow-pw: true # allow login via password
# locale setup
keyboard:
layout: 'de'
variant: 'nodeadkeys'
toggle: null
locale: de_DE.UTF-8
timezone: Europe/Berlin
# curtin formatted drive configuration
storage:
swap:
size: 0 # don't use swap
config:
# the drive to use
- id: disk-sda
type: disk
ptable: gpt
serial: Patriot_Burst_B9780789165300068560
path: /dev/sda
wipe: superblock-recursive
preserve: false
name: ''
grub_device: false
# efi boot partition
- id: efi-partition
device: disk-sda
type: partition
number: 1
size: 512M
wipe: superblock
flag: boot
preserve: false
grub_device: true
- id: efi-filesystem
volume: efi-partition
type: format
fstype: fat32
preserve: false
- id: efi-mountpoint
device: efi-filesystem
type: mount
path: /boot/efi
# btrfs system partition
- id: btrfs-partition
device: disk-sda
type: partition
number: 2
size: -1 # use the remaining free space
wipe: superblock
preserve: false
grub_device: false
- id: btrfs-filesystem
volume: btrfs-partition
type: format
fstype: btrfs
extra_options: ['--csum', 'xxhash', '--data', 'single', '--metadata', 'dup'] # needs hwe-kernel for ubuntu 20.04
preserve: false
- id: btrfs-mountpoint
device: btrfs-filesystem
type: mount
path: /
options: 'defaults,lazytime,compress-force=zstd:1,discard=async'
# configure apt package sources
apt:
geoip: false # don't ask the geoip server
preserve_sources_list: false
primary:
- arches:
- amd64
- i386
uri: 'http://de.archive.ubuntu.com/ubuntu'
- arches:
- default
uri: 'http://ports.ubuntu.com/ubuntu-ports'
# configure packages
packages: # install additional packages
- micro # a terminal editor that doesn't suck
- python3 # needed for ansible
- tmux # terminal multiplexer
byobu_by_default: disable # don't use byobu (use tmux)
updates: all # install not only security updates
# reboot after install
power_state:
delay: 10 # in seconds, for no delay use 'now'
mode: reboot
{
"control": [
{ "VTOY_DEFAULT_SEARCH_ROOT": "/iso" }
],
"persistence": [
{
"image": "/iso/ubuntu-**.**-live-server-amd64.iso",
"backend": "/persistence/ubuntu-server-cloud-init.img"
},
{
"image": "/iso/ubuntu-**.**.*-live-server-amd64.iso",
"backend": "/persistence/ubuntu-server-cloud-init.img"
}
],
"conf_replace": [
{
"iso": "/iso/ubuntu-**.**-live-server-amd64.iso",
"org": "/boot/grub/grub.cfg",
"new": "/ventoy/ubuntu-server-autoinstall-grub.cfg"
},
{
"iso": "/iso/ubuntu-**.**.*-live-server-amd64.iso",
"org": "/boot/grub/grub.cfg",
"new": "/ventoy/ubuntu-server-autoinstall-grub.cfg"
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment