feat(aegis): add ARM image bootstrap workflow

This commit is contained in:
Fabio Scotto di Santolo
2026-09-04 23:03:50 +02:00
parent cb88e95385
commit 46ae536570
5 changed files with 239 additions and 41 deletions

View File

@@ -1,12 +1,43 @@
# Bootstrap monouso per Fedora CoreOS su Aegis.
# Sostituire la chiave SSH prima di generare Ignition con butane --strict.
# One-time bootstrap for Fedora CoreOS on Aegis (Raspberry Pi 4).
# Generate only: ./generate-aegis-ign.sh
# Generate and write an SD card: ./generate-aegis-ign.sh --write IMAGE DEVICE
# The write mode uses arm-image-installer with the RPi4 target and embeds
# config.ign; it prompts for Wi-Fi credentials unless supplied through its
# WIFI_SSID and WIFI_PASS environment variables.
# For WiFi, the UEFI 'System Table Selection' must be DeviceTree (Esc at boot).
variant: fcos
version: 1.6.0
passwd:
users:
- name: core
- name: pi
password_hash: "$6$bNDsU0XC5BxNJS5U$ENDGpdOUPJM3wcXBgNESCQkOqqQ9gN72/xEQoJsAI6QdsaY6mD4G5DBVIv7nHwHQOP35IH1oGRl.Uy3R2iUYQ1"
groups:
- wheel
ssh_authorized_keys:
- "ssh-ed25519 CHANGEME_AEGIS_SSH_PUBLIC_KEY"
- "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINrIxXjA3ffPwziKGR5gzc4gAoBehQPlnEMcXF4Wl0ZS ikaros"
systemd:
units:
- name: sshd.service
enabled: true
- name: rpm-ostree-install-wifi.service
enabled: true
contents: |
[Unit]
Description=Layer WiFi packages (driver, firmware, NetworkManager-wifi)
Wants=network-online.target
After=network-online.target
Before=zincati.service
ConditionPathExists=!/var/lib/%N.stamp
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/rpm-ostree install -y --allow-inactive NetworkManager-wifi NetworkManager-wwan wpa_supplicant wireless-regdb iw brcmfmac-firmware
ExecStart=/bin/touch /var/lib/%N.stamp
ExecStart=/bin/systemctl --no-block reboot
[Install]
WantedBy=multi-user.target
storage:
files:
- path: /etc/hostname
@@ -14,3 +45,19 @@ storage:
contents:
inline: |
aegis
- path: /etc/sysctl.d/99-ip-forward.conf
mode: 0644
contents:
inline: |
net.ipv4.ip_forward = 1
- path: /etc/hosts
mode: 0644
overwrite: true
contents:
inline: |
127.0.0.1 localhost
::1 localhost
192.168.0.1 aegis
links:
- path: /etc/localtime
target: ../usr/share/zoneinfo/Europe/Rome

View File

