Autoinstall: script for wallpaper with info during deploy

I don’t know how many would use this but I haven’t seen much of these posts so I thought I share it. Someone might want it.

prereq: knowledge of how to build your custom iso with autoinstall.

I made this script called pre-install-wallpaper.sh that runs from early-commands section in autoinstall. The script will draw some infotext onto a wallpaper image (like model, ip, os version, kernel, asset tag, hostname)

the file cdrom/files/ubuntu-deployment.png is a custom wallpaper that replaces the default wallpaper during the installation.

#!/bin/bash
# updating repos
apt update
# dependencies
sudo apt install -y libglib2.0-dev-bin 
sudo apt install -y imagemagick # for writing the image
sudo apt install -y curl # for grabbing info about network
# All variables
vKernel=$(uname -r)
vUbuntuversion=$(lsb_release -d | cut -d' ' -f2)
vModel=$(sudo dmidecode -s system-product-name)
vIp=$(curl ipinfo.io | grep "ip" | cut -d: -f2 | head -n1 | cut -c3-16 | sed 's/"//g')
vOrg=$(curl ipinfo.io | grep "org" | cut -d: -f2 | sed 's/,//g'| sed 's/"//g')
vHostName=$(grep -oP '(?<=hostname: ).*' /autoinstall.yaml)
vAsset_tag=$(dmidecode | grep -A 6 "Asset Tag" | grep -m 2 "Asset Tag" | tail -n 1 | awk -F ': ' '{print $2}')
#
# Create Wallpaper image
convert /cdrom/files/ubuntu-deployment.png -pointsize 40 -fill white -draw "text 1450,270 ' ${vHostName} '" \
-pointsize 15 -fill white -draw "text 1450,310 'Model: ${vModel}'" \
-pointsize 15 -fill white -draw "text 1450,330 'Asset: ${vAsset_tag}'" \
-pointsize 15 -fill white -draw "text 1450,350 'OS: Ubuntu ${vUbuntuversion} (${vKernel})'" \
-pointsize 15 -fill white -draw "text 1450,370 'IPv4: ${vIp}'" \
-pointsize 15 -fill white -draw "text 1450,390 'Net:${vOrg}'" \
-pointsize 15 -fill white -draw "text 1450,230 'System:'" /usr/share/backgrounds/warty-final-ubuntu.png

so in my yaml file it would look like this

  # EARLY COMMANDS
  early-commands:
    - bash /cdrom/nocloud/scripts/pre-install-wallpaper.sh

I hope this helps someone.

1 Like

Hi,

thank you for sharing your tips. I’m also interested in you post regarding dynamically set the hostname ( Autoinstall: script for setting hostname based on serialnumber )…..

I’m quite new on this subject (autoinstall). I managed to use autoinstall.yaml for a quite simple case.

Now I would like to use early-commands as you do…..but don’t know where to store my scripts so that they are accessible during installation process. I tried to store them in the root folder of the iso…but they seem to be not visible in early-commands

I’m currently using the script from https://www.baeldung.com/linux/ubuntu-autoinstall-no-screen-keyboard to create my iso file with the autoinstall.yaml file

could you share with us your procedure creating your iso and how you create /cdrom/nocloud/scripts/ to store your scripts please?

thank you for your help

Gerald

1 Like

Ok, I tried and found how to do it :

  • copy script at the root of iso file
  • in autoinstall.yaml, the script is found in /cdrom
1 Like

script for building custom Ubuntu iso

#!/bin/bash
# from original source https://raw.githubusercontent.com/covertsh/ubuntu-autoinstall-generator/main/ubuntu-autoinstall-generator.sh
# 2024-04-26 - added support for 24.04 LTS (Magnus Bergdahl)
#
#
set -Eeuo pipefail
 
function cleanup() {
        trap - SIGINT SIGTERM ERR EXIT
        if [ -n "${tmpdir+x}" ]; then
                rm -rf "$tmpdir"
                log "🚽 Deleted temporary working directory $tmpdir"
        fi
}
 
trap cleanup SIGINT SIGTERM ERR EXIT
script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd -P)
[[ ! -x "$(command -v date)" ]] && echo "💥 date command not found." && exit 1
today=$(date +"%Y-%m-%d")
 
