diff --git a/ansible/bootstrap/aegis.bu b/ansible/bootstrap/aegis.bu index c283a11..75c3c4b 100644 --- a/ansible/bootstrap/aegis.bu +++ b/ansible/bootstrap/aegis.bu @@ -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 diff --git a/ansible/bootstrap/generate-aegis-ign.sh b/ansible/bootstrap/generate-aegis-ign.sh new file mode 100755 index 0000000..e978714 --- /dev/null +++ b/ansible/bootstrap/generate-aegis-ign.sh @@ -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" diff --git a/ansible/inventory/group_vars/desktop_gnome.yml b/ansible/inventory/group_vars/desktop_gnome.yml index 3453ecb..37e1cd1 100644 --- a/ansible/inventory/group_vars/desktop_gnome.yml +++ b/ansible/inventory/group_vars/desktop_gnome.yml @@ -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 diff --git a/ansible/inventory/host_vars/aegis.yml b/ansible/inventory/host_vars/aegis.yml index d1e4a95..2232f68 100644 --- a/ansible/inventory/host_vars/aegis.yml +++ b/ansible/inventory/host_vars/aegis.yml @@ -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 diff --git a/secrets/vault.yml b/secrets/vault.yml index 945ea29..2f62ecd 100644 --- a/secrets/vault.yml +++ b/secrets/vault.yml @@ -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