@@ -0,0 +1,147 @@
#!/usr/bin/env sh
set -eu
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname "$0")" && pwd)
BUTANE_IMAGE=${BUTANE_IMAGE:-quay.io/coreos/butane:release}
BUTANE_SOURCE=${BUTANE_SOURCE:-"$SCRIPT_DIR/aegis.bu"}
IGNITION_OUTPUT=${IGNITION_OUTPUT:-"$SCRIPT_DIR/config.ign"}
SSH_PUBLIC_KEY=${SSH_PUBLIC_KEY:-"$HOME/.ssh/id_ed25519.pub"}
WIFI_SECURITY=${WIFI_SECURITY:-wpa-psk}
usage() {
cat <<'USAGE'
Usage:
generate-aegis-ign.sh
generate-aegis-ign.sh --write IMAGE DEVICE
Environment overrides:
BUTANE_IMAGE Butane container image (default: quay.io/coreos/butane:release)
BUTANE_SOURCE Butane source path (default: aegis.bu beside this script)
IGNITION_OUTPUT Ignition output path (default: config.ign beside this script)
SSH_PUBLIC_KEY SSH public key passed to arm-image-installer
WIFI_SSID Wi-Fi SSID; prompted if unset in --write mode
WIFI_PASS Wi-Fi password; prompted if unset in --write mode
WIFI_SECURITY Wi-Fi security type (default: wpa-psk)
USAGE
}
require_command() {
if ! command -v "$1" >/dev/null 2>&1; then
printf 'Error: required command not found: %s\n' "$1" >&2
exit 1
fi
}
read_required() {
prompt=$1
value=$2
if [ -z "$value" ]; then
printf '%s' "$prompt" >&2
IFS= read -r value
fi
if [ -z "$value" ]; then
printf '%s\n' 'Error: a value is required.' >&2
exit 1
fi
printf '%s' "$value"
}
read_secret() {
value=$1
if [ -z "$value" ]; then
printf '%s' 'Wi-Fi password: ' >&2
stty -echo
IFS= read -r value
stty echo
printf '\n' >&2
fi
if [ -z "$value" ]; then
printf '%s\n' 'Error: a value is required.' >&2
exit 1
fi
printf '%s' "$value"
}
write_image=false
case $# in
0)
;;
3)
if [ "$1" != '--write' ]; then
usage >&2
exit 2
fi
write_image=true
IMAGE=$2
DEVICE=$3
;;
*)
usage >&2
exit 2
;;
esac
require_command podman
if [ ! -f "$BUTANE_SOURCE" ]; then
printf 'Error: Butane source not found: %s\n' "$BUTANE_SOURCE" >&2
exit 1
fi
OUTPUT_DIR=$(dirname "$IGNITION_OUTPUT")
if [ ! -d "$OUTPUT_DIR" ]; then
printf 'Error: output directory not found: %s\n' "$OUTPUT_DIR" >&2
exit 1
fi
umask 077
TEMP_OUTPUT=$(mktemp "$OUTPUT_DIR/.config.ign.XXXXXX")
trap 'rm -f "$TEMP_OUTPUT"' EXIT HUP INT TERM
podman run --rm -i "$BUTANE_IMAGE" --strict < "$BUTANE_SOURCE" > "$TEMP_OUTPUT"
mv "$TEMP_OUTPUT" "$IGNITION_OUTPUT"
trap - EXIT HUP INT TERM
printf 'Generated Ignition config: %s\n' "$IGNITION_OUTPUT"
if [ "$write_image" = false ]; then
exit 0
fi
if [ ! -f "$IMAGE" ]; then
printf 'Error: image not found: %s\n' "$IMAGE" >&2
exit 1
fi
if [ ! -b "$DEVICE" ]; then
printf 'Error: target is not a block device: %s\n' "$DEVICE" >&2
exit 1
fi
if [ ! -f "$SSH_PUBLIC_KEY" ]; then
printf 'Error: SSH public key not found: %s\n' "$SSH_PUBLIC_KEY" >&2
exit 1
fi
require_command arm-image-installer
WIFI_SSID=$(read_required 'Wi-Fi SSID: ' "${WIFI_SSID:-}")
WIFI_PASS=$(read_secret "${WIFI_PASS:-}")
printf 'Writing %s to %s.\n' "$IMAGE" "$DEVICE" >&2
sudo arm-image-installer \
--image="$IMAGE" \
--target=rpi4 \
--media="$DEVICE" \
--ignition="$IGNITION_OUTPUT" \
--addkey="$SSH_PUBLIC_KEY" \
--resizefs \
--wifi-ssid="$WIFI_SSID" \
--wifi-pass="$WIFI_PASS" \
--wifi-security="$WIFI_SECURITY"

View File

@@ -11,6 +11,7 @@ fedora_desktop_packages:
# Fedora equivalents of the development/tooling packages previously pulled by
# the Void desktop profile.
- 7zip
- arm-image-installer
- nodejs-bash-language-server
- bluez
- bridge-utils

View File

@@ -1,7 +1,7 @@
---
ansible_host: aegis
ansible_connection: ssh
ansible_user: core
ansible_user: pi
ansible_become: true
ansible_python_interpreter: /usr/bin/python3

View File