function log() {
        echo >&2 -e "[$(date +"%Y-%m-%d %H:%M:%S")] ${1-}"
}
 
function die() {
        local msg=$1
        local code=${2-1} # Bash parameter expansion - default exit status 1. See https://wiki.bash-hackers.org/syntax/pe#use_a_default_value
        log "$msg"
        exit "$code"
}
 
usage() {
        cat <<EOF
Usage: $(basename "${BASH_SOURCE[0]}") [-h] [-v] [-a] [-e] [-u user-data-file] [-m meta-data-file] [-k] [-c] [-r] [-s source-iso-file] [-d destination-iso-file]
 
💁 This script will create fully-automated Ubuntu 24.04 Noble Numbat installation media.
 
Available options:
 
-h, --help              Print this help and exit
-v, --verbose           Print script debug info
-a, --all-in-one        Bake user-data and meta-data into the generated ISO. By default you will
                        need to boot systems with a CIDATA volume attached containing your
                        autoinstall user-data and meta-data files.
                        For more information see: https://ubuntu.com/server/docs/install/autoinstall-quickstart
-e, --use-hwe-kernel    Force the generated ISO to boot using the hardware enablement (HWE) kernel. Not supported
                        by early Ubuntu 20.04 release ISOs.
-u, --user-data         Path to user-data file. Required if using -a
-u2, --user-data	 Path to 2nd user-data file. Required if using -a
-m, --meta-data         Path to meta-data file. Will be an empty file if not specified and using -a
-k, --no-verify         Disable GPG verification of the source ISO file. By default SHA256SUMS-$today and
                        SHA256SUMS-$today.gpg in ${script_dir} will be used to verify the authenticity and integrity
                        of the source ISO file. If they are not present the latest daily SHA256SUMS will be
                        downloaded and saved in ${script_dir}. The Ubuntu signing key will be downloaded and
                        saved in a new keyring in ${script_dir}
-c, --no-md5            Disable MD5 checksum on boot
-r, --use-release-iso   Use the current release ISO instead of the daily ISO. The file will be used if it already
                        exists.
-s, --source            Source ISO file. By default the latest daily ISO for Ubuntu 24.04 daily build will be downloaded
                        and saved as ${script_dir}/ubuntu-original-$today.iso
                        That file will be used by default if it already exists.
-d, --destination       Destination ISO file. By default ${script_dir}/ubuntu-autoinstall-$today.iso will be
                        created, overwriting any existing file.
EOF
        exit
}
 
function parse_params() {
        # default values of variables set from params
        user_data_file=''
        user_data_file2=''
        meta_data_file=''
        download_url="https://mirror.bahnhof.net/ubuntu-releases/24.04.4"
        download_iso="ubuntu-24.04.4-desktop-amd64.iso"
        original_iso="ubuntu-original-$today.iso"
        source_iso="${script_dir}/${original_iso}"
        destination_iso="${script_dir}/ubuntu-autoinstall-$today.iso"
        sha_suffix="${today}"
        gpg_verify=1
        all_in_one=0
        use_hwe_kernel=0
        md5_checksum=1
        use_release_iso=0
 
        while :; do
                case "${1-}" in
                -h | --help) usage ;;
                -v | --verbose) set -x ;;
                -a | --all-in-one) all_in_one=1 ;;
                -e | --use-hwe-kernel) use_hwe_kernel=1 ;;
                -c | --no-md5) md5_checksum=0 ;;
                -k | --no-verify) gpg_verify=0 ;;
                -r | --use-release-iso) use_release_iso=1 ;;
                -u | --user-data)
                        user_data_file="${2-}"
                        shift
                        ;;
                -u2 | --user-data)
                        user_data_file2="${2-}"
                        shift
                        ;;       
                -s | --source)
                        source_iso="${2-}"
                        shift
                        ;;
                -d | --destination)
                        destination_iso="${2-}"
                        shift
                        ;;
                -m | --meta-data)
                        meta_data_file="${2-}"
                        shift
                        ;;
                -?*) die "Unknown option: $1" ;;
                *) break ;;
                esac
                shift
        done
 
        log "👶 Starting up..."
 
        # check required params and arguments
        if [ ${all_in_one} -ne 0 ]; then
                [[ -z "${user_data_file}" ]] && die "💥 user-data file was not specified."
                [[ ! -f "$user_data_file" ]] && die "💥 user-data file could not be found."
                [[ -n "${meta_data_file}" ]] && [[ ! -f "$meta_data_file" ]] && die "💥 meta-data file could not be found."
        fi
 
        if [ "${source_iso}" != "${script_dir}/${original_iso}" ]; then
                [[ ! -f "${source_iso}" ]] && die "💥 Source ISO file could not be found."
        fi
 
        if [ "${use_release_iso}" -eq 1 ]; then
                download_url="https://releases.ubuntu.com/24.04"
                log "🔎 Checking for current release..."
                download_iso=$(curl -sSL "${download_url}" | grep -oP 'ubuntu\-\24.04.4\-\desktop-amd64\.iso' | head -n 1)
                original_iso="${download_iso}"
                source_iso="${script_dir}/${download_iso}"
                current_release=$(echo "${download_iso}" | cut -f2 -d-)
                sha_suffix="${current_release}"
                log "💿 Current release is ${current_release}"
        fi
 
        destination_iso=$(realpath "${destination_iso}")
        source_iso=$(realpath "${source_iso}")
 
        return 0
}
 
