Extract cidata loading into a standalone omarchy-cidata-load command

The loader now settles udev before probing, so a fast boot cannot miss
the drive and silently drop a headless install into the wizard. All the
files come over in a single cp, and a failed copy removes anything it
already copied and falls back to the wizard: the wizard cleans up only
what it writes itself, so a half-copied ssh.json would otherwise leak
into the interactive install that follows. The command takes an optional
path prefix so tests can run it against a sandbox instead of the live
system.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
David Heinemeier HanssonandClaude Fable 5 committed 2026-08-04 05:56:33 -07:00
1 parent 7e782bb7cf
commit e8a7e3cfce
3 files changed
+62 -33

No files matched your search

+4 -33
View File
@@ -90,40 +90,11 @@ warm_offline_mirror &
warm_pid=$!
trap 'kill "$warm_pid" 2>/dev/null' EXIT
# 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 stands in for the wizard. Copy those files into /root and everything
# downstream runs the ordinary path against ordinary inputs.
#
# 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 we fall back to the wizard.
load_cidata() {
local device="" label mnt=/run/cidata
for label in cidata CIDATA; do
[[ -e /dev/disk/by-label/$label ]] && { device=/dev/disk/by-label/$label; break; }
done
[[ -n $device ]] || return 1
mkdir -p "$mnt"
mount -o ro "$device" "$mnt" || return 1
if [[ -f $mnt/user_configuration.json && -f $mnt/user_credentials.json ]]; then
cp "$mnt"/user_configuration.json "$mnt"/user_credentials.json /root/
for file in user_full_name.txt user_email_address.txt user_encrypt_installation.txt ssh.json; do
[[ -f $mnt/$file ]] && cp "$mnt/$file" /root/
done
umount "$mnt"
return 0
fi
umount "$mnt"
return 1
}
cd /root
if load_cidata; then
# Autoinstall: a cidata drive carrying the configurator's own output files
# stands in for the wizard. omarchy-cidata-load copies them into /root and
# everything downstream runs the ordinary path against ordinary inputs.
if /usr/local/bin/omarchy-cidata-load; then
echo "Autoinstall configuration found on cidata drive; skipping the configurator."
export OMARCHY_UI_INTERACTIVE=no
else
+57
View File
@@ -0,0 +1,57 @@
#!/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 ssh.json; 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 ssh.json would leak into the
# interactive install that follows.
for file in "${files[@]}"; do
rm -f "$dest/${file##*/}"
done
fi
fi
umount "$mnt"
exit $loaded
+1
View File
@@ -36,6 +36,7 @@ file_permissions=(
["/root/.gnupg"]="0:0:700"
["/root/configurator"]="0:0:755"
["/usr/local/bin/choose-mirror"]="0:0:755"
["/usr/local/bin/omarchy-cidata-load"]="0:0:755"
["/usr/local/bin/omarchy-iso-cleanup-disk"]="0:0:755"
["/usr/local/bin/omarchy-install-dashboard"]="0:0:755"
["/usr/local/bin/omarchy-iso-install"]="0:0:755"