@@ -1,37 +1,40 @@
$ANSIBLE_VAULT;1.1;AES256
36346638633530653262306466326434346237313965643039643837623233313037363163346338
3165386461353334393464616362333033613231313865340a313731623439626633303566333239
63363166666663376365613034643663373937613162643935366333313438373365346539663161
6663343762336130350a306336613962353931306230363564626538346163623936363064383964
61333734633635326630383339306539643537316665666666643533333364613030613265313032
62643363383464303836376266633962313666396630313361303039343133316237643164616666
30376433323330363033643231643861383234336362383432633665313566336537633631303133
66656363613165333666383432623435626339666364643936653037663839643262393664653564
37373465373663376537616532656434316435623734656265363536336333633537626435303635
65623036613631386464646335653862396232326163623130396133643935363135393934333638
37626664353131613336353130366566383238623031636366333036643161626564613965613233
63336138393161306565623466383763663664323864633430626561313939336434363462656361
33343433636562653138613233343030333362383661633536616564313662353231343966386466
63633032643432343337303131656465373039646235653335353239633865353533626632336366
32386430623035626533346463333230663735353632356530643635386336393235646461303064
37316265613233303537373631613265636435343631363930323234366332613966346262336531
36646566393036636363333733613433353561363639616139626331336234353334303739643061
32333062383164373435666166386263663438666364636239383731313863386361363035313333
30656363306565623035303462363637353839343665393934613733613532313237613134313466
61336335616631666430393364363864306632663462393733656539386431313864333265393265
33626630643863306632363835353238376631626335313566666264343664656136316337376432
36653534336232303361663966663366343637663432316533643766636339313339643430336531
34303430336333663364306432363461326465396533376263336131323639393737666632623363
36656438616230663566633061383135633937613530346636396630656135663639396235373965
31396536376666333839336166653734303362633263643039353838393431393463303337313263
62653036346666393930646536653235326566303465333666646534643935663734643063613762
63336334646336343537386133383138363932616662376131393530633565353935613566306563
30643338613065393731623534656431373235353837383963383262323939343061326531303536
38303731633265376334393465656334353265656633336231326636636339626461616533323533
39326663336431353633313265353736356435393761613163386665623865346132333537666336
32366564363739386339343835393966623161656165643232643535616536633762666530623466
63636336386563373032663939373237383639623938616336653235663430613863616537326666
65346464326138646435353033303831383732623133393666663533303564613835323334333632
65366138613266313261646134303165333265366134373362333433653734653038646538363566
31373137643331373734353038643833333966663161633561653533333338353230393838336434
35346533356463666466
31333936393638613266313236303037323963333839336537656538623730326661346335346361
3635303665316130666139363462616230353763396439650a346463613033626365306666323638
37343734316534653437643834383139613562353538303838383137636361663530313432343030
3132333139346363630a343338336235613062336639633431643737383638363131316536363630
31643031626666616537303538393134326335666165636362313861306362623939396337653365
65386165343130613332363361313261353930396536396134323038623764326630653431633430
33386463313266373531343365333734336433656635663130613334333666376336316232323836
36373961373661323361363739623665616162323630396166616232613234623338613664303332
30623361363663396633333865343461616334636439376631646236313538663363336432623765
36323435626265333063326232663334376234303735313761306130623739323663333563363461
61383066333639323034616535333535373666346337613035656635313466666362313130633035
63383465663464363238643666653462656635626137613531343961336166373732323863613162
62386263376231653836336331653064316430656661336137316432363464376435373136383630
32633134383861616266643534303934396531343065376338653663356339343236356362393164
39616464623232646536376630646239626131373938323337323261663536323135623736333534
32393766663131376662666462666135616262353366336230336134383565656238313663626435
62636333326331346661646135313766363935393563333939323336363163306132333534626361
66623261376639646563306464623836306163396565326266366663386239306138333837376230
34616230623336653633303864353434666335323936343366653733396463653838646534393265
34393138656538373732616165646237353833313365383035346532613461613766653765366336
37613963386333666662323731656237343862383837633734363333613537623836666339383731
34313966383739383937343332613931656236336365643135373235343331346163333332313139
30333035663361393266303464376464623864653631306430353830383935643930313132623936
33303135386434366365396339636631633139663030323237646165376263666430626634333936
34333638333638613339343437396566323435323361323061666338356130333032613736633735
61643033383131306430653039633161343039303438373761386132626135613839313465353934
38636533353465633231326665336130616462303730333733306533326466346665333239306662
32336133346236316433353766356336653039303563623763396665653237383335316562376534
61386464626264363436656362303233633833623835623630656635353962333264393466663865
39626530323539656566326631316461303931323330356534316236616636613433363233303531
30326463636162653935663361653363313633323635613666616437386537653532656461653131
34376663393364356432656331383830633832363030643831303135393039343838303636616336
64666132353364373235646637353934656264313330646530393637663063326134363166613037
63373037333939363935316266363633316236373434363430323535393530383066396238653166
34653666666435633832623139353330396235616134633339643932316432363263646263613863
38343337353137653239623162656465363562643031353939653634323734663765356335316466
31653636626538303161626334643235643236666130613437643930306263336564373465303564
38353832313732376336643635613536336130393365336239303862393838323632303831656664
333665383162333661393336643863376438