feat: implement backend_postinstall() for the Fedora backend

Fetch the provisioning agent from git.tuxflotte.de, register it via
POST /api/v1/agent/bootstrap using the device id from the activation
response, write /etc/tuxflotte/agent.credentials, and enable the
tuxflotte-agent systemd service so it starts on first boot. Verified
end to end against a QEMU test VM and the real anode API.

The device id is now threaded through backend_generate_config() and
substituted into the kickstart template like the existing hostname
and blueprint values. %post drops the implicit chroot-wide set -e in
favor of per-step error handling, since localectl calls in this
section are known to fail best-effort without a running D-Bus.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Thomas Stallinger 2026-08-01 19:58:29 +02:00
parent 05dfacab4a
commit 715658893c
2 changed files with 64 additions and 7 deletions

View File

@ -67,6 +67,7 @@ backend_validate() {
backend_generate_config() {
local hostname
local device_id
local disk_encryption
local partitioning
local secure_boot_required
@ -80,6 +81,10 @@ backend_generate_config() {
[[ -n "${hostname}" ]] ||
{ backend_fatal "Kein Hostname in der Serverantwort gefunden."; return 1; }
device_id="$(jq --raw-output '.device.id // empty' "${SERVER_RESPONSE_FILE}")"
[[ -n "${device_id}" ]] ||
{ backend_fatal "Keine Geräte-ID in der Serverantwort gefunden."; return 1; }
disk_encryption="$(jq --raw-output '.runtime_blueprint.installation_directives.disk_encryption' "${RUNTIME_BLUEPRINT_FILE}")"
partitioning="$(jq --raw-output '.runtime_blueprint.installation_directives.partitioning' "${RUNTIME_BLUEPRINT_FILE}")"
secure_boot_required="$(jq --raw-output '.runtime_blueprint.installation_directives.secure_boot_required' "${RUNTIME_BLUEPRINT_FILE}")"
@ -105,9 +110,10 @@ backend_generate_config() {
blueprints_json="$(jq --compact-output '.runtime_blueprint.blueprints' "${RUNTIME_BLUEPRINT_FILE}")"
TUXFLOTTE_HOSTNAME="${hostname}" \
TUXFLOTTE_DEVICE_ID="${device_id}" \
TUXFLOTTE_PARTITIONING_COMMAND="${partitioning_command}" \
TUXFLOTTE_BLUEPRINTS_JSON="${blueprints_json}" \
envsubst '${TUXFLOTTE_HOSTNAME} ${TUXFLOTTE_PARTITIONING_COMMAND} ${TUXFLOTTE_BLUEPRINTS_JSON}' \
envsubst '${TUXFLOTTE_HOSTNAME} ${TUXFLOTTE_DEVICE_ID} ${TUXFLOTTE_PARTITIONING_COMMAND} ${TUXFLOTTE_BLUEPRINTS_JSON}' \
<"${KICKSTART_TEMPLATE}" >"${CONFIG_FILE}"
chmod 0600 "${CONFIG_FILE}"
@ -129,5 +135,5 @@ backend_launch() {
}
backend_postinstall() {
backend_log "Phase 1: Vorbereitung des Provisioning-Agent erfolgt bereits im %post-Abschnitt der Kickstart-Konfiguration."
backend_log "Provisioning-Agent-Einrichtung erfolgt im %post-Abschnitt der Kickstart-Konfiguration (Agent-Abruf, Bootstrap-Registrierung, systemd-Aktivierung)."
}

View File

@ -28,10 +28,11 @@ bootloader --location=mbr
vim
curl
git
jq
ansible-core
%end
%post
%post --erroronfail --interpreter=/bin/bash
cat > /etc/motd <<'EOF'
Provisioned by tuxflotte
@ -42,14 +43,64 @@ localectl set-locale LANG=de_DE.UTF-8
localectl set-keymap de
localectl set-x11-keymap de
mkdir -p /etc/tuxflotte
install -d -m 0700 /etc/tuxflotte
cat > /etc/tuxflotte/runtime_blueprint.json <<'RUNTIME_BLUEPRINT_EOF'
${TUXFLOTTE_BLUEPRINTS_JSON}
RUNTIME_BLUEPRINT_EOF
# Der Provisioning Agent existiert noch nicht als Build-Artefakt.
# Anwendung der obigen Blueprints per Ansible-Pull erfolgt erst nach dessen Implementierung.
# Provisioning Agent einrichten (backend_postinstall). Vorbereitung vor dem
# ersten Reboot: Agent-Code holen, beim Provisioning-Server registrieren und
# den Dienst für den ersten Boot aktivieren. Gestartet wird er erst danach,
# durch systemd selbst (siehe provisioning-agent/README.md).
#
# Bewusst ohne globales `set -e`: vorangehende Schritte wie
# `localectl set-x11-keymap` schlagen in der %post-Chroot best-effort fehl
# (kein laufendes systemd/D-Bus) und sollen die Installation nicht abbrechen.
# Der Agent-Block unten prüft deshalb jeden kritischen Schritt einzeln.
tuxflotte_agent_fatal() {
echo "tuxflotte: Provisioning-Agent-Einrichtung fehlgeschlagen: $*" >> /var/log/tuxflotte-postinstall.log
exit 1
}
ANODE_URL="https://anode.tuxflotte.de"
AGENT_REPO_RAW="https://git.tuxflotte.de/admin/provisioning-agent/raw/branch/main"
install -d /opt/tuxflotte/agent ||
tuxflotte_agent_fatal "Verzeichnis /opt/tuxflotte/agent konnte nicht angelegt werden."
curl --silent --show-error --fail --location \
--output /opt/tuxflotte/agent/agent.py \
"${AGENT_REPO_RAW}/agent.py" ||
tuxflotte_agent_fatal "agent.py konnte nicht von ${AGENT_REPO_RAW} geladen werden."
curl --silent --show-error --fail --location \
--output /etc/systemd/system/tuxflotte-agent.service \
"${AGENT_REPO_RAW}/tuxflotte-agent.service" ||
tuxflotte_agent_fatal "tuxflotte-agent.service konnte nicht von ${AGENT_REPO_RAW} geladen werden."
AGENT_BOOTSTRAP_RESPONSE="$(
curl --silent --show-error --fail --location \
--header 'Content-Type: application/json' \
--data-binary "{\"device_id\": \"${TUXFLOTTE_DEVICE_ID}\"}" \
"${ANODE_URL}/api/v1/agent/bootstrap"
)" ||
tuxflotte_agent_fatal "Bootstrap-Aufruf gegen ${ANODE_URL} ist fehlgeschlagen."
jq --exit-status '.success == true' <<<"${AGENT_BOOTSTRAP_RESPONSE}" >/dev/null ||
tuxflotte_agent_fatal "Server hat den Bootstrap abgelehnt: ${AGENT_BOOTSTRAP_RESPONSE}"
jq --null-input \
--arg device_id "${TUXFLOTTE_DEVICE_ID}" \
--argjson response "${AGENT_BOOTSTRAP_RESPONSE}" \
'{device_id: $device_id, agent_secret: $response.agent_secret}' \
> /etc/tuxflotte/agent.credentials ||
tuxflotte_agent_fatal "Credentials-Datei konnte nicht erzeugt werden."
chmod 0600 /etc/tuxflotte/agent.credentials
systemctl enable tuxflotte-agent.service ||
tuxflotte_agent_fatal "systemd-Dienst tuxflotte-agent konnte nicht aktiviert werden."
echo "tuxflotte: Runtime Blueprint unter /etc/tuxflotte/runtime_blueprint.json hinterlegt." >> /var/log/tuxflotte-postinstall.log
echo "tuxflotte: Provisioning-Agent-Installation ist noch nicht implementiert (Phase 1)." >> /var/log/tuxflotte-postinstall.log
echo "tuxflotte: Provisioning-Agent installiert, registriert und für den ersten Boot aktiviert." >> /var/log/tuxflotte-postinstall.log
%end