ubuntu_gpg_key_id="843938DF228D22F7B3742BC0D94AA3F0EFE21092"
 
parse_params "$@"
 
tmpdir=$(mktemp -d)
 
if [[ ! "$tmpdir" || ! -d "$tmpdir" ]]; then
        die "💥 Could not create temporary working directory."
else
        log "📁 Created temporary working directory $tmpdir"
fi
 
log "🔎 Checking for required utilities..."
[[ ! -x "$(command -v xorriso)" ]] && die "💥 xorriso is not installed. On Ubuntu, install  the 'xorriso' package."
[[ ! -x "$(command -v sed)" ]] && die "💥 sed is not installed. On Ubuntu, install the 'sed' package."
[[ ! -x "$(command -v curl)" ]] && die "💥 curl is not installed. On Ubuntu, install the 'curl' package."
[[ ! -x "$(command -v gpg)" ]] && die "💥 gpg is not installed. On Ubuntu, install the 'gpg' package."
[[ ! -f "/usr/lib/ISOLINUX/isohdpfx.bin" ]] && die "💥 isolinux is not installed. On Ubuntu, install the 'isolinux' package."
log "👍 All required utilities are installed."
 
if [ ! -f "${source_iso}" ]; then
        log "🌎 Downloading ISO image for Ubuntu 24.04.4 Noble Numbat..."
        curl -NsSL "${download_url}/${download_iso}" -o "${source_iso}"
        log "👍 Downloaded and saved to ${source_iso}"
else
        log "☑️ Using existing ${source_iso} file."
        if [ ${gpg_verify} -eq 1 ]; then
                if [ "${source_iso}" != "${script_dir}/${original_iso}" ]; then
                        log "⚠️ Automatic GPG verification is enabled. If the source ISO file is not the latest daily or release image, verification will fail!"
                fi
        fi
fi
 
if [ ${gpg_verify} -eq 1 ]; then
        if [ ! -f "${script_dir}/SHA256SUMS-${sha_suffix}" ]; then
                log "🌎 Downloading SHA256SUMS & SHA256SUMS.gpg files..."
                curl -NsSL "${download_url}/SHA256SUMS" -o "${script_dir}/SHA256SUMS-${sha_suffix}"
                curl -NsSL "${download_url}/SHA256SUMS.gpg" -o "${script_dir}/SHA256SUMS-${sha_suffix}.gpg"
        else
                log "☑️ Using existing SHA256SUMS-${sha_suffix} & SHA256SUMS-${sha_suffix}.gpg files."
        fi
 
        if [ ! -f "${script_dir}/${ubuntu_gpg_key_id}.keyring" ]; then
                log "🌎 Downloading and saving Ubuntu signing key..."
                gpg -q --no-default-keyring --keyring "${script_dir}/${ubuntu_gpg_key_id}.keyring" --keyserver "hkp://keyserver.ubuntu.com" --recv-keys "${ubuntu_gpg_key_id}"
                log "👍 Downloaded and saved to ${script_dir}/${ubuntu_gpg_key_id}.keyring"
        else
                log "☑️ Using existing Ubuntu signing key saved in ${script_dir}/${ubuntu_gpg_key_id}.keyring"
        fi
 
        log "🔐 Verifying ${source_iso} integrity and authenticity..."
        gpg -q --keyring "${script_dir}/${ubuntu_gpg_key_id}.keyring" --verify "${script_dir}/SHA256SUMS-${sha_suffix}.gpg" "${script_dir}/SHA256SUMS-${sha_suffix}" 2>/dev/null
        if [ $? -ne 0 ]; then
                rm -f "${script_dir}/${ubuntu_gpg_key_id}.keyring~"
                die "👿 Verification of SHA256SUMS signature failed."
        fi
 
        rm -f "${script_dir}/${ubuntu_gpg_key_id}.keyring~"
        digest=$(sha256sum "${source_iso}" | cut -f1 -d ' ')
        set +e
        grep -Fq "$digest" "${script_dir}/SHA256SUMS-${sha_suffix}"
        if [ $? -eq 0 ]; then
                log "👍 Verification succeeded."
                set -e
        else
                die "👿 Verification of ISO digest failed."
        fi
else
        log "🤞 Skipping verification of source ISO."
fi
log "🔧 Extracting ISO image..."
7z -y x ${source_iso} -o$tmpdir #&>/dev/null
#xorriso -osirrox on -indev "${source_iso}" -extract / "$tmpdir" &>/dev/null
chmod -R u+w "$tmpdir"
# rm -rf "$tmpdir/"'[BOOT]'
# Move BOOT directory outside, since this is not needed in the final iso.
mv --force "$tmpdir/"'[BOOT]' /tmp/BOOT
log "👍 Extracted to $tmpdir"
 
if [ ${use_hwe_kernel} -eq 1 ]; then
        if grep -q "hwe-vmlinuz" "$tmpdir/boot/grub/grub.cfg"; then
                log "☑️ Destination ISO will use HWE kernel."
                sed -i -e 's|/casper/vmlinuz|/casper/hwe-vmlinuz|g' "$tmpdir/boot/grub/grub.cfg"
                sed -i -e 's|/casper/initrd|/casper/hwe-initrd|g' "$tmpdir/boot/grub/grub.cfg"
                sed -i -e 's|/casper/vmlinuz|/casper/hwe-vmlinuz|g' "$tmpdir/boot/grub/loopback.cfg"
                sed -i -e 's|/casper/initrd|/casper/hwe-initrd|g' "$tmpdir/boot/grub/loopback.cfg"
        else
                log "⚠️ This source ISO does not support the HWE kernel. Proceeding with the regular kernel."
        fi
fi
 
log "🧩 Adding autoinstall parameter to kernel command line..."
if [ ${all_in_one} -eq 1 ]; then
    log "🧩 Adding user-data and meta-data files..."
    mkdir "$tmpdir/nocloud"
    mkdir "$tmpdir/nocloud2"
    cp "$user_data_file" "$tmpdir/nocloud/user-data"
    cp "$user_data_file2" "$tmpdir/nocloud2/user-data"
    log "🧩 Adding packages files..."
    cp -a "$HOME/ubuntu-desktop-config/packages/" "$tmpdir"
    cp -a "$HOME/ubuntu-desktop-config/scripts/" "$tmpdir/nocloud"
    cp -a "$HOME/ubuntu-desktop-config/scripts2/" "$tmpdir/nocloud2"

    if [ -n "${meta_data_file}" ]; then
        cp "$meta_data_file" "$tmpdir/nocloud/meta-data"
    else
        touch "$tmpdir/nocloud/meta-data"
        touch "$tmpdir/nocloud2/meta-data"
    fi
 
    # Find the position to insert the new menuentry
    menu_pos=13
 
    # Create a new menuentry with autoinstall parameter and nocloud data source
    new_entry='menuentry "Ubuntu 24.04 LTS encrypted install" {\n\tset gfxpayload=keep\n\tlinux /casper/vmlinuz layerfs-path=minimal.standard.live.squashfs  autoinstall   ds=nocloud\\;s=/cdrom/nocloud/ --- quiet splash\n\tinitrd /casper/initrd\n}'
 
    # Insert the new menuentry into grub.cfg
    sed -i "${menu_pos}i ${new_entry}" "$tmpdir/boot/grub/grub.cfg"
 
    # Insert the same menuentry into loopback.cfg
    sed -i "${menu_pos}i ${new_entry}" "$tmpdir/boot/grub/loopback.cfg"
 
    log "👍 Added data and configured kernel command line for ENCRYPTED install."
    
        # Find the position to insert the new menuentry
    menu_pos=18
 
    # Create a new menuentry with autoinstall parameter and nocloud data source
    new_entry='menuentry "Ubuntu 24.04 LTS interactive install" {\n\tset gfxpayload=keep\n\tlinux /casper/vmlinuz layerfs-path=minimal.standard.live.squashfs  autoinstall   ds=nocloud\\;s=/cdrom/nocloud2/ --- quiet splash\n\tinitrd /casper/initrd\n}'
 
    # Insert the new menuentry into grub.cfg
    sed -i "${menu_pos}i ${new_entry}" "$tmpdir/boot/grub/grub.cfg"
 
    # Insert the same menuentry into loopback.cfg
    sed -i "${menu_pos}i ${new_entry}" "$tmpdir/boot/grub/loopback.cfg"
 
    log "👍 Added data and configured kernel command line for INTERACTIVE install."
fi
 
 
 
if [ ${md5_checksum} -eq 1 ]; then
        log "👷 Updating $tmpdir/md5sum.txt with hashes of modified files..."
        md5=$(md5sum "$tmpdir/boot/grub/grub.cfg" | cut -f1 -d ' ')
        sed -i -e 's,^.*[ ] ./boot/grub/grub.cfg,'"$md5"'  ./boot/grub/grub.cfg,' "$tmpdir/md5sum.txt"
        md5=$(md5sum "$tmpdir/boot/grub/loopback.cfg" | cut -f1 -d ' ')
        sed -i -e 's,^.*[ ] ./boot/grub/loopback.cfg,'"$md5"'  ./boot/grub/loopback.cfg,' "$tmpdir/md5sum.txt"
        log "👍 Updated hashes."
else
        log "🗑️ Clearing MD5 hashes..."
        echo > "$tmpdir/md5sum.txt"
        log "👍 Cleared hashes."
fi
 
log "📦 Repackaging extracted files into an ISO image..."
cd "$tmpdir"
xorriso -as mkisofs -r \
  -V "Ubuntu 24.04.4 LTS amd64" \
  -o "${destination_iso}" \
  --grub2-mbr /tmp/BOOT/1-Boot-NoEmul.img \
  -partition_offset 16 \
  --mbr-force-bootable \
  -append_partition 2 0xef /tmp/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 \
  "${tmpdir}" &>/dev/null
rm -rf /tmp/BOOT
log "👍 Repackaged into ${destination_iso}"
 
die "✅ Completed." 0

I use this script to download and build my iso.
I place it in a folder I called ubuntu-desktop-config and have subfolders packages, scripts and scripts2 under it.
place two files under ubuntu-desktop-config , called user-data and user-data2 (see below)

folders:
ubuntu-desktop-config/scripts (scripts for luks encrypted zero touch install)
ubuntu-desktop-config/scripts2 (scripts for semi-interactive non-encrypted install)

files:
ubuntu-desktop-config/user-data (the autoinstall-file in yaml-format for luks encrypted zero touch install)
ubuntu-desktop-config/user-data (the autoinstall-file in yaml-format for semi-interactive non-encrypted install
ubuntu-desktop-config/ubuntu-autoinstall-generator.sh (this script above)

command:
ubuntu-autoinstall-generator.sh -a -u user-data -u2 user-data2

This will download and original iso as file name as ubuntu-original-.iso and then after if all is well create a custom iso named ubuntu-autoinstall-.

You might wanna change server that it downloads from as I have a swedish one in there.

I hope this helps.

1 Like