#!/bin/bash # # Autoinstall: a drive labeled cidata (the cloud-init NoCloud label, so Proxmox, # libvirt and Packer all know how to attach one) carrying the configurator's own # output files stands in for the wizard. Copy those files into /root and # everything downstream runs the ordinary path against ordinary inputs. # # Exits 0 when an autoinstall drive was loaded and the configurator can be # skipped. The required pair is the same one the orchestrator treats as # mandatory; the rest are optional there too, so don't be stricter here. # Anything less than the pair means this isn't an autoinstall drive, and the # caller falls back to the wizard. # # The optional argument prefixes every path the script touches; tests use it to # run against a sandbox instead of the live system. set -uo pipefail root=${1:-} by_label=$root/dev/disk/by-label dest=$root/root mnt=$root/run/cidata # The by-label symlinks come from udev, and on a fast boot this can run before # device enumeration has finished. Wait for the queue to drain instead of # racing it and silently dropping a headless install into the wizard. udevadm settle 2>/dev/null || true device="" for label in cidata CIDATA; do [[ -e $by_label/$label ]] && { device=$by_label/$label; break; } done [[ -n $device ]] || exit 1 mkdir -p "$mnt" mount -o ro "$device" "$mnt" || exit 1 loaded=1 if [[ -f $mnt/user_configuration.json && -f $mnt/user_credentials.json ]]; then files=("$mnt"/user_configuration.json "$mnt"/user_credentials.json) for file in user_full_name.txt user_email_address.txt user_encrypt_installation.txt authorized_keys tailscale_authkey; do [[ -f $mnt/$file ]] && files+=("$mnt/$file") done if cp "${files[@]}" "$dest"/; then loaded=0 else # A partial copy must not leave files behind: the wizard cleans up only # what it writes itself, so a half-copied authorized_keys would leak into # the interactive install that follows. for file in "${files[@]}"; do rm -f "$dest/${file##*/}" done fi fi umount "$mnt" exit $loaded