Fedora-Installer-Versuche archivieren (Tag archiv/fedora-versuche) und aus main entfernen
Nicht mehr genutzt seit dem eigenen Boot-Medium (ADR-0025). Die Testdateien enthielten u. a. ein WLAN-Passwort im Klartext; es bleibt in der Historie, die Abhilfe ist ein Passwortwechsel, nicht dieses Entfernen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
cee4fe58ad
commit
4929a37175
10 files changed
+3
-756
No files matched your search
@@ -32,6 +32,6 @@ headless-tauglichen Code (Module `scripts/modules/00`-`40`,
|
||||
personalisiert ein bereits gebautes Basis-Image für eine konkrete
|
||||
Kundenorganisation (Aktivierungscode + WLAN-Zugangsdaten).
|
||||
|
||||
Fedora nutzt weiterhin das ältere Kickstart/Anaconda-Muster
|
||||
(`scripts/build.sh <source.iso> fedora`) - noch nicht auf dasselbe
|
||||
Boot-Medium-Muster umgestellt.
|
||||
Die früheren Versuche mit Fedora (Kickstart/Anaconda, `scripts/build.sh`,
|
||||
`backends/fedora/`, `grub/`) sind am 18.10.2026 aus `main` entfernt worden;
|
||||
der letzte Stand liegt im Tag `archiv/fedora-versuche`.
|
||||
@@ -1,155 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
# Dieses Skript wird von einem Orchestrator-Modul (z.B. 40_backend.sh) per
|
||||
# `source` in dessen Shell geladen. Variablen bleiben deshalb bewusst nicht
|
||||
# readonly, um Namenskollisionen mit dem ladenden Modul zu vermeiden.
|
||||
BACKEND_KEY="fedora"
|
||||
|
||||
BACKEND_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
KICKSTART_TEMPLATE="${BACKEND_DIR}/kickstart.tpl"
|
||||
|
||||
RUNTIME_BLUEPRINT_FILE="/run/tuxflotte/runtime/runtime_blueprint.json"
|
||||
SERVER_RESPONSE_FILE="/run/tuxflotte/server/response.json"
|
||||
# Von 10_hardware.sh im selben Live-Boot geschrieben (siehe dort) - Quelle
|
||||
# fuer den Fingerprint, der jetzt auch auf dem installierten Geraet selbst
|
||||
# hinterlegt wird (siehe backend_generate_config()/kickstart.tpl %post).
|
||||
HARDWARE_FILE="/run/tuxflotte/hardware/hardware.json"
|
||||
|
||||
RUNTIME_DIR="/run/tuxflotte/backend"
|
||||
CONFIG_FILE="${RUNTIME_DIR}/config"
|
||||
|
||||
backend_log() {
|
||||
printf '[backend:%s] %s\n' "${BACKEND_KEY}" "$*" >&2
|
||||
}
|
||||
|
||||
backend_fatal() {
|
||||
printf '[backend:%s] FEHLER: %s\n' "${BACKEND_KEY}" "$*" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
backend_init() {
|
||||
for cmd in jq envsubst; do
|
||||
command -v "${cmd}" >/dev/null 2>&1 ||
|
||||
{ backend_fatal "Benötigtes Werkzeug fehlt: ${cmd}"; return 1; }
|
||||
done
|
||||
|
||||
[[ -r "${KICKSTART_TEMPLATE}" ]] ||
|
||||
{ backend_fatal "Kickstart-Template nicht gefunden: ${KICKSTART_TEMPLATE}"; return 1; }
|
||||
|
||||
install -d \
|
||||
--mode=0700 \
|
||||
--owner=root \
|
||||
--group=root \
|
||||
"${RUNTIME_DIR}"
|
||||
|
||||
rm -f -- "${CONFIG_FILE}"
|
||||
|
||||
backend_log "Initialisiert."
|
||||
}
|
||||
|
||||
backend_validate() {
|
||||
[[ -r "${RUNTIME_BLUEPRINT_FILE}" ]] ||
|
||||
{ backend_fatal "Runtime Blueprint nicht gefunden: ${RUNTIME_BLUEPRINT_FILE}"; return 1; }
|
||||
|
||||
jq --exit-status \
|
||||
--arg backend_key "${BACKEND_KEY}" \
|
||||
'.runtime_blueprint.backend_id == $backend_key' \
|
||||
"${RUNTIME_BLUEPRINT_FILE}" >/dev/null ||
|
||||
{ backend_fatal "Runtime Blueprint ist nicht für Backend '${BACKEND_KEY}' aufgelöst."; return 1; }
|
||||
|
||||
jq --exit-status '
|
||||
.runtime_blueprint.installation_directives
|
||||
| (.disk_encryption | type == "boolean")
|
||||
and (.partitioning | type == "string")
|
||||
and (.secure_boot_required | type == "boolean")
|
||||
' "${RUNTIME_BLUEPRINT_FILE}" >/dev/null ||
|
||||
{ backend_fatal "Installationszeitliche Vorgaben fehlen oder sind ungültig."; return 1; }
|
||||
|
||||
backend_log "Runtime Blueprint ist gültig für Backend '${BACKEND_KEY}'."
|
||||
}
|
||||
|
||||
backend_generate_config() {
|
||||
local hostname
|
||||
local device_id
|
||||
local disk_encryption
|
||||
local partitioning
|
||||
local secure_boot_required
|
||||
local partitioning_command
|
||||
local blueprints_json
|
||||
|
||||
[[ -r "${SERVER_RESPONSE_FILE}" ]] ||
|
||||
{ backend_fatal "Serverantwort nicht gefunden: ${SERVER_RESPONSE_FILE}"; return 1; }
|
||||
|
||||
hostname="$(jq --raw-output '.device.hostname // empty' "${SERVER_RESPONSE_FILE}")"
|
||||
[[ -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; }
|
||||
|
||||
# Fuer die beidseitige Identifikation (Geraeteliste <-> Geraet selbst,
|
||||
# siehe kickstart.tpl %post) - aus der bereits waehrend des Live-Boots
|
||||
# berechneten hardware.json, nicht aus der Serverantwort (die kennt nur
|
||||
# die zugewiesene device_id, nicht den urspruenglichen Hardware-Hash).
|
||||
local device_fingerprint
|
||||
[[ -r "${HARDWARE_FILE}" ]] ||
|
||||
{ backend_fatal "Hardware-Erfassung nicht gefunden: ${HARDWARE_FILE}"; return 1; }
|
||||
device_fingerprint="$(jq --raw-output '.identity.device_fingerprint // empty' "${HARDWARE_FILE}")"
|
||||
[[ -n "${device_fingerprint}" ]] ||
|
||||
{ backend_fatal "Kein device_fingerprint in ${HARDWARE_FILE} 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}")"
|
||||
|
||||
case "${partitioning}" in
|
||||
default)
|
||||
if [[ "${disk_encryption}" == "true" ]]; then
|
||||
partitioning_command="autopart --encrypted"
|
||||
else
|
||||
partitioning_command="autopart"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
backend_fatal "Nicht unterstützte Partitionierungsvorgabe: ${partitioning}"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ "${secure_boot_required}" == "true" ]]; then
|
||||
backend_log "Hinweis: secure_boot_required=true wird derzeit nicht in der Kickstart-Konfiguration durchgesetzt (Phase 1)."
|
||||
fi
|
||||
|
||||
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}" \
|
||||
TUXFLOTTE_DEVICE_FINGERPRINT="${device_fingerprint}" \
|
||||
envsubst '${TUXFLOTTE_HOSTNAME} ${TUXFLOTTE_DEVICE_ID} ${TUXFLOTTE_PARTITIONING_COMMAND} ${TUXFLOTTE_BLUEPRINTS_JSON} ${TUXFLOTTE_DEVICE_FINGERPRINT}' \
|
||||
<"${KICKSTART_TEMPLATE}" >"${CONFIG_FILE}"
|
||||
|
||||
chmod 0600 "${CONFIG_FILE}"
|
||||
|
||||
[[ -s "${CONFIG_FILE}" ]] ||
|
||||
{ backend_fatal "Erzeugte Konfigurationsdatei ist leer: ${CONFIG_FILE}"; return 1; }
|
||||
|
||||
if grep -q '\${TUXFLOTTE_' "${CONFIG_FILE}"; then
|
||||
backend_fatal "Erzeugte Konfigurationsdatei enthält nicht aufgelöste Platzhalter."
|
||||
return 1
|
||||
fi
|
||||
|
||||
backend_log "Konfiguration erzeugt: ${CONFIG_FILE}"
|
||||
}
|
||||
|
||||
backend_launch() {
|
||||
backend_log "Phase 1: Start des nativen Installers ist noch nicht aktiv."
|
||||
backend_log "Erzeugte Konfiguration liegt bereit unter: ${CONFIG_FILE}"
|
||||
}
|
||||
|
||||
backend_postinstall() {
|
||||
backend_log "Provisioning-Agent-Einrichtung erfolgt im %post-Abschnitt der Kickstart-Konfiguration (Agent-Abruf, Bootstrap-Registrierung, systemd-Aktivierung)."
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
#version=DEVEL
|
||||
# Test-Kickstart fuer das neue Architekturmodell (ADR-0009, Update 30.07.2026):
|
||||
# Fedora-Server-DVD statt Netinstall -- die Installation selbst braucht kein
|
||||
# Netz (Kickstart und Pakete liegen schon auf dem Medium). WLAN wird NICHT
|
||||
# waehrend der Installation aufgebaut (network --wpakey= haengt unabhaengig
|
||||
# von --activate in dracut-initqueue, real getestet, siehe ADR-0009), sondern
|
||||
# per %post als NetworkManager-Verbindungsprofil direkt ins fertig
|
||||
# installierte Zielsystem geschrieben -- dieselbe Stelle, an der heute schon
|
||||
# runtime_blueprint.json geschrieben wird.
|
||||
#
|
||||
# Versuch 2: keine network-Zeile mehr ueberhaupt. Versuch 1 (network
|
||||
# --hostname=... ohne --essid/--wpakey) haengt real genauso in
|
||||
# dracut-initqueue wie zuvor mit WLAN-Angaben -- offenbar reicht schon eine
|
||||
# blosse network-Zeile, damit Anaconda auf irgendein Netzwerk wartet,
|
||||
# unabhaengig vom Inhalt. Hostname wird jetzt stattdessen in %post per
|
||||
# hostnamectl gesetzt -- das braucht kein Dracut-Netzwerk, laeuft schon im
|
||||
# chroot des installierten Systems.
|
||||
|
||||
text
|
||||
reboot
|
||||
|
||||
lang de_DE.UTF-8
|
||||
keyboard de
|
||||
timezone Europe/Berlin --utc
|
||||
|
||||
rootpw --plaintext test123
|
||||
user --name=tuxflotte --groups=wheel --password=test123
|
||||
|
||||
zerombr
|
||||
clearpart --all --initlabel
|
||||
autopart
|
||||
|
||||
firewall --enabled
|
||||
selinux --enforcing
|
||||
|
||||
bootloader --location=mbr
|
||||
|
||||
%packages
|
||||
@core
|
||||
vim
|
||||
curl
|
||||
%end
|
||||
|
||||
%post
|
||||
hostnamectl set-hostname fedora-dvd-test
|
||||
|
||||
cat > /etc/motd <<'EOF'
|
||||
dvd-wlan-test (ADR-0009, neues Architekturmodell) -- provisioned by tuxflotte
|
||||
EOF
|
||||
|
||||
mkdir -p /etc/NetworkManager/system-connections
|
||||
cat > /etc/NetworkManager/system-connections/stallinux.nmconnection <<'EOF'
|
||||
[connection]
|
||||
id=stallinux
|
||||
type=wifi
|
||||
[wifi]
|
||||
mode=infrastructure
|
||||
ssid=stallinux
|
||||
[wifi-security]
|
||||
key-mgmt=wpa-psk
|
||||
psk=a987654321
|
||||
[ipv4]
|
||||
method=auto
|
||||
[ipv6]
|
||||
method=auto
|
||||
EOF
|
||||
chmod 600 /etc/NetworkManager/system-connections/stallinux.nmconnection
|
||||
|
||||
echo "tuxflotte: dvd-wlan-test %post lief durch, WLAN-Profil geschrieben." >> /var/log/tuxflotte-postinstall.log
|
||||
%end
|
||||
@@ -1,42 +0,0 @@
|
||||
#version=DEVEL
|
||||
# Test-Kickstart fuer ADR-0009, Pruefplan-Schritt 2 (kexec statt Neustart aus
|
||||
# der Live-Sitzung). Kein Platzhalter-Templating wie kickstart.tpl -- feste
|
||||
# Testwerte, damit sich das Ergebnis eindeutig einer Ursache zuordnen laesst.
|
||||
#
|
||||
# Versuch 2: keine liveimg-Zeile mehr. Versuch 1 (root=live:CDLABEL=...
|
||||
# rd.live.image) landete trotz inst.ks= wieder im normalen Live-Desktop --
|
||||
# vermutlich weil root=live/rd.live.image Dracuts dmsquash-live-Pfad
|
||||
# ausloesen, der inst.ks= ignoriert. Jetzt setzt inst.stage2=hd:LABEL=
|
||||
# TUXFLOTTE:/ (siehe kexec-reboot-test.sh) die Installationsquelle bereits
|
||||
# auf Boot-Ebene -- eine zusaetzliche liveimg-Zeile hier waere eine zweite,
|
||||
# moeglicherweise widerspruechliche Quellenangabe. Der %packages-Abschnitt
|
||||
# wird von Anaconda bei einer liveimg-artigen Quelle ignoriert
|
||||
# (dokumentiertes pykickstart-Verhalten) -- absichtlich leer gelassen.
|
||||
|
||||
text
|
||||
reboot
|
||||
|
||||
lang de_DE.UTF-8
|
||||
keyboard de
|
||||
timezone Europe/Berlin --utc
|
||||
|
||||
rootpw --plaintext test123
|
||||
user --name=tuxflotte --groups=wheel --password=test123
|
||||
|
||||
network --bootproto=dhcp --activate --hostname=fedora-kexec-test
|
||||
|
||||
zerombr
|
||||
clearpart --all --initlabel
|
||||
autopart
|
||||
|
||||
firewall --enabled
|
||||
selinux --enforcing
|
||||
|
||||
bootloader --location=mbr
|
||||
|
||||
%post
|
||||
cat > /etc/motd <<'EOF'
|
||||
kexec-reboot-test (ADR-0009, Schritt 2) -- provisioned by tuxflotte
|
||||
EOF
|
||||
echo "tuxflotte: kexec-reboot-test %post lief durch." >> /var/log/tuxflotte-postinstall.log
|
||||
%end
|
||||
@@ -1,68 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
# Manueller Test fuer ADR-0009, Pruefplan-Schritt 2: prueft, ob Anaconda
|
||||
# rootpw/user/Partitionierung korrekt uebernimmt, wenn der Installer per
|
||||
# kexec (statt liveinst mitten in der Session) mit inst.ks= gestartet wird.
|
||||
#
|
||||
# Kein Teil des Backend-Lifecycles (40_backend.sh) -- wird von Hand in der
|
||||
# laufenden Live-Sitzung ausgefuehrt, Ergebnis wird manuell in Proxmox
|
||||
# beobachtet (siehe Verifikations-Arbeitsteilung: Claude bereitet vor,
|
||||
# Nutzer prueft funktional).
|
||||
#
|
||||
# Versuch 3: Kickstart-Zustellung per HTTPS (inst.ks=https://...) statt per
|
||||
# Initrd-Einbettung. Versuch 2 (Initrd-Anhaengen per cat) scheiterte an
|
||||
# "invalid magic at start of compressed archive" -- vermutlich xz/zstd-
|
||||
# komprimiertes Basis-Initrd, das sich nicht wie ein Gzip-Initrd per cat
|
||||
# verketten laesst. Diese VM haengt an virtio/DHCP, kein WLAN im Spiel,
|
||||
# daher ist Netz-Zustellung hier kein Risiko -- die ungeklaerte WLAN-im-
|
||||
# Dracut-Frage bleibt fuer den spaeteren WLAN-Autoprovisionierungs-Schritt
|
||||
# offen, wird hier bewusst nicht mitgetestet.
|
||||
#
|
||||
# Kickstart-Quelle fuer diesen Test: https://anode.tuxflotte.de/installers/
|
||||
# fedora-workstation/ks.cfg (bestehender Endpoint, temporaer mit
|
||||
# kexec-reboot-test.cfg ueberschrieben, Original als
|
||||
# ks.cfg.bak-2026-07-29 gesichert).
|
||||
|
||||
log() { printf '[kexec-test] %s\n' "$*" >&2; }
|
||||
fatal() { printf '[kexec-test] FEHLER: %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
[[ "${EUID}" -eq 0 ]] || fatal "Bitte als root ausfuehren (sudo)."
|
||||
|
||||
KICKSTART_URL="https://anode.tuxflotte.de/installers/fedora-workstation/ks.cfg"
|
||||
|
||||
log "Pruefe kexec-tools."
|
||||
if ! command -v kexec >/dev/null 2>&1; then
|
||||
log "kexec fehlt, installiere ueber dnf (Netzwerk muss bereits stehen)."
|
||||
dnf install -y kexec-tools || fatal "kexec-tools konnte nicht installiert werden."
|
||||
fi
|
||||
|
||||
log "Pruefe Erreichbarkeit der Kickstart-URL: ${KICKSTART_URL}"
|
||||
curl -fsS -o /dev/null "${KICKSTART_URL}" ||
|
||||
fatal "Kickstart-URL nicht erreichbar -- Netzwerk der Live-Sitzung pruefen."
|
||||
|
||||
log "Suche Live-Medium-Kernel/Initrd unter /run/initramfs/live."
|
||||
LIVE_ROOT="/run/initramfs/live"
|
||||
[[ -d "${LIVE_ROOT}" ]] || fatal "Live-Medium nicht unter ${LIVE_ROOT} gemountet -- Pfad pruefen und Skript anpassen."
|
||||
|
||||
LIVE_VMLINUZ="${LIVE_ROOT}/boot/x86_64/loader/linux"
|
||||
LIVE_INITRD="${LIVE_ROOT}/boot/x86_64/loader/initrd"
|
||||
|
||||
for f in "${LIVE_VMLINUZ}" "${LIVE_INITRD}"; do
|
||||
[[ -r "${f}" ]] || fatal "Erwartete Datei fehlt: ${f} -- tatsaechliche Struktur unter ${LIVE_ROOT} pruefen (find ${LIVE_ROOT} -maxdepth 4)."
|
||||
done
|
||||
log "Gefunden: ${LIVE_VMLINUZ}, ${LIVE_INITRD}"
|
||||
|
||||
# Kein root=live/rd.live.image (loest Dracuts dmsquash-live-Pfad aus, der
|
||||
# inst.ks= ignoriert -- real getestet, Versuch 1). inst.stage2= setzt die
|
||||
# Installationsquelle auf Boot-Ebene direkt auf Anacondas eigenen Pfad.
|
||||
# inst.cmdline statt inst.text: bricht laut ab, wenn eine Direktive
|
||||
# unvollstaendig bleibt, statt es wie im ADR-0009-Befund still zu ignorieren.
|
||||
APPEND="inst.stage2=hd:LABEL=TUXFLOTTE:/ vconsole.keymap=de inst.ks=${KICKSTART_URL} inst.cmdline"
|
||||
|
||||
log "kexec -l mit Append: ${APPEND}"
|
||||
kexec -l "${LIVE_VMLINUZ}" --initrd="${LIVE_INITRD}" --append="${APPEND}" ||
|
||||
fatal "kexec -l fehlgeschlagen."
|
||||
|
||||
read -r -p "[kexec-test] Alles geprueft? Enter loest kexec -e aus, Strg+C bricht ab: " _
|
||||
kexec -e
|
||||
@@ -1,115 +0,0 @@
|
||||
#version=DEVEL
|
||||
|
||||
text
|
||||
reboot
|
||||
|
||||
lang de_DE.UTF-8
|
||||
keyboard de
|
||||
timezone Europe/Berlin --utc
|
||||
|
||||
# Lab-Bootstrap-Zugangsdaten. Ersetzt ein noch fehlendes Secret-Reference-Modell
|
||||
# (siehe 09-data-model-v1.md) und darf nicht als Produktionsmechanismus gelten.
|
||||
rootpw --plaintext test123
|
||||
user --name=tuxflotte --groups=wheel --password=test123
|
||||
|
||||
network --bootproto=dhcp --activate --hostname=${TUXFLOTTE_HOSTNAME}
|
||||
|
||||
zerombr
|
||||
clearpart --all --initlabel
|
||||
${TUXFLOTTE_PARTITIONING_COMMAND}
|
||||
|
||||
firewall --enabled
|
||||
selinux --enforcing
|
||||
|
||||
bootloader --location=mbr
|
||||
|
||||
%packages
|
||||
@core
|
||||
vim
|
||||
curl
|
||||
git
|
||||
jq
|
||||
ansible-core
|
||||
%end
|
||||
|
||||
%post --erroronfail --interpreter=/bin/bash
|
||||
cat > /etc/motd <<'EOF'
|
||||
Provisioned by tuxflotte
|
||||
|
||||
https://tuxflotte.de
|
||||
EOF
|
||||
|
||||
localectl set-locale LANG=de_DE.UTF-8
|
||||
localectl set-keymap de
|
||||
localectl set-x11-keymap de
|
||||
|
||||
install -d -m 0700 /etc/tuxflotte
|
||||
|
||||
# Identifikation soll in beide Richtungen moeglich sein: die Geraeteliste
|
||||
# zeigt den Fingerprint bereits an (siehe geraete_liste.html), aber bislang
|
||||
# gab es auf dem installierten Geraet selbst keine Datei, um ihn mit einem
|
||||
# einfachen "cat" gegenzupruefen - build_device_fingerprint() (10_hardware.sh)
|
||||
# berechnet ihn nur einmalig waehrend des Live-Boots und haelt ihn sonst
|
||||
# nirgends fest. Absichtlich Klartext, kein Secret - reiner Hardware-Hash,
|
||||
# kein chmod 0600 noetig wie bei agent.credentials.
|
||||
echo "${TUXFLOTTE_DEVICE_FINGERPRINT}" > /etc/tuxflotte/device_fingerprint
|
||||
|
||||
cat > /etc/tuxflotte/runtime_blueprint.json <<'RUNTIME_BLUEPRINT_EOF'
|
||||
${TUXFLOTTE_BLUEPRINTS_JSON}
|
||||
RUNTIME_BLUEPRINT_EOF
|
||||
|
||||
# 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 installiert, registriert und für den ersten Boot aktiviert." >> /var/log/tuxflotte-postinstall.log
|
||||
%end
|
||||
@@ -1,79 +0,0 @@
|
||||
#version=DEVEL
|
||||
# Test-Kickstart fuer ADR-0009 Ultima Ratio, WLAN-Schritt.
|
||||
#
|
||||
# Liegt direkt auf dem ISO (inst.ks=cdrom:/ks.cfg), wird NICHT per Netz
|
||||
# geladen: das Boot-Initrd von Fedora-Netinstall enthaelt zwar WLAN-Treiber
|
||||
# und NetworkManager, aber kein wpa_supplicant (real geprueft, siehe
|
||||
# ADR-0009-Update) -- WPA waere in dieser fruehen Phase also gar nicht
|
||||
# moeglich, unabhaengig von einem gebackenen Verbindungsprofil.
|
||||
#
|
||||
# wpa_supplicant liegt stattdessen in images/install.img (Anacondas
|
||||
# groesseres Laufzeit-Environment, nach dem Initrd nachgeladen).
|
||||
#
|
||||
# Versuch 1 (mit --activate): real getestet, haengt in
|
||||
# dracut-initqueue.service -- --activate zwingt Anaconda offenbar, das
|
||||
# Geraet bereits in der Dracut-Phase hochzufahren, also genau dort, wo
|
||||
# wpa_supplicant fehlt.
|
||||
#
|
||||
# Versuch 2 (--activate entfernt, sonst gleiche network-Zeile): ebenfalls
|
||||
# real getestet, haengt identisch. Also nicht --activate selbst der
|
||||
# Ausloeser -- schon die blosse Angabe von --essid/--wpakey auf einer
|
||||
# network-Zeile lasst Anaconda den Dracut-Hook fuer dieses Geraet ausfuehren,
|
||||
# unabhaengig vom Aktivierungs-Flag.
|
||||
#
|
||||
# Versuch 3 (dieser): network-Zeile komplett ohne WLAN-Details (nur noch
|
||||
# Hostname), damit Dracut fuer wlan0 gar nichts versucht. WLAN-Verbindung
|
||||
# stattdessen per %pre-Skript ueber nmcli -- %pre laeuft laut
|
||||
# Kickstart-Ablauf bereits in Anacondas voller install.img-Umgebung (nach
|
||||
# dem Stage2-Laden, vor der Paketinstallation), also genau dort, wo
|
||||
# wpa_supplicant vorhanden ist. Kein Hack, nmcli ist offiziell fuer genau
|
||||
# diesen Zweck vorgesehen.
|
||||
#
|
||||
# %packages braucht danach echtes Netz (dies ist ein Netinstall-Repo, keine
|
||||
# lokalen Pakete) -- ein vollstaendiger Durchlauf beweist also, dass die
|
||||
# WPA-Anmeldung ueber nmcli tatsaechlich funktioniert hat.
|
||||
|
||||
text
|
||||
reboot
|
||||
|
||||
lang de_DE.UTF-8
|
||||
keyboard de
|
||||
timezone Europe/Berlin --utc
|
||||
|
||||
rootpw --plaintext test123
|
||||
user --name=tuxflotte --groups=wheel --password=test123
|
||||
|
||||
network --hostname=fedora-wlan-test
|
||||
|
||||
zerombr
|
||||
clearpart --all --initlabel
|
||||
autopart
|
||||
|
||||
firewall --enabled
|
||||
selinux --enforcing
|
||||
|
||||
bootloader --location=mbr
|
||||
|
||||
%pre
|
||||
nmcli device wifi connect stallinux password a987654321 ifname wlan0
|
||||
ec=$?
|
||||
{
|
||||
echo "tuxflotte: %pre nmcli exit=${ec}"
|
||||
nmcli device status
|
||||
nmcli connection show
|
||||
} > /tmp/tuxflotte-wlan-pre.log 2>&1
|
||||
exit 0
|
||||
%end
|
||||
|
||||
%packages
|
||||
@core
|
||||
vim
|
||||
curl
|
||||
%end
|
||||
|
||||
%post
|
||||
cat > /etc/motd <<'EOF'
|
||||
wlan-netinst-test (ADR-0009 Ultima Ratio, WLAN-Schritt) -- provisioned by tuxflotte
|
||||
EOF
|
||||
echo "tuxflotte: wlan-netinst-test %post lief durch." >> /var/log/tuxflotte-postinstall.log
|
||||
%end
|
||||
@@ -1,47 +0,0 @@
|
||||
set default="Lokales UEFI-System booten"
|
||||
|
||||
function load_video {
|
||||
insmod efi_gop
|
||||
insmod efi_uga
|
||||
insmod video_bochs
|
||||
insmod video_cirrus
|
||||
insmod all_video
|
||||
}
|
||||
|
||||
load_video
|
||||
set gfxpayload=keep
|
||||
insmod gzio
|
||||
insmod part_gpt
|
||||
insmod ext2
|
||||
|
||||
set timeout=10
|
||||
### END /etc/grub.d/00_header ###
|
||||
|
||||
search --no-floppy --set=root -l 'TUXFLOTTE'
|
||||
|
||||
insmod gfxterm
|
||||
terminal_output gfxterm
|
||||
set color_normal=blue/white
|
||||
set color_highlight=white/blue
|
||||
|
||||
### BEGIN /etc/grub.d/10_linux ###
|
||||
menuentry 'Tuxflotte Provisioning (automatisch)' --class fedora --class gnu-linux --class gnu --class os {
|
||||
linux /boot/x86_64/loader/linux quiet rhgb root=live:CDLABEL=TUXFLOTTE rd.live.image vconsole.keymap=de tuxflotte.mode=auto
|
||||
initrd /boot/x86_64/loader/initrd
|
||||
}
|
||||
|
||||
menuentry 'Tuxflotte Provisioning (interaktiv)' --class fedora --class gnu-linux --class gnu --class os {
|
||||
linux /boot/x86_64/loader/linux quiet rhgb root=live:CDLABEL=TUXFLOTTE rd.live.image vconsole.keymap=de tuxflotte.mode=interactive
|
||||
initrd /boot/x86_64/loader/initrd
|
||||
}
|
||||
|
||||
menuentry 'Lokales UEFI-System booten' --class hdd --class os {
|
||||
insmod part_gpt
|
||||
insmod fat
|
||||
insmod chain
|
||||
|
||||
search --no-floppy --file --set=local_efi /EFI/fedora/shimx64.efi
|
||||
|
||||
chainloader ($local_efi)/EFI/fedora/shimx64.efi
|
||||
boot
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
set default="Von erster lokaler Festplatte booten"
|
||||
|
||||
function load_video {
|
||||
insmod all_video
|
||||
}
|
||||
|
||||
load_video
|
||||
set gfxpayload=keep
|
||||
insmod gzio
|
||||
insmod part_gpt
|
||||
insmod ext2
|
||||
insmod chain
|
||||
|
||||
set timeout=10
|
||||
### END /etc/grub.d/00_header ###
|
||||
|
||||
search --no-floppy --set=root -l 'TUXFLOTTE'
|
||||
|
||||
insmod gfxterm
|
||||
terminal_output gfxterm
|
||||
set color_normal=blue/white
|
||||
set color_highlight=white/blue
|
||||
|
||||
### BEGIN /etc/grub.d/10_linux ###
|
||||
menuentry 'Tuxflotte Provisioning (automatisch)' --class fedora --class gnu-linux --class gnu --class os {
|
||||
linux /boot/x86_64/loader/linux quiet rhgb root=live:CDLABEL=TUXFLOTTE rd.live.image vconsole.keymap=de tuxflotte.mode=auto
|
||||
initrd /boot/x86_64/loader/initrd
|
||||
}
|
||||
|
||||
menuentry 'Tuxflotte Provisioning (interaktiv)' --class fedora --class gnu-linux --class gnu --class os {
|
||||
linux /boot/x86_64/loader/linux quiet rhgb root=live:CDLABEL=TUXFLOTTE rd.live.image vconsole.keymap=de tuxflotte.mode=interactive
|
||||
initrd /boot/x86_64/loader/initrd
|
||||
}
|
||||
|
||||
menuentry 'Von erster lokaler Festplatte booten' --class hdd --class os {
|
||||
chainloader (hd0)+1
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Nur noch fuer das Fedora-Backend (Kickstart/Anaconda) - das Mint-Backend
|
||||
# ist auf das eigenstaendige, per live-build gebaute Boot-Medium umgezogen
|
||||
# (siehe scripts/build_boot_medium.sh, boot-medium/). Der bisherige
|
||||
# Mint-Zweig hier (Casper-Patchen einer echten Mint-Live-ISO + Ubiquity-
|
||||
# Preseed) ist damit Geschichte - siehe ADR-0025 fuer die Begruendung.
|
||||
|
||||
SOURCE_ISO="${1:-}"
|
||||
BACKEND="${2:-}"
|
||||
|
||||
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
BASE_DIR="$(cd "$REPO_DIR/.." && pwd)"
|
||||
BUILD_DIR="$BASE_DIR/build"
|
||||
WORK_DIR="$BUILD_DIR/work"
|
||||
OUTPUT_DIR="$BUILD_DIR/output"
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 /path/to/source.iso fedora"
|
||||
}
|
||||
|
||||
check_input() {
|
||||
if [[ -z "$SOURCE_ISO" || -z "$BACKEND" ]]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$SOURCE_ISO" ]]; then
|
||||
echo "Error: ISO not found: $SOURCE_ISO"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$BACKEND" != "fedora" ]]; then
|
||||
echo "Error: unbekanntes Backend '$BACKEND' (erwartet: fedora)"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_dependencies() {
|
||||
for cmd in xorriso; do
|
||||
if ! command -v "$cmd" >/dev/null 2>&1; then
|
||||
echo "Error: missing dependency: $cmd"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
prepare_dirs() {
|
||||
mkdir -p "$BUILD_DIR" "$OUTPUT_DIR"
|
||||
# xorriso extrahiert Verzeichnisse teils mit den Original-ISO-Rechten
|
||||
# (z.B. 555, kein Write-Bit) - ohne chmod schlaegt rm -rf darauf fehl.
|
||||
chmod -R u+w "$WORK_DIR" 2>/dev/null || true
|
||||
rm -rf "$WORK_DIR"
|
||||
mkdir -p "$WORK_DIR"
|
||||
}
|
||||
|
||||
extract_iso() {
|
||||
echo "Extracting ISO..."
|
||||
xorriso -indev "$SOURCE_ISO" -osirrox on -extract / "$WORK_DIR" >/dev/null
|
||||
# xorriso uebernimmt die Original-ISO-Rechte (haeufig 555 auf
|
||||
# Verzeichnissen, 444 auf Dateien) - ohne Write-Bit koennen weder
|
||||
# spaetere Schritte (patch_grub) noch spaetere Aufraeumlaeufe
|
||||
# (prepare_dirs) Dateien darin ersetzen/entfernen.
|
||||
chmod -R u+w "$WORK_DIR"
|
||||
}
|
||||
|
||||
patch_grub() {
|
||||
echo "Installing Tuxflotte GRUB configuration..."
|
||||
|
||||
# -f: xorriso extrahiert ISO-Dateien mit deren Original-Rechten, die auf
|
||||
# Live-Medien haeufig read-only (444) sind - ohne -f schlaegt cp beim
|
||||
# Ueberschreiben mit "Keine Berechtigung" fehl.
|
||||
cp -f "$REPO_DIR/grub/EFI-BOOT-grub.cfg" \
|
||||
"$WORK_DIR/EFI/BOOT/grub.cfg"
|
||||
|
||||
cp -f "$REPO_DIR/grub/boot-grub2-grub.cfg" \
|
||||
"$WORK_DIR/boot/grub2/grub.cfg"
|
||||
}
|
||||
|
||||
verify_workdir() {
|
||||
echo "Verifying workdir..."
|
||||
|
||||
grep -q "Tuxflotte" "$WORK_DIR/EFI/BOOT/grub.cfg"
|
||||
grep -q "Tuxflotte" "$WORK_DIR/boot/grub2/grub.cfg"
|
||||
|
||||
echo "GRUB verification passed."
|
||||
}
|
||||
|
||||
prepare_updates() {
|
||||
echo "Assembling updates payload..."
|
||||
|
||||
local updates_dir="$WORK_DIR/updates"
|
||||
|
||||
rm -rf "$updates_dir"
|
||||
mkdir -p "$updates_dir/opt/tuxflotte"
|
||||
|
||||
cp -a "$REPO_DIR/scripts" "$updates_dir/opt/tuxflotte/"
|
||||
cp -a "$REPO_DIR/backends" "$updates_dir/opt/tuxflotte/"
|
||||
cp -a "$REPO_DIR/config" "$updates_dir/opt/tuxflotte/"
|
||||
}
|
||||
|
||||
create_iso() {
|
||||
echo "Creating Tuxflotte ISO..."
|
||||
|
||||
local output_iso="$OUTPUT_DIR/tuxflotte-provisioning-0.2.iso"
|
||||
|
||||
rm -f "$output_iso"
|
||||
|
||||
xorriso \
|
||||
-indev "$SOURCE_ISO" \
|
||||
-outdev "$output_iso" \
|
||||
-compliance no_emul_toc \
|
||||
-volid TUXFLOTTE \
|
||||
-map "$REPO_DIR/grub/EFI-BOOT-grub.cfg" /EFI/BOOT/grub.cfg \
|
||||
-map "$REPO_DIR/grub/boot-grub2-grub.cfg" /boot/grub2/grub.cfg \
|
||||
-map "$WORK_DIR/updates" /updates \
|
||||
-chown_r 0 /updates -- \
|
||||
-chgrp_r 0 /updates -- \
|
||||
-boot_image any replay
|
||||
|
||||
echo "ISO created: $output_iso"
|
||||
}
|
||||
|
||||
main() {
|
||||
check_input
|
||||
check_dependencies
|
||||
prepare_dirs
|
||||
extract_iso
|
||||
patch_grub
|
||||
verify_workdir
|
||||
prepare_updates
|
||||
create_iso
|
||||
|
||||
echo
|
||||
echo "Build complete."
|
||||
echo "Work dir: $WORK_DIR"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in new issue
Block a user