diff --git a/README.md b/README.md index ab08f65..2040e64 100644 --- a/README.md +++ b/README.md @@ -14,3 +14,24 @@ Ziele: - lokaler Festplattenstart Die eigentliche Provisionierung erfolgt über den Tuxflotte Provisioning Server. + +## Boot-Medium (Mint) + +Das Mint-Boot-Medium ist ein eigenständiges, per Debian `live-build` +gebautes Image (`boot-medium/`, siehe ADR-0025) - kein gepatchter +Distributions-Installer mehr. Es enthält nur Tuxflottes eigenen, +headless-tauglichen Code (Module `scripts/modules/00`-`40`, +`backends/mint-image/`) und bootet direkt in einen systemd-Dienst, der +`installer.sh` startet. + +- `scripts/build_boot_medium.sh [--dev]` baut das Basis-Image + (`boot-medium/live-image-amd64.hybrid.iso`). `--dev` aktiviert einen + SSH-Debug-Zugang (`tuxflotte`/`test123`); ohne `--dev` bleibt SSH + deaktiviert (Produktiv-Default). +- `scripts/build_customer_iso.sh [wifi_ssid] [wifi_psk] [volid]` + 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 fedora`) - noch nicht auf dasselbe +Boot-Medium-Muster umgestellt. diff --git a/backends/mint/backend.sh b/backends/mint/backend.sh deleted file mode 100644 index d24728c..0000000 --- a/backends/mint/backend.sh +++ /dev/null @@ -1,454 +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="mint" - -BACKEND_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PRESEED_TEMPLATE="${BACKEND_DIR}/preseed.tpl" -POSTINSTALL_SCRIPT="${BACKEND_DIR}/postinstall.sh" - -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()/postinstall.sh). -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() { - # jq/envsubst(gettext-base)/cpio/kexec-tools sind auf dem Live-Medium - # selbst (anders als im Zielsystem, siehe pkgsel/include in preseed.tpl) - # nicht vorinstalliert - real gegen das Live-Abbild verifiziert - # (Phase-1-Spike, zunächst nur für kexec-tools behoben, hier auf alle - # vier Live-only-Werkzeuge ausgeweitet). base64 kommt aus coreutils und - # ist auf jedem Debian-Derivat immer vorhanden, deshalb ohne Nachinstal- - # lationspfad. - local live_packages_needed=() - - command -v jq >/dev/null 2>&1 || live_packages_needed+=(jq) - command -v envsubst >/dev/null 2>&1 || live_packages_needed+=(gettext-base) - command -v cpio >/dev/null 2>&1 || live_packages_needed+=(cpio) - command -v kexec >/dev/null 2>&1 || live_packages_needed+=(kexec-tools) - - if [[ "${#live_packages_needed[@]}" -gt 0 ]]; then - backend_log "Werkzeuge fehlen auf dem Live-Medium, installiere nach: ${live_packages_needed[*]}" - - sed -i '/^deb cdrom/d' /etc/apt/sources.list 2>/dev/null || true - rm -f /etc/apt/sources.list.d/*cdrom* 2>/dev/null || true - - apt-get update -qq || - { backend_fatal "apt-get update fehlgeschlagen."; return 1; } - DEBIAN_FRONTEND=noninteractive apt-get install -y "${live_packages_needed[@]}" || - { backend_fatal "Installation fehlender Werkzeuge fehlgeschlagen."; return 1; } - fi - - command -v base64 >/dev/null 2>&1 || - { backend_fatal "Benötigtes Werkzeug fehlt: base64"; return 1; } - - [[ -r "${PRESEED_TEMPLATE}" ]] || - { backend_fatal "Preseed-Template nicht gefunden: ${PRESEED_TEMPLATE}"; return 1; } - - [[ -r "${POSTINSTALL_SCRIPT}" ]] || - { backend_fatal "Postinstall-Skript nicht gefunden: ${POSTINSTALL_SCRIPT}"; 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 == "object") - and (.secure_boot_required | type == "boolean") - ' "${RUNTIME_BLUEPRINT_FILE}" >/dev/null || - { backend_fatal "Installationszeitliche Vorgaben fehlen oder sind ungültig."; return 1; } - - # disk_encryption wird für Mint (noch) nicht unterstützt - kein getesteter - # LUKS-Preseed-Mechanismus (anders als Fedoras "autopart --encrypted"). - if [[ "$(jq --raw-output '.runtime_blueprint.installation_directives.disk_encryption' "${RUNTIME_BLUEPRINT_FILE}")" == "true" ]]; then - backend_fatal "disk_encryption=true wird vom Mint-Backend derzeit nicht unterstützt." - return 1 - fi - - backend_log "Runtime Blueprint ist gültig für Backend '${BACKEND_KEY}'." -} - - -# Baut einen einzelnen partman-auto/expert_recipe-Partitionsblock als -# EINZEILIGEN String (Felder durch Leerzeichen statt Zeilenumbrueche -# getrennt) - Debconf-Preseed-Werte mit eingebetteten Zeilenumbruechen -# brechen leicht lautlos (siehe base64-Kommentar bei success_command weiter -# unten fuer denselben Fallstrick an anderer Stelle), partmans Parser selbst -# ist bei Leerzeichen als Trenner tolerant. -_tuxflotte_partman_stanza() { - local size_mb="$1" - local filesystem="$2" - local mountpoint="$3" - local extra_flags="${4:-}" - - printf '%s %s %s %s %s method{ format } format{ } use_filesystem{ } filesystem{ %s } mountpoint{ %s } . ' \ - "${size_mb}" "${size_mb}" "${size_mb}" "${filesystem}" "${extra_flags}" "${filesystem}" "${mountpoint}" -} - -# Ermittelt den ersten echten Datentraeger des Zielgeraets fuer die -# Groessenberechnung bei prozentualer Partitionierung (Fedoras autopart macht -# implizit dieselbe Ein-Datentraeger-Annahme, siehe fedora/backend.sh). -# Groessenfilter (>0) und Namensausschluss noetig - reale Systeme koennen -# nbd-/zram-/loop-Geraete mit type=="disk" aber ohne echte Speicherkapazitaet -# auflisten, die sonst faelschlich vor dem echten Zieldatentraeger gewaehlt -# wuerden (real beim Testen entdeckt). -_tuxflotte_detect_target_disk() { - lsblk --nodeps --noheadings --bytes --output NAME,TYPE,SIZE --paths | - awk '$2 == "disk" && $3 > 0 && $1 !~ /(nbd|zram|loop)[0-9]*$/ { print $1; exit }' -} - -# Baut den kompletten partman-auto/expert_recipe-Rezeptkoerper aus dem -# installation_directives.partitioning-Objekt. Prozentangaben werden anhand -# der realen Zieldatentraegergroesse (erst hier, live auf dem Zielgeraet, -# bekannt - nicht beim ISO-Bau) in feste MB-Groessen umgerechnet. Bewusst -# feste Groessen (min=priority=max) statt partmans eigener proportionaler -# Prioritaets-Verteilung - deterministischer und leichter zu verifizieren. -_tuxflotte_render_partman_recipe() { - local partitioning_json="$1" - local root_filesystem="$2" - local scheme - local disk_device - local disk_size_mb - local extra_count - local extra_percent_sum=0 - local root_mb - local recipe_body="" - local i - local mountpoint - local filesystem - local percent - local size_mb - local esp_mb=0 - local bios_grub_mb=0 - local root_extra_flags - - scheme="$(jq --raw-output '.scheme // "single"' <<<"${partitioning_json}")" - - disk_device="$(_tuxflotte_detect_target_disk)" - [[ -n "${disk_device}" ]] || - { backend_fatal "Zieldatenträger konnte nicht ermittelt werden."; return 1; } - disk_size_mb="$(( $(blockdev --getsize64 "${disk_device}") / 1024 / 1024 ))" - - # Die eingebauten partman-Recipes ("atomic" etc.) legen auf UEFI-Systemen - # automatisch eine EFI-System-Partition an - ein eigenes expert_recipe - # muss das selbst tun, sonst warnt/verweigert der Installer (real beim - # Testen entdeckt: "No EFI System Partition was found"). 512 MB vorab - # reserviert, vor der Prozentaufteilung der restlichen Platte. - if [[ -d /sys/firmware/efi ]]; then - # Exakte Stanza-Form aus der eingebauten "atomic"-Recipe uebernommen - # (/usr/lib/partman/recipes-amd64-efi/30atomic auf dem Live-Medium - # ausgelesen) - eine erste eigene Vermutung ohne $reusemethod{ } und - # mit $bootable{ } wurde von partman zwar anstandslos geparst, aber - # nicht als gueltige EFI-System-Partition erkannt ("No EFI System - # Partition was found", real beim Testen entdeckt). - esp_mb=512 - disk_size_mb="$(( disk_size_mb - esp_mb ))" - recipe_body="${esp_mb} ${esp_mb} ${esp_mb} fat32 \$reusemethod{ } \$primary{ } method{ efi } format{ } . " - # Root NICHT zusaetzlich $bootable{ } markieren wie im BIOS-Zweig - # unten (real beim Testen entdeckt, 29.08.2026): auf UEFI traegt - # bereits die ESP-Stanza oben die eigentliche Boot-Kennzeichnung - # (method{ efi }) - das im Original-Rezept - # /usr/lib/partman/recipes-amd64-efi/30atomic (Quelle der - # ESP-Stanza) uebernommene Wurzel-Partitionsschema markiert die - # Root-Partition dort ebenfalls NICHT als bootable. Ein - # zusaetzliches $bootable{ } auf der Root-Partition scheint partman - # in einen Zustand zu bringen, den es nach dem Commit staendig neu - # bewerten will: der Installer klickte "Jetzt installieren" - # nachweislich korrekt (Debug-Log erreichte sogar - # "grub-installer/bootdev seen"), sprang aber danach immer wieder - # zurueck auf dieselbe Partitionierungsseite (ubi-partman.py: - # rebuild_cache(), ausgeloest durch die wiederholt gestellte - # Debconf-Frage "ubiquity/partman-rebuild-cache" aus - # /lib/partman/update.d/99signal_ubiquity). Noch nicht abschliessend - # verifiziert, ob dies die alleinige Ursache ist - siehe - # ADR-0023-Nachtrag. - root_extra_flags='$primary{ }' - else - # Analoges Pendant fuer reinen BIOS-Betrieb: partman legt den - # Datentraeger auch ohne EFI offenbar als GPT an (real beim Testen - # bestaetigt: freier Speicher vor Partition 1 und nach der letzten - # Partition ist die GPT-Kopfdaten-Signatur, kein MSDOS-Layout). GPT + - # BIOS-Boot braucht eine kleine unformatierte Boot-Partition fuer den - # GRUB-Core, sonst schlaegt /usr/lib/partman/check.d/08biosgrub fehl - # und partman-partitioning/no_bootable_biosgrub sorgt fuer eine - # Endlosschleife zurueck ins choose_partition-Menue statt - # abzuschliessen (real beim Testen entdeckt und via 08biosgrub- - # Quelltext auf dem Live-Medium verifiziert - "true" bei dieser Frage - # bedeutet dort "Problem besteht weiterhin", nicht "trotzdem - # fortfahren", anders als bei den meisten uebrigen Boolean-Fragen in - # diesem Rezept). "$iflabel{ gpt }" macht die Stanza auf einem - # MSDOS-Datentraeger automatisch wirkungslos. - bios_grub_mb=1 - disk_size_mb="$(( disk_size_mb - bios_grub_mb ))" - recipe_body="${bios_grub_mb} ${bios_grub_mb} ${bios_grub_mb} free \$iflabel{ gpt } \$reusemethod{ } method{ biosgrub } . " - # Im BIOS-Zweig (anders als EFI oben) bleibt $bootable{ } auf der - # Root-Partition noetig - hier gibt es keine ESP, die diese Rolle - # uebernimmt. - root_extra_flags='$primary{ } $bootable{ }' - fi - - case "${scheme}" in - single) - root_mb="$(( disk_size_mb - 1024 ))" - [[ "${root_mb}" -ge 2048 ]] || - { backend_fatal "Zieldatenträger ist zu klein (${disk_size_mb} MB)."; return 1; } - - recipe_body="${recipe_body}$(_tuxflotte_partman_stanza "${root_mb}" "${root_filesystem}" "/" "${root_extra_flags}")" - ;; - custom) - extra_count="$(jq '.extra_partitions | length' <<<"${partitioning_json}")" - [[ "${extra_count}" -gt 0 ]] || - { backend_fatal "scheme=custom ohne extra_partitions angegeben."; return 1; } - - for ((i = 0; i < extra_count; i++)); do - mountpoint="$(jq --raw-output ".extra_partitions[${i}].mountpoint" <<<"${partitioning_json}")" - filesystem="$(jq --raw-output ".extra_partitions[${i}].filesystem" <<<"${partitioning_json}")" - percent="$(jq --raw-output ".extra_partitions[${i}].percent" <<<"${partitioning_json}")" - - case "${mountpoint}" in - /home|/var) ;; - *) backend_fatal "Nicht unterstützter Einhängepunkt: ${mountpoint}"; return 1 ;; - esac - case "${filesystem}" in - ext4|btrfs) ;; - *) backend_fatal "Nicht unterstütztes Dateisystem: ${filesystem}"; return 1 ;; - esac - - extra_percent_sum="$(( extra_percent_sum + percent ))" - done - - [[ "${extra_percent_sum}" -gt 0 && "${extra_percent_sum}" -lt 90 ]] || - { backend_fatal "Summe der Partitions-Prozentangaben ist ungültig: ${extra_percent_sum}"; return 1; } - - root_mb="$(( disk_size_mb * (100 - extra_percent_sum) / 100 - 1024 ))" - [[ "${root_mb}" -ge 2048 ]] || - { backend_fatal "Root-Partition wäre bei dieser Aufteilung zu klein."; return 1; } - - recipe_body="${recipe_body}$(_tuxflotte_partman_stanza "${root_mb}" "${root_filesystem}" "/" "${root_extra_flags}")" - - for ((i = 0; i < extra_count; i++)); do - mountpoint="$(jq --raw-output ".extra_partitions[${i}].mountpoint" <<<"${partitioning_json}")" - filesystem="$(jq --raw-output ".extra_partitions[${i}].filesystem" <<<"${partitioning_json}")" - percent="$(jq --raw-output ".extra_partitions[${i}].percent" <<<"${partitioning_json}")" - size_mb="$(( disk_size_mb * percent / 100 ))" - - recipe_body="${recipe_body}$(_tuxflotte_partman_stanza "${size_mb}" "${filesystem}" "${mountpoint}")" - done - ;; - *) - backend_fatal "Nicht unterstütztes Partitionierungsschema: ${scheme}" - return 1 - ;; - esac - - printf 'tuxflotte :: %s' "${recipe_body}" -} - -backend_generate_config() { - local hostname - local device_id - local partitioning_json - local root_filesystem - local secure_boot_required - local partman_recipe - local blueprints_json - local postinstall_rendered - local postinstall_b64 - - [[ -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 postinstall.sh) - 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; } - - partitioning_json="$(jq --compact-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}")" - - root_filesystem="$(jq --raw-output '.root_filesystem // "ext4"' <<<"${partitioning_json}")" - case "${root_filesystem}" in - ext4|btrfs) ;; - *) backend_fatal "Nicht unterstütztes Root-Dateisystem: ${root_filesystem}"; return 1 ;; - esac - - partman_recipe="$(_tuxflotte_render_partman_recipe "${partitioning_json}" "${root_filesystem}")" || - return 1 - - if [[ "${secure_boot_required}" == "true" ]]; then - backend_log "Hinweis: secure_boot_required=true wird derzeit nicht in der Preseed-Konfiguration durchgesetzt (Phase 1)." - fi - - blueprints_json="$(jq --compact-output '.runtime_blueprint.blueprints' "${RUNTIME_BLUEPRINT_FILE}")" - - # Erste Stufe: postinstall.sh-Platzhalter auflösen. - postinstall_rendered="$( - TUXFLOTTE_DEVICE_ID="${device_id}" \ - TUXFLOTTE_BLUEPRINTS_JSON="${blueprints_json}" \ - TUXFLOTTE_DEVICE_FINGERPRINT="${device_fingerprint}" \ - envsubst '${TUXFLOTTE_DEVICE_ID} ${TUXFLOTTE_BLUEPRINTS_JSON} ${TUXFLOTTE_DEVICE_FINGERPRINT}' \ - <"${POSTINSTALL_SCRIPT}" - )" - - if grep -q '\${TUXFLOTTE_' <<<"${postinstall_rendered}"; then - backend_fatal "postinstall.sh enthält nach envsubst nicht aufgelöste Platzhalter." - return 1 - fi - - # base64-Kodierung: mehrzeilige/zitierte Preseed-Werte brechen unter - # Debconf lautlos (real erprobt, siehe backends/mint/wlan-test.seed) - - # als einzeiliger Base64-Blob besteht der success_command-Wert nur noch - # aus unkritischen Zeichen. - postinstall_b64="$(printf '%s' "${postinstall_rendered}" | base64 -w0)" - - # Zweite Stufe: preseed.tpl mit allen Werten inkl. des fertigen Base64-Blobs auflösen. - TUXFLOTTE_HOSTNAME="${hostname}" \ - TUXFLOTTE_PARTMAN_RECIPE="${partman_recipe}" \ - TUXFLOTTE_POSTINSTALL_B64="${postinstall_b64}" \ - envsubst '${TUXFLOTTE_HOSTNAME} ${TUXFLOTTE_PARTMAN_RECIPE} ${TUXFLOTTE_POSTINSTALL_B64}' \ - <"${PRESEED_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() { - local cdrom_vmlinuz="/cdrom/casper/vmlinuz" - local cdrom_initrd="/cdrom/casper/initrd.lz" - local extra_initrd_dir="${RUNTIME_DIR}/initrd-extra" - local extra_cpio="${RUNTIME_DIR}/extra.cpio.gz" - local custom_initrd="${RUNTIME_DIR}/initrd-custom.lz" - - [[ -r "${cdrom_vmlinuz}" && -r "${cdrom_initrd}" ]] || - { backend_fatal "Casper-Kernel/-Initrd nicht gefunden unter /cdrom/casper."; return 1; } - - # Das personalisierte Preseed (CONFIG_FILE, erst live auf diesem Gerät - # erzeugt - Hostname/Geräte-ID/Partitionierung sind erst hier bekannt, - # nicht schon beim ISO-Bau) kann nicht per file=/cdrom/... übergeben - # werden (read-only Medium, Inhalt seit ISO-Bau fixiert) und auch nicht - # per url= von einem selbst gestarteten lokalen Server - der komplette - # Prozess- und Netzwerkzustand dieser Sitzung geht beim Kexec-Sprung - # verloren, ein soeben gestarteter HTTP-Server koennte die neue - # Boot-Umgebung also nicht mehr bedienen. Stattdessen wird das Preseed in - # eine zusaetzliche Initrd-Schicht eingebettet: der Kernel unterstuetzt - # aneinandergehaengte cpio-Archive als initramfs (spaetere Archive - # ergaenzen fruehere), das uebersteht den Kexec-Uebergang unveraendert. - # Real gegen QEMU verifiziert (Phase-1-Spike, beide Ansaetze getestet). - rm -rf "${extra_initrd_dir}" - install -d --mode=0700 --owner=root --group=root "${extra_initrd_dir}" - cp "${CONFIG_FILE}" "${extra_initrd_dir}/preseed.cfg" - - (cd "${extra_initrd_dir}" && find . | cpio -o -H newc 2>/dev/null | gzip) \ - >"${extra_cpio}" || - { backend_fatal "Preseed-Initrd-Schicht konnte nicht gebaut werden."; return 1; } - - cat "${cdrom_initrd}" "${extra_cpio}" >"${custom_initrd}" || - { backend_fatal "Initrd konnte nicht zusammengesetzt werden."; return 1; } - - backend_log "Lade Kexec-Ziel fuer automatisierten Ubiquity-Start." - - # Ubiquitys eigenes "noninteractive"-Frontend (ubiquity/frontend/ - # noninteractive.py, ueber das gleichnamige Boot-Keyword ausgewaehlt) - # arbeitet zwar rein ueber Debconf ohne je ein Fenster zu zeichnen, aber - # dessen Seite fuer die gefuehrte Partitionierung (ubi-partman.py) haengt - # sich bei einem vollstaendig vorbefuellten Rezept in einer echten - # Endlosschleife auf (staendiges Neuaufbauen des choose_partition-Menues, - # "partman/confirm" wird nie erreicht - real ueber >800 Wiederholungen - # ohne Fortschritt bestaetigt, siehe ADR-0023-Nachtrag). Ursache: die - # PageNoninteractive-Klasse liefert fuer etliche vom GTK-Codepfad - # benoetigte Rueckfragen (get_autopartition_choice(), get_crypto_keys()) - # nur "pass"/None statt echter Werte. - # - # Deshalb bewusst zurueck auf "automatic-ubiquity" (echte GTK-Oberflaeche, - # PageGtk-Klasse - der von Ubiquity selbst getestete, produktiv genutzte - # Codepfad, auch fuer die Partitionierung). Der GTK-Assistent fuellt jede - # Seite aus dem Preseed vor, wartet aber weiterhin auf einen "Weiter"-Klick - # pro Seite (real verifiziert, siehe ADR-0023-Nachtrag) - dafuer laeuft - # zusaetzlich autoclicker.sh (live-updates/opt/tuxflotte/scripts/), per - # systemd-Service und ausgeloest durch das eigene Boot-Keyword - # "tuxflotte-autoclick" (harmlos bei jedem anderen Boot ohne dieses - # Keyword). "debug-ubiquity" (setzt debug="-d") macht - # /var/log/installer/debug ausfuehrlicher, hilfreich bei weiterer - # Fehlersuche. - # username=/hostname=mint bewusst ergaenzt (real beim Testen entdeckt, - # 29.08.2026): ohne diese beiden Parameter faellt casper auf dem - # kexec-Boot auf einen anderen Live-Account-Zustand zurueck als beim - # ersten Boot (der die grub.cfg-Vorlage explizit mit "username=mint - # hostname=mint" startet) - konkret verlangt der Konsolenlogin auf - # diesem zweiten Boot ein echtes Passwort statt des sonst leeren - # Live-Session-Passworts. Fuer den eigentlichen Auto-Install-Ablauf - # (GTK-Assistent unter ubiquity-dm, kein Konsolenlogin noetig) - # folgenlos, aber inkonsistent gegenueber dem ersten Boot und erschwert - # die Fehlersuche via Konsole unnoetig - deshalb hier angeglichen. - kexec -l "${cdrom_vmlinuz}" \ - --initrd="${custom_initrd}" \ - --append="boot=casper automatic-ubiquity tuxflotte-autoclick debug-ubiquity noprompt file=/preseed.cfg debian-installer/language=de keyboard-configuration/layoutcode=de username=mint hostname=mint quiet splash ---" || - { backend_fatal "kexec -l fehlgeschlagen."; return 1; } - - backend_log "Starte unbeaufsichtigte Installation (kexec -e). Kein Ruecksprung erwartet - ab hier laeuft die eigentliche Installation im neuen Kernel weiter." - - kexec -e -} - -backend_postinstall() { - backend_log "Provisioning-Agent-Einrichtung erfolgt im ubiquity/success_command der Preseed-Konfiguration (Agent-Abruf, Bootstrap-Registrierung, systemd-Aktivierung)." -} diff --git a/backends/mint/early-command-test-FAILED.sh b/backends/mint/early-command-test-FAILED.sh deleted file mode 100644 index 27da3c6..0000000 --- a/backends/mint/early-command-test-FAILED.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -{ - echo "tuxflotte: early_command lief, $(date -u)" - echo "--- ip link ---" - ip link 2>&1 - echo "--- nmcli device status (vorher) ---" - nmcli device status 2>&1 - echo "--- WLAN verbinden (mit Wiederholung, falls Treiber noch nicht bereit) ---" - for i in 1 2 3 4 5 6; do - nmcli device wifi rescan 2>&1 - sleep 2 - if nmcli device wifi connect stallinux password a987654321 2>&1; then - echo "WLAN verbunden nach Versuch $i" - break - fi - echo "Versuch $i fehlgeschlagen, warte..." - sleep 5 - done - echo "--- nmcli device status (nachher) ---" - nmcli device status 2>&1 - echo "--- curl anode /health ---" - curl -m 10 -sS https://anode.tuxflotte.de/health 2>&1 - echo - echo "--- debconf-set-selections Test (simuliert dynamisch von anode geholten Wert) ---" - echo "d-i netcfg/get_hostname string tuxflotte-early-test" | debconf-set-selections - echo "debconf-set-selections exit: $?" - echo "--- Verifikation per debconf-communicate ---" - echo "GET netcfg/get_hostname" | debconf-communicate 2>&1 -} >> /var/log/tuxflotte-early-command.log 2>&1 diff --git a/backends/mint/postinstall.sh b/backends/mint/postinstall.sh deleted file mode 100644 index f20f032..0000000 --- a/backends/mint/postinstall.sh +++ /dev/null @@ -1,72 +0,0 @@ -#!/bin/bash -# Lesbare Referenzfassung des Agent-Bootstraps, den backend_generate_config() -# in backend.sh zur Laufzeit envsubst-auflöst und anschließend base64-kodiert -# in preseed.tpls ubiquity/success_command einsetzt (siehe backend.sh). Diese -# Datei selbst wird nie direkt ausgeführt - sie existiert, damit der Code -# lesbar bleibt statt nur als Base64-Blob im Preseed zu existieren. -# -# Inhaltlich das Bash-Pendant zu backends/fedora/kickstart.tpl %post: gleiche -# curl/jq-Aufrufe, nur eingebettet über ubiquity/success_command (in-target, -# chrooted) statt Kickstart %post. -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 -m 0700 /etc/tuxflotte || - tuxflotte_agent_fatal "Verzeichnis /etc/tuxflotte konnte nicht angelegt werden." - -# 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 || - tuxflotte_agent_fatal "device_fingerprint konnte nicht abgelegt werden." - -cat > /etc/tuxflotte/runtime_blueprint.json <<'RUNTIME_BLUEPRINT_EOF' -${TUXFLOTTE_BLUEPRINTS_JSON} -RUNTIME_BLUEPRINT_EOF - -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 diff --git a/backends/mint/preseed.tpl b/backends/mint/preseed.tpl deleted file mode 100644 index 1abebbd..0000000 --- a/backends/mint/preseed.tpl +++ /dev/null @@ -1,137 +0,0 @@ -### Tuxflotte Auto-Install Preseed fuer Linux Mint (Ubiquity/Debian-Installer). -### Liegt direkt auf dem Medium (file=/cdrom/preseed/tuxflotte.seed), keine -### Netz-Zustellung noetig -- analog zu Fedoras inst.ks=cdrom:/ks.cfg. -### -### d-i preseed/early_command wird bewusst NICHT verwendet -- unter Ubiquity -### bestaetigt wirkungslos (Ubiquity nutzt eigene Python-Plugins statt der -### klassischen Debian-Installer-Komponenten, an die early_command haengt). - -d-i debian-installer/locale string de_DE.UTF-8 -d-i keyboard-configuration/xkb-keymap select de -d-i keyboard-configuration/layoutcode string de - -d-i netcfg/get_hostname string ${TUXFLOTTE_HOSTNAME} -d-i netcfg/get_domain string unassigned-domain - -# Lab-Bootstrap-Zugangsdaten. Ersetzt ein noch fehlendes Secret-Reference-Modell -# (siehe 09-data-model-v1.md) und darf nicht als Produktionsmechanismus gelten. -d-i passwd/user-fullname string Tuxflotte -d-i passwd/username string tuxflotte -d-i passwd/user-password password test123 -d-i passwd/user-password-again password test123 -d-i user-setup/allow-password-weak boolean true - -d-i clock-setup/utc boolean true -d-i time/zone string Europe/Berlin -d-i clock-setup/ntp boolean true - -d-i partman-auto/method string regular -d-i partman-auto/expert_recipe string ${TUXFLOTTE_PARTMAN_RECIPE} -d-i partman-auto/choose_recipe select tuxflotte -d-i partman-partitioning/confirm_write_new_label boolean true -d-i partman-partitioning/confirm_new_label boolean true -# "partman/choose_partition select finish" wurde bewusst entfernt: das ist -# die Frage des MANUELLEN/erweiterten Partitionierers ("Menu" -> "Finish -# partitioning"), keine des gefuehrten/automatischen Ablaufs. Direktes -# Preseeden ohne echten Seitenaufbau (weder im GTK- noch im -# noninteractive-Frontend) fuehrt in ubi-partman.py real reproduzierbar zu -# einer Endlosschleife im internen "building_cache"-Zustandsautomaten der -# choose_partition-Verarbeitung (ueber 100.000 Debconf-Zeilen in wenigen -# Sekunden ohne echten Fortschritt, sowohl mit automatic-ubiquity/GTK als -# auch mit dem verworfenen noninteractive-Frontend - siehe ADR-0023-Nachtrag). -# Ohne diese Zeile uebernehmen partman-auto/method + expert_recipe + -# choose_recipe (oben) die gefuehrte Partitionierung auf dem dafuer -# vorgesehenen Weg. -d-i partman/confirm boolean true -d-i partman/confirm_nochanges boolean true -d-i partman/confirm_nooverwrite boolean true -d-i partman/unmount_active boolean true -d-i partman/automount boolean true -d-i partman/filter_mounted boolean true -d-i partman-partitioning/confirm_resize boolean true -d-i partman-ext3/lazy_itable_init boolean true -d-i partman/boot_not_first_partition boolean true -d-i partman-basicfilesystems/boot_not_first_partition boolean true -d-i partman-basicfilesystems/boot_not_ext2 boolean true -d-i partman-ext3/boot_not_bootable boolean true -d-i partman-ext3/boot_not_ext2_or_ext3 boolean true -d-i partman-basicfilesystems/no_mount_point boolean true -d-i partman-basicfilesystems/no_swap boolean true -d-i partman-basicfilesystems/check_failed boolean true -d-i partman-basicfilesystems/swap_check_failed boolean true -d-i partman-ext3/bad_alignment boolean true -# Dieselbe Polaritaets-Falle wie bei no_bootable_biosgrub weiter unten (siehe -# dortiger Kommentar) - "true" hiesse "Problem besteht wirklich, abbrechen". -# Fuer UEFI-Zielgeraete legt _tuxflotte_render_partman_recipe() bereits eine -# echte ESP an, dieser Fallback sollte also nie greifen. -d-i partman-partitioning/no_bootable_efi boolean false -# Anders als die meisten uebrigen Boolean-Fragen hier bedeutet "true" bei -# no_bootable_biosgrub NICHT "trotzdem fortfahren", sondern "das Problem -# besteht wirklich" -> der pruefende Skript (check.d/08biosgrub) bricht dann -# mit exit 1 ab, was zur Endlosschleife zurueck ins choose_partition-Menue -# fuehrt (real entdeckt und via Quelltext auf dem Live-Medium verifiziert, -# siehe ADR-0023-Nachtrag). Der eigentliche Fix ist eine echte BIOS-Boot- -# Partition im Rezept (siehe _tuxflotte_render_partman_recipe() in -# backend.sh) - "false" hier bleibt nur als defensiver Fallback, falls die -# Partition aus irgendeinem Grund nicht als "biosgrub" erkannt wird. -d-i partman-partitioning/no_bootable_biosgrub boolean false -d-i partman-partitioning/bootable_logical boolean true -d-i partman-partitioning/unknown_label boolean true -d-i partman-partitioning/unsupported_label boolean true -d-i partman-basicmethods/method_only boolean true -d-i grub-installer/only_debian boolean true -d-i grub-installer/with_other_os boolean true -d-i grub-installer/make_active boolean true -d-i grub-installer/grub2_instead_of_grub_legacy boolean true -d-i grub-installer/grub_not_mature_on_this_platform boolean true -d-i grub-installer/multipath boolean true -d-i grub-installer/sataraid boolean true -# Wichtig: false, nicht true -- "skip" heisst hier woertlich "GRUB-Installation -# ueberspringen". true wuerde die Bootloader-Installation aktiv verhindern. -d-i grub-installer/skip boolean false -d-i partman-auto-lvm/no_boot boolean true -d-i partman-target/mount_failed boolean true -# partman-efi/no_efi wird ENTGEGEN der urspruenglichen Annahme sehr wohl -# gefragt, auch im reinen BIOS/SeaBIOS-Betrieb ohne NVRAM (real via -# debug-ubiquity-Log verifiziert, siehe ADR-0023-Nachtrag) -- Ubiquity prueft -# offenbar unabhaengig vom aktuellen Boot-Modus, ob eine EFI-System-Partition -# existiert. "false" heisst hier "trotzdem fortfahren" (die Alternative -# "true" wuerde zurueck ins Partitionierungsmenue springen und den Ablauf -# blockieren -- fuer ein bewusstes BIOS/MBR-Setup ohne EFI-Partition ist -# false die richtige Antwort). -d-i partman-efi/no_efi boolean false -# Bewusst weiterhin NICHT preseeded: grub-installer/force-efi-extra-removable -# (EFI-spezifisch, im BIOS-Betrieb ohne Wirkung) sowie partman-crypto/*, -# partman-lvm/*, partman-jfs/* (Recipe nutzt weder Crypto noch LVM noch JFS, -# koennen also nie auftreten; einige dieser Fragen sind bei "true" destruktiv -# (z.B. crypto_warn_erase), daher hier absichtlich nicht blind auf true -# gesetzt). - -ubiquity ubiquity/summary note -ubiquity ubiquity/reboot boolean true -ubiquity ubiquity/use_nonfree boolean true -# Ohne diese Zeile stuerzt Ubiquity im automatic-ubiquity-GTK-Modus real -# reproduzierbar ab (TypeError: Argument 1 does not allow None as a value, -# in ubi-prepare.py enable_download_updates() -> label_download_updates. -# set_label(), ausgeloest durch einen globalen Online-Status-Callback, der -# unabhaengig vom Automatik-Modus feuert, obwohl die zugehoerige Seite dort -# nie aufgebaut wird - die Widget-Referenz bleibt None). Die "Waehrend der -# Installation aktualisieren"-Option wird dadurch bewusst deaktiviert; -# funktional kein Verlust, da der Provisioning Agent das System nach der -# Ersteinrichtung ohnehin selbst aktuell haelt. -ubiquity ubiquity/download_updates boolean false - -# Pendant zu Fedoras kickstart.tpl %packages (ansible-core, git) - der -# Provisioning Agent braucht ansible-pull, das wiederum git zum Klonen des -# Ansible-Repos. Ohne diese Zeile fehlen beide auf einer frischen -# Mint-Installation, der Agent-Dienst laeuft dann in einer -# Restart-Fehlerschleife ("ansible-pull nicht gefunden") - real gegen eine -# frische Testinstallation gefunden und verifiziert (2026-08-04). -d-i pkgsel/include string ansible-core git - -# success_command laeuft in-target (gechrootet ins Zielsystem) nach der -# Paketinstallation, vor dem Reboot - das Pendant zu Kickstarts %post. Der -# Payload ist base64-kodiert (backend_generate_config() in backend.sh baut -# ihn aus postinstall.sh): mehrzeilige/zitierte Preseed-Werte brechen unter -# Debconf lautlos, Base64 umgeht das (real erprobt, siehe wlan-test.seed). -ubiquity ubiquity/success_command string in-target bash -c 'echo ${TUXFLOTTE_POSTINSTALL_B64} | base64 -d | bash' diff --git a/backends/mint/wlan-test-boot-grub.cfg b/backends/mint/wlan-test-boot-grub.cfg deleted file mode 100644 index acf9115..0000000 --- a/backends/mint/wlan-test-boot-grub.cfg +++ /dev/null @@ -1,41 +0,0 @@ -loadfont unicode - -set color_normal=white/black -set color_highlight=black/light-gray - -set timeout=30 - -menuentry "Start Linux Mint 22.3 Cinnamon 64-bit" --class linuxmint { - set gfxpayload=keep - linux /casper/vmlinuz boot=casper uuid=6e72f523-dc09-4880-8910-93ffa64401c5 username=mint hostname=mint iso-scan/filename=${iso_path} quiet splash -- - initrd /casper/initrd.lz -} -menuentry "Start Linux Mint 22.3 Cinnamon 64-bit (compatibility mode)" { - linux /casper/vmlinuz boot=casper uuid=6e72f523-dc09-4880-8910-93ffa64401c5 username=mint hostname=mint iso-scan/filename=${iso_path} noapic noacpi nosplash irqpoll nomodeset -- - initrd /casper/initrd.lz -} -menuentry "OEM install (for manufacturers)" { - set gfxpayload=keep - linux /casper/vmlinuz oem-config/enable=true only-ubiquity boot=casper uuid=6e72f523-dc09-4880-8910-93ffa64401c5 username=mint hostname=mint iso-scan/filename=${iso_path} quiet splash -- - initrd /casper/initrd.lz -} -menuentry "Tuxflotte Auto-Install (Linux Mint 22.3 Cinnamon)" --class linuxmint { - set gfxpayload=keep - linux /casper/vmlinuz boot=casper uuid=6e72f523-dc09-4880-8910-93ffa64401c5 username=mint hostname=mint iso-scan/filename=${iso_path} file=/cdrom/preseed/tuxflotte.seed automatic-ubiquity noprompt debian-installer/language=de keyboard-configuration/layoutcode=de quiet splash -- - initrd /casper/initrd.lz -} -grub_platform -if [ "$grub_platform" = "efi" ]; then -menuentry 'Von lokaler Festplatte booten (Standard)' { - exit 1 -} -set default="Von lokaler Festplatte booten (Standard)" -menuentry 'UEFI Firmware Settings' { - fwsetup -} -menuentry 'Memory test' { - linux /boot/memtest.efi -} -else -set default="0" -fi diff --git a/backends/mint/wlan-test-isolinux-live.cfg b/backends/mint/wlan-test-isolinux-live.cfg deleted file mode 100644 index 93fd5dc..0000000 --- a/backends/mint/wlan-test-isolinux-live.cfg +++ /dev/null @@ -1,57 +0,0 @@ -timeout 100 - -menu background splash.png -menu title Welcome to Linux Mint 22.3 64-bit - -menu color screen 37;40 #80ffffff #00000000 std -MENU COLOR border 30;44 #40ffffff #a0000000 std -MENU COLOR title 1;36;44 #ffffffff #a0000000 std -MENU COLOR sel 7;37;40 #e0ffffff #20ffffff all -MENU COLOR unsel 37;44 #50ffffff #a0000000 std -MENU COLOR help 37;40 #c0ffffff #a0000000 std -MENU COLOR timeout_msg 37;40 #80ffffff #00000000 std -MENU COLOR timeout 1;37;40 #c0ffffff #00000000 std -MENU COLOR msg07 37;40 #90ffffff #a0000000 std -MENU COLOR tabmsg 31;40 #ffDEDEDE #00000000 std -MENU WIDTH 78 -MENU MARGIN 15 -MENU ROWS 6 -MENU VSHIFT 10 -MENU TABMSGROW 12 -MENU CMDLINEROW 12 -MENU HELPMSGROW 16 -MENU HELPMSGENDROW 29 - -label tuxflotte - menu label Tuxflotte Auto-Install - kernel /casper/vmlinuz - append boot=casper initrd=/casper/initrd.lz uuid=6e72f523-dc09-4880-8910-93ffa64401c5 username=mint hostname=mint file=/cdrom/preseed/tuxflotte.seed automatic-ubiquity noprompt debian-installer/language=de keyboard-configuration/layoutcode=de quiet splash -- - -label live - menu label Start Linux Mint - kernel /casper/vmlinuz - append boot=casper initrd=/casper/initrd.lz uuid=6e72f523-dc09-4880-8910-93ffa64401c5 username=mint hostname=mint quiet splash -- - -label compat - menu label Start Linux Mint in compatibility mode - linux /casper/vmlinuz - append boot=casper initrd=/casper/initrd.lz uuid=6e72f523-dc09-4880-8910-93ffa64401c5 username=mint hostname=mint noapic noacpi nosplash irqpoll nomodeset -- - -label oem - menu label OEM install (for manufacturers) - linux /casper/vmlinuz - append oem-config/enable=true only-ubiquity boot=casper initrd=/casper/initrd.lz uuid=6e72f523-dc09-4880-8910-93ffa64401c5 username=mint hostname=mint quiet splash -- - -label hdt - menu label Hardware Detection - kernel hdt.c32 - -label local - menu label Boot from local drive - menu default - COM32 chain.c32 - APPEND hd0 - -label memtest - menu label Memory test - linux /boot/memtest.bin diff --git a/backends/mint/wlan-test-post-install.sh b/backends/mint/wlan-test-post-install.sh deleted file mode 100644 index a763433..0000000 --- a/backends/mint/wlan-test-post-install.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -{ - echo "tuxflotte: success_command lief, $(date -u)" - echo "--- nmcli device status (vorher) ---" - nmcli device status 2>&1 - echo "--- WLAN verbinden (live, fuer den anode-Test waehrend der Installation) ---" - nmcli device wifi rescan 2>&1 - sleep 3 - nmcli device wifi connect stallinux password a987654321 2>&1 - sleep 3 - echo "--- nmcli device status (nachher) ---" - nmcli device status 2>&1 - echo "--- curl anode /health ---" - curl -m 10 -sS https://anode.tuxflotte.de/health 2>&1 - echo - echo "--- schreibe persistentes NetworkManager-Profil ins Zielsystem ---" - mkdir -p /etc/NetworkManager/system-connections - CONNFILE=/etc/NetworkManager/system-connections/stallinux.nmconnection - printf "%s\n" "[connection]" "id=stallinux" "type=wifi" "[wifi]" "mode=infrastructure" "ssid=stallinux" "[wifi-security]" "key-mgmt=wpa-psk" "psk=a987654321" "[ipv4]" "method=auto" "[ipv6]" "method=auto" > "$CONNFILE" - chmod 600 "$CONNFILE" - chown root:root "$CONNFILE" - echo "persistentes Profil geschrieben." -} >> /var/log/tuxflotte-postinstall.log 2>&1 -echo "dvd-wlan-test (ADR-0009, Mint-Fortsetzung) -- provisioned by tuxflotte" > /etc/motd diff --git a/backends/mint/wlan-test.seed b/backends/mint/wlan-test.seed deleted file mode 100644 index 2c6204a..0000000 --- a/backends/mint/wlan-test.seed +++ /dev/null @@ -1,56 +0,0 @@ -### Test-Preseed fuer ADR-0009 Fortsetzung mit Mint/Ubuntu (31.07.2026-01.08.2026). -### Liegt direkt auf dem Medium (file=/cdrom/preseed/tuxflotte.seed), keine -### Netz-Zustellung noetig -- analog zu Fedoras inst.ks=cdrom:/ks.cfg. - -# Test 01.08.2026: laeuft VOR allen anderen Fragen (Partitionierung etc.), -# nicht gechrootet -- Ziel ist zu pruefen, ob so frueh schon WLAN herstellbar -# ist und ob debconf-set-selections tatsaechlich spaetere Fragen beeinflusst. -# Base64 von Anfang an (Lehre aus success_command Versuch 3 gestern). -d-i preseed/early_command string bash -c 'echo IyEvYmluL2Jhc2gKewogIGVjaG8gInR1eGZsb3R0ZTogZWFybHlfY29tbWFuZCBsaWVmLCAkKGRhdGUgLXUpIgogIGVjaG8gIi0tLSBpcCBsaW5rIC0tLSIKICBpcCBsaW5rIDI+JjEKICBlY2hvICItLS0gbm1jbGkgZGV2aWNlIHN0YXR1cyAodm9yaGVyKSAtLS0iCiAgbm1jbGkgZGV2aWNlIHN0YXR1cyAyPiYxCiAgZWNobyAiLS0tIFdMQU4gdmVyYmluZGVuIChtaXQgV2llZGVyaG9sdW5nLCBmYWxscyBUcmVpYmVyIG5vY2ggbmljaHQgYmVyZWl0KSAtLS0iCiAgZm9yIGkgaW4gMSAyIDMgNCA1IDY7IGRvCiAgICBubWNsaSBkZXZpY2Ugd2lmaSByZXNjYW4gMj4mMQogICAgc2xlZXAgMgogICAgaWYgbm1jbGkgZGV2aWNlIHdpZmkgY29ubmVjdCBzdGFsbGludXggcGFzc3dvcmQgYTk4NzY1NDMyMSAyPiYxOyB0aGVuCiAgICAgIGVjaG8gIldMQU4gdmVyYnVuZGVuIG5hY2ggVmVyc3VjaCAkaSIKICAgICAgYnJlYWsKICAgIGZpCiAgICBlY2hvICJWZXJzdWNoICRpIGZlaGxnZXNjaGxhZ2VuLCB3YXJ0ZS4uLiIKICAgIHNsZWVwIDUKICBkb25lCiAgZWNobyAiLS0tIG5tY2xpIGRldmljZSBzdGF0dXMgKG5hY2hoZXIpIC0tLSIKICBubWNsaSBkZXZpY2Ugc3RhdHVzIDI+JjEKICBlY2hvICItLS0gY3VybCBhbm9kZSAvaGVhbHRoIC0tLSIKICBjdXJsIC1tIDEwIC1zUyBodHRwczovL2Fub2RlLnR1eGZsb3R0ZS5kZS9oZWFsdGggMj4mMQogIGVjaG8KICBlY2hvICItLS0gZGViY29uZi1zZXQtc2VsZWN0aW9ucyBUZXN0IChzaW11bGllcnQgZHluYW1pc2NoIHZvbiBhbm9kZSBnZWhvbHRlbiBXZXJ0KSAtLS0iCiAgZWNobyAiZC1pIG5ldGNmZy9nZXRfaG9zdG5hbWUgc3RyaW5nIHR1eGZsb3R0ZS1lYXJseS10ZXN0IiB8IGRlYmNvbmYtc2V0LXNlbGVjdGlvbnMKICBlY2hvICJkZWJjb25mLXNldC1zZWxlY3Rpb25zIGV4aXQ6ICQ/IgogIGVjaG8gIi0tLSBWZXJpZmlrYXRpb24gcGVyIGRlYmNvbmYtY29tbXVuaWNhdGUgLS0tIgogIGVjaG8gIkdFVCBuZXRjZmcvZ2V0X2hvc3RuYW1lIiB8IGRlYmNvbmYtY29tbXVuaWNhdGUgMj4mMQp9ID4+IC92YXIvbG9nL3R1eGZsb3R0ZS1lYXJseS1jb21tYW5kLmxvZyAyPiYxCg== | base64 -d | bash' - -d-i debian-installer/locale string de_DE.UTF-8 -d-i keyboard-configuration/xkb-keymap select de -d-i keyboard-configuration/layoutcode string de - -d-i netcfg/get_hostname string tuxflotte-mint-test -d-i netcfg/get_domain string unassigned-domain - -d-i passwd/user-fullname string Tuxflotte -d-i passwd/username string tuxflotte -d-i passwd/user-password password test123 -d-i passwd/user-password-again password test123 -d-i user-setup/allow-password-weak boolean true - -d-i clock-setup/utc boolean true -d-i time/zone string Europe/Berlin -d-i clock-setup/ntp boolean true - -d-i partman-auto/method string regular -d-i partman-auto/choose_recipe select atomic -d-i partman-partitioning/confirm_write_new_label boolean true -d-i partman/choose_partition select finish -d-i partman/confirm boolean true -d-i partman/confirm_nooverwrite boolean true - -ubiquity ubiquity/summary note - -# Versuch 4: kein automatischer Reboot mehr, damit wir vor dem Neustart aus -# der Live-Sitzung heraus direkt unter /target/... nachsehen koennen, ob -# alles geschrieben wurde -- auf Vorschlag des Nutzers. -ubiquity ubiquity/reboot boolean false - -# Versuch 1: wlp9s0 (Intel AX210) erkannt, aber nicht verbunden (keine -# Zugangsdaten). Versuch 2: nmcli verbindet + anode per curl erreichbar -# WAEHREND der Installation -- funktioniert. Verbindung ueberlebte den -# Reboot nicht (nmcli sprach vermutlich mit der Live-NetworkManager-Instanz, -# nicht mit einer, die ins Zielsystem schreibt). Versuch 3: direktes -# Schreiben der .nmconnection-Datei als eigener Preseed-Wert -- Datei kam -# nie an, kein Log vorhanden, vermutlich Debconf-Problem mit einem so -# langen, mehrzeiligen Preseed-Wert (lokaler Bash-Syntaxtest war fehlerfrei, -# also kein Bash-Problem). Versuch 4 (dieser): dasselbe Skript Base64- -# kodiert -- der Preseed-Wert besteht dadurch nur noch aus unkritischen -# Zeichen, keine Anfuehrungszeichen/Klammern mehr, die Debconf Probleme -# machen koennten. -ubiquity ubiquity/use_nonfree boolean true - -ubiquity ubiquity/success_command string in-target bash -c 'echo IyEvYmluL2Jhc2gKewogIGVjaG8gInR1eGZsb3R0ZTogc3VjY2Vzc19jb21tYW5kIGxpZWYsICQoZGF0ZSAtdSkiCiAgZWNobyAiLS0tIG5tY2xpIGRldmljZSBzdGF0dXMgKHZvcmhlcikgLS0tIgogIG5tY2xpIGRldmljZSBzdGF0dXMgMj4mMQogIGVjaG8gIi0tLSBXTEFOIHZlcmJpbmRlbiAobGl2ZSwgZnVlciBkZW4gYW5vZGUtVGVzdCB3YWVocmVuZCBkZXIgSW5zdGFsbGF0aW9uKSAtLS0iCiAgbm1jbGkgZGV2aWNlIHdpZmkgcmVzY2FuIDI+JjEKICBzbGVlcCAzCiAgbm1jbGkgZGV2aWNlIHdpZmkgY29ubmVjdCBzdGFsbGludXggcGFzc3dvcmQgYTk4NzY1NDMyMSAyPiYxCiAgc2xlZXAgMwogIGVjaG8gIi0tLSBubWNsaSBkZXZpY2Ugc3RhdHVzIChuYWNoaGVyKSAtLS0iCiAgbm1jbGkgZGV2aWNlIHN0YXR1cyAyPiYxCiAgZWNobyAiLS0tIGN1cmwgYW5vZGUgL2hlYWx0aCAtLS0iCiAgY3VybCAtbSAxMCAtc1MgaHR0cHM6Ly9hbm9kZS50dXhmbG90dGUuZGUvaGVhbHRoIDI+JjEKICBlY2hvCiAgZWNobyAiLS0tIHNjaHJlaWJlIHBlcnNpc3RlbnRlcyBOZXR3b3JrTWFuYWdlci1Qcm9maWwgaW5zIFppZWxzeXN0ZW0gLS0tIgogIG1rZGlyIC1wIC9ldGMvTmV0d29ya01hbmFnZXIvc3lzdGVtLWNvbm5lY3Rpb25zCiAgQ09OTkZJTEU9L2V0Yy9OZXR3b3JrTWFuYWdlci9zeXN0ZW0tY29ubmVjdGlvbnMvc3RhbGxpbnV4Lm5tY29ubmVjdGlvbgogIHByaW50ZiAiJXNcbiIgIltjb25uZWN0aW9uXSIgImlkPXN0YWxsaW51eCIgInR5cGU9d2lmaSIgIlt3aWZpXSIgIm1vZGU9aW5mcmFzdHJ1Y3R1cmUiICJzc2lkPXN0YWxsaW51eCIgIlt3aWZpLXNlY3VyaXR5XSIgImtleS1tZ210PXdwYS1wc2siICJwc2s9YTk4NzY1NDMyMSIgIltpcHY0XSIgIm1ldGhvZD1hdXRvIiAiW2lwdjZdIiAibWV0aG9kPWF1dG8iID4gIiRDT05ORklMRSIKICBjaG1vZCA2MDAgIiRDT05ORklMRSIKICBjaG93biByb290OnJvb3QgIiRDT05ORklMRSIKICBlY2hvICJwZXJzaXN0ZW50ZXMgUHJvZmlsIGdlc2NocmllYmVuLiIKfSA+PiAvdmFyL2xvZy90dXhmbG90dGUtcG9zdGluc3RhbGwubG9nIDI+JjEKZWNobyAiZHZkLXdsYW4tdGVzdCAoQURSLTAwMDksIE1pbnQtRm9ydHNldHp1bmcpIC0tIHByb3Zpc2lvbmVkIGJ5IHR1eGZsb3R0ZSIgPiAvZXRjL21vdGQK | base64 -d | bash' diff --git a/grub/mint-boot-grub.cfg b/grub/mint-boot-grub.cfg deleted file mode 100644 index d310d75..0000000 --- a/grub/mint-boot-grub.cfg +++ /dev/null @@ -1,44 +0,0 @@ -loadfont unicode - -set color_normal=white/black -set color_highlight=black/light-gray - -set timeout=30 - -menuentry "Start Linux Mint 22.3 Cinnamon 64-bit" --class linuxmint { - set gfxpayload=keep - linux /casper/vmlinuz boot=casper uuid=6e72f523-dc09-4880-8910-93ffa64401c5 username=mint hostname=mint iso-scan/filename=${iso_path} quiet splash -- - initrd /casper/initrd.lz -} -menuentry "Start Linux Mint 22.3 Cinnamon 64-bit (compatibility mode)" { - linux /casper/vmlinuz boot=casper uuid=6e72f523-dc09-4880-8910-93ffa64401c5 username=mint hostname=mint iso-scan/filename=${iso_path} noapic noacpi nosplash irqpoll nomodeset -- - initrd /casper/initrd.lz -} -menuentry "OEM install (for manufacturers)" { - set gfxpayload=keep - linux /casper/vmlinuz oem-config/enable=true only-ubiquity boot=casper uuid=6e72f523-dc09-4880-8910-93ffa64401c5 username=mint hostname=mint iso-scan/filename=${iso_path} quiet splash -- - initrd /casper/initrd.lz -} -menuentry "Tuxflotte Auto-Install (Linux Mint 22.3 Cinnamon)" --class linuxmint { - set gfxpayload=keep - linux /casper/vmlinuz boot=casper uuid=6e72f523-dc09-4880-8910-93ffa64401c5 username=mint hostname=mint iso-scan/filename=${iso_path} file=/cdrom/preseed/tuxflotte.seed automatic-ubiquity noprompt priority=critical debian-installer/language=de keyboard-configuration/layoutcode=de quiet splash -- - initrd /casper/initrd.lz -} -grub_platform -if [ "$grub_platform" = "efi" ]; then -menuentry 'Von lokaler Festplatte booten (Standard)' { - exit 1 -} -set default="Von lokaler Festplatte booten (Standard)" -menuentry 'UEFI Firmware Settings' { - fwsetup -} -menuentry 'Memory test' { - linux /boot/memtest.efi -} -else -menuentry 'Von lokaler Festplatte booten (Standard)' { - exit 1 -} -set default="Von lokaler Festplatte booten (Standard)" -fi diff --git a/grub/mint-isolinux-live.cfg b/grub/mint-isolinux-live.cfg deleted file mode 100644 index ff555de..0000000 --- a/grub/mint-isolinux-live.cfg +++ /dev/null @@ -1,57 +0,0 @@ -timeout 100 - -menu background splash.png -menu title Welcome to Linux Mint 22.3 64-bit - -menu color screen 37;40 #80ffffff #00000000 std -MENU COLOR border 30;44 #40ffffff #a0000000 std -MENU COLOR title 1;36;44 #ffffffff #a0000000 std -MENU COLOR sel 7;37;40 #e0ffffff #20ffffff all -MENU COLOR unsel 37;44 #50ffffff #a0000000 std -MENU COLOR help 37;40 #c0ffffff #a0000000 std -MENU COLOR timeout_msg 37;40 #80ffffff #00000000 std -MENU COLOR timeout 1;37;40 #c0ffffff #00000000 std -MENU COLOR msg07 37;40 #90ffffff #a0000000 std -MENU COLOR tabmsg 31;40 #ffDEDEDE #00000000 std -MENU WIDTH 78 -MENU MARGIN 15 -MENU ROWS 6 -MENU VSHIFT 10 -MENU TABMSGROW 12 -MENU CMDLINEROW 12 -MENU HELPMSGROW 16 -MENU HELPMSGENDROW 29 - -label tuxflotte - menu label Tuxflotte Auto-Install - kernel /casper/vmlinuz - append boot=casper initrd=/casper/initrd.lz uuid=6e72f523-dc09-4880-8910-93ffa64401c5 username=mint hostname=mint file=/cdrom/preseed/tuxflotte.seed automatic-ubiquity noprompt priority=critical debian-installer/language=de keyboard-configuration/layoutcode=de quiet splash -- - -label live - menu label Start Linux Mint - kernel /casper/vmlinuz - append boot=casper initrd=/casper/initrd.lz uuid=6e72f523-dc09-4880-8910-93ffa64401c5 username=mint hostname=mint quiet splash -- - -label compat - menu label Start Linux Mint in compatibility mode - linux /casper/vmlinuz - append boot=casper initrd=/casper/initrd.lz uuid=6e72f523-dc09-4880-8910-93ffa64401c5 username=mint hostname=mint noapic noacpi nosplash irqpoll nomodeset -- - -label oem - menu label OEM install (for manufacturers) - linux /casper/vmlinuz - append oem-config/enable=true only-ubiquity boot=casper initrd=/casper/initrd.lz uuid=6e72f523-dc09-4880-8910-93ffa64401c5 username=mint hostname=mint quiet splash -- - -label hdt - menu label Hardware Detection - kernel hdt.c32 - -label local - menu label Boot from local drive - menu default - COM32 chain.c32 - APPEND hd0 - -label memtest - menu label Memory test - linux /boot/memtest.bin diff --git a/initrd-hooks/casper-bottom/99casperboot b/initrd-hooks/casper-bottom/99casperboot deleted file mode 100755 index 002056c..0000000 --- a/initrd-hooks/casper-bottom/99casperboot +++ /dev/null @@ -1,71 +0,0 @@ -#! /bin/sh - -PREREQ="" - -prereqs() -{ - echo "$PREREQ" -} - -case $1 in -# get pre-requisites -prereqs) - prereqs - exit 0 - ;; -esac - -# Ueberschreibt das originale 99casperboot (macht nur `touch -# /run/.casper-boot`) statt einen zusaetzlichen, neuen Hook-Skriptnamen -# einzufuehren: initramfs-tools generiert beim ISO-Bau eine ORDER-Datei -# (scripts/casper-bottom/ORDER) mit der fest verdrahteten Aufruf-Reihenfolge -# aller casper-bottom-Skripte - real durch Extraktion des echten initrd.lz -# mit unmkinitramfs bestaetigt. Ein per Initrd-Cpio-Layer NEU hinzugefuegtes -# Skript taucht in dieser ORDER-Datei nicht auf und wird nie aufgerufen, -# selbst wenn die Datei im initramfs physisch vorhanden ist (erste Version -# dieses Fixes ist daran gescheitert). Das Ueberschreiben eines bereits in -# ORDER referenzierten Pfads funktioniert dagegen zuverlaessig (spaetere -# cpio-Schichten ueberschreiben Dateiinhalte am selben Pfad, siehe -# scripts/lib/initrd.sh - derselbe Mechanismus, der schon fuer das -# Kexec-Preseed in Phase 1 verifiziert wurde). 99casperboot ist laut ORDER -# das letzte casper-bottom-Skript ueberhaupt - garantiert nach 05mountpoints, -# das /cdrom nach /root/cdrom umhaengt und damit die Voraussetzung fuer den -# folgenden Kopiervorgang schafft. -if [ -d /root/cdrom/updates ]; then - cp -a /root/cdrom/updates/. /root/ -fi - -# Ubiquity stuerzt im automatic-ubiquity-GTK-Modus real reproduzierbar ab -# (TypeError: Argument 1 does not allow None as a value), sobald -# enable_download_updates(False) den Netzwerkstatus als "nicht verbunden" -# meldet: ubi-prepare.py uebergibt das Ergebnis von -# self.controller.get_string('ubiquity/text/label_download_updates_na') -# ungeprueft an GtkLabel.set_label() - fehlt fuer diese Vorlage/Sprache ein -# Uebersetzungsstring, liefert get_string() None statt eines leeren Strings, -# und GTK akzeptiert kein None als Label-Text (real ueber QEMU-Testlauf -# gefunden, siehe ADR-0023-Nachtrag). Gezielter Sed-Patch statt vollstaendigem -# Datei-Ersatz, um nicht die komplette Drittanbieter-Datei mitpflegen zu -# muessen - betrifft nur die eine Zeile, "or ''" faengt jeden None-Rueckgabewert -# ab, unabhaengig von der genauen Ursache der fehlenden Uebersetzung. -ubi_prepare="/root/usr/lib/ubiquity/plugins/ubi-prepare.py" -if [ -f "$ubi_prepare" ]; then - sed -i \ - "s/self\.controller\.get_string(template))/self.controller.get_string(template) or '')/" \ - "$ubi_prepare" -fi - -# AT-SPI-Bruecke fuer den Autoklicker (atspi_click.py) muss VOR dem -# GTK-Start von Ubiquity aktiv sein - siehe live-updates/usr/share/ubiquity/ -# tuxflotte-atspi-env.sh (dorthin per casper-bottom-Kopie oben bereits nach -# /root/usr/share/ubiquity/ ausgeliefert). Einzeilige Einbindung direkt nach -# dem fruehen Existenz-Check von ubiquity-dm - alles Weitere, inkl. -# Paketinstallation, uebernimmt die eingebundene Datei selbst. -start_ubiquity_dm="/root/usr/share/ubiquity/start-ubiquity-dm" -if [ -f "$start_ubiquity_dm" ]; then - sed -i \ - '/^test -x \/usr\/bin\/ubiquity-dm || exit 0$/a\ -. /usr/share/ubiquity/tuxflotte-atspi-env.sh' \ - "$start_ubiquity_dm" -fi - -touch /run/.casper-boot diff --git a/live-updates/etc/sudoers.d/90-tuxflotte b/live-updates/etc/sudoers.d/90-tuxflotte deleted file mode 100644 index 705b1e6..0000000 --- a/live-updates/etc/sudoers.d/90-tuxflotte +++ /dev/null @@ -1 +0,0 @@ -mint ALL=(ALL) NOPASSWD: ALL diff --git a/live-updates/etc/systemd/system/multi-user.target.wants/tuxflotte-autoclicker.service b/live-updates/etc/systemd/system/multi-user.target.wants/tuxflotte-autoclicker.service deleted file mode 120000 index c2bec14..0000000 --- a/live-updates/etc/systemd/system/multi-user.target.wants/tuxflotte-autoclicker.service +++ /dev/null @@ -1 +0,0 @@ -../tuxflotte-autoclicker.service \ No newline at end of file diff --git a/live-updates/etc/systemd/system/tuxflotte-autoclicker.service b/live-updates/etc/systemd/system/tuxflotte-autoclicker.service deleted file mode 100644 index 92647ac..0000000 --- a/live-updates/etc/systemd/system/tuxflotte-autoclicker.service +++ /dev/null @@ -1,17 +0,0 @@ -[Unit] -Description=Tuxflotte Autoklicker fuer Ubiquitys GTK-Installationsassistenten -# Nur bei automatisierter Installation relevant (siehe autoclicker.sh - -# prueft selbst auf das Boot-Keyword "tuxflotte-autoclick" und beendet sich -# sofort, wenn es fehlt). Bewusst kein "After=graphical.target" o.ae., da -# ubiquity-dm keine normale Display-Manager-Sitzung startet, deren -# Bereitschaft systemd auf ueblichem Weg erkennen wuerde - das Skript selbst -# wartet auf den X-Socket. -After=multi-user.target - -[Service] -Type=simple -ExecStart=/opt/tuxflotte/scripts/autoclicker.sh -Restart=no - -[Install] -WantedBy=multi-user.target diff --git a/live-updates/etc/xdg/autostart/sealertauto.desktop b/live-updates/etc/xdg/autostart/sealertauto.desktop deleted file mode 100644 index 49de53b..0000000 --- a/live-updates/etc/xdg/autostart/sealertauto.desktop +++ /dev/null @@ -1,4 +0,0 @@ -[Desktop Entry] -Type=Application -Name=SELinux Troubleshooter Notifier -Hidden=true diff --git a/live-updates/etc/xdg/autostart/tuxflotte-installer.desktop b/live-updates/etc/xdg/autostart/tuxflotte-installer.desktop deleted file mode 100644 index db9b4bd..0000000 --- a/live-updates/etc/xdg/autostart/tuxflotte-installer.desktop +++ /dev/null @@ -1,6 +0,0 @@ -[Desktop Entry] -Type=Application -Name=Tuxflotte Provisioning -Exec=/opt/tuxflotte/kiosk/start-kiosk.sh -X-GNOME-Autostart-enabled=true -NoDisplay=true diff --git a/live-updates/opt/tuxflotte/kiosk/index.html b/live-updates/opt/tuxflotte/kiosk/index.html deleted file mode 100644 index b49a59b..0000000 --- a/live-updates/opt/tuxflotte/kiosk/index.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - -Tuxflotte Provisioning - - - - Tuxflotte -

Kiosk-Oberfläche in Entwicklung.

- - diff --git a/live-updates/opt/tuxflotte/kiosk/logo.svg b/live-updates/opt/tuxflotte/kiosk/logo.svg deleted file mode 100644 index 35d5e2a..0000000 --- a/live-updates/opt/tuxflotte/kiosk/logo.svg +++ /dev/null @@ -1,179 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/live-updates/opt/tuxflotte/kiosk/start-kiosk.sh b/live-updates/opt/tuxflotte/kiosk/start-kiosk.sh deleted file mode 100755 index 3994783..0000000 --- a/live-updates/opt/tuxflotte/kiosk/start-kiosk.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# German keyboard layout for the graphical session (vconsole.keymap=de on the -# kernel cmdline only covers the text console, not X11/Wayland input). Cinnamon -# ships its own parallel org.cinnamon.desktop.input-sources schema, separate -# from GNOME's org.gnome.desktop.input-sources — writing org.gnome alone had -# no effect (confirmed on real hardware), so both are set here. -dconf write /org/cinnamon/desktop/input-sources/sources "[('xkb', 'de')]" -dconf write /org/gnome/desktop/input-sources/sources "[('xkb', 'de')]" - -# Suppresses Epiphany's "set as default browser?" first-run prompt (schema -# default is true, see /usr/share/glib-2.0/schemas/org.gnome.epiphany.gschema.xml). -dconf write /org/gnome/epiphany/ask-for-default false - -# Kiosk cleanup: no desktop icons (Nemo). The panel itself is kept (removing -# the last panel via panels-enabled triggers Cinnamon's own "you don't have -# any panels, open panel settings?" confirmation dialog — hardcoded in -# js/ui/panel.js, no way to suppress it, so panels-enabled is deliberately -# left untouched). Instead, only the two useful applets are kept: a window -# list (to restore Epiphany if a user minimizes it) and power (shutdown/ -# reboot) — everything else (menu, systray, clock, workspace switcher etc.) -# is removed. Deliberately the classic window-list@cinnamon.org, not -# grouped-window-list@cinnamon.org: the grouped variant ships default -# "pinned apps" launchers (firefox.desktop, org.gnome.Terminal.desktop, -# nemo.desktop — confirmed via its settings-schema.json) that showed up in -# the panel even with unrelated applets removed. Plain window-list has no -# pinned-apps concept at all, only ever shows actually open windows. -dconf write /org/nemo/desktop/show-desktop-icons false -dconf write /org/cinnamon/enabled-applets "['panel1:left:0:window-list@cinnamon.org:1', 'panel1:right:0:power@cinnamon.org:2']" - -mkdir -p "${HOME}/.local/share/tuxflotte-kiosk" - -# Auto-Modus (personalisierte Kunden-ISO, siehe scripts/build_customer_iso.sh) -# startet den Installer sofort unbeaufsichtigt statt der Kiosk-Startseite - -# config/installer.conf wird nur bei personalisierten Abbildern mitgeliefert, -# das Standard-/Testabbild bleibt unverändert interaktiv. -if grep -qE '^\s*(export\s+)?TUXFLOTTE_AUTO_MODE=true\s*$' /opt/tuxflotte/config/installer.conf 2>/dev/null; then - exec sudo /opt/tuxflotte/scripts/installer.sh -fi - -exec epiphany --profile="${HOME}/.local/share/tuxflotte-kiosk" file:///opt/tuxflotte/kiosk/index.html diff --git a/live-updates/opt/tuxflotte/scripts/atspi_click.py b/live-updates/opt/tuxflotte/scripts/atspi_click.py deleted file mode 100755 index a0488a7..0000000 --- a/live-updates/opt/tuxflotte/scripts/atspi_click.py +++ /dev/null @@ -1,308 +0,0 @@ -#!/usr/bin/env python3 -"""Klickt den primaeren "Weiter"-Button der aktuell sichtbaren Ubiquity-Seite -per AT-SPI (Linux-Barrierefreiheits-API) - wird von autoclicker.sh wiederholt -aufgerufen (ein Prozessstart pro Klickversuch, absichtlich einfach statt -dauerhaft im Hintergrund am Accessibility-Bus zu lauschen). - -Warum AT-SPI statt Bildschirmkoordinaten: der urspruengliche xdotool-Ansatz -scheiterte daran, dass Metacity mehrere ueberlappende X11-Fenster aehnlicher -Groesse erzeugt (WM-Dekorationsrahmen, Hilfsfenster) - eine "groesstes -sichtbares Fenster"-Heuristik traf wiederholt das falsche Fenster (siehe -ADR-0023-Nachtrag). AT-SPI identifiziert den Button stattdessen ueber seine -Rolle (PUSH_BUTTON) und seinen Namen im Accessibility-Baum der Anwendung -selbst - unabhaengig von Fenstergeometrie/-dekoration. - -WICHTIG (real beim Testen entdeckt, 29.08.2026): trotz fest gesetztem -"debian-installer/language=de" sind NICHT alle Assistentenseiten auf -Deutsch beschriftet - die Mint-eigene "Multimedia-Codecs"-Seite zeigt reale -englische Buttons ("Quit"/"Back"/"Continue"), vermutlich dieselbe Ursache -wie der bereits gepatchte ubi-prepare.py-None-Bug (fehlender/unvollstaendiger -.mo-Uebersetzungskatalog fuer dieses Plugin auf dem Live-Medium). Eine reine -Werteliste bekannter deutscher Beschriftungen (fruehere Version dieses -Skripts) haette hier fuer immer haengen bleiben. Die Logik wurde deshalb auf -eine sprachunabhaengige Ausschluss-Strategie umgestellt: bekannte -rueckwaerts-/abbrechende Beschriftungen (zweisprachig) werden aus der -Kandidatenliste entfernt, der bzw. die verbleibenden Kandidaten werden -geklickt - siehe select_target() fuer die genaue Regel samt -Sicherheitsverhalten bei Mehrdeutigkeit. - -Sprache ist durch "debian-installer/language=de" im Kexec-Append-Preseed -grundsaetzlich auf de_DE gesetzt (siehe backend.sh), s.o. aber nicht -verlaesslich fuer jede einzelne Seite. - -NACHTRAG (real beim Testen entdeckt, 29.08.2026): auf der manuellen -Partitionierungsseite ("Etwas Anderes") lief der Klick auf "Jetzt -installieren" nachweislich zuverlaessig (AT-SPI meldete jedes Mal Erfolg), -aber die Seite kam nie voran - stattdessen loeste jeder Klick erneut die -Debconf-Frage "ubiquity/partman-rebuild-cache" aus -(/lib/partman/update.d/99signal_ubiquity), was ubi-partman.py zurueck auf -dieselbe Seite wirft (siehe ADR-0023-Nachtrag). Ein gezielter Fix am -Partitionsrezept (kein zusaetzliches $bootable{ } auf der Root-Partition -unter UEFI) aenderte NICHTS - das deutet auf einen zeitlichen statt -strukturellen Fehler hin: die Seite zeigt waehrend dieser Phase ein -Status-Panel "Konfiguration der Installation wird ueberprueft ..." - klickt -der Autoklicker WAEHREND dieser Hintergrundpruefung noch laeuft, koennte -er sie unterbrechen/neu anstossen, statt ihr Zeit zum Abschliessen zu -geben. Dieses Skript wartet deshalb jetzt aktiv, solange dieser Text -sichtbar ist (siehe VALIDATION_TEXT_MARKERS/find_showing_text()), und -klickt erst, wenn er verschwunden ist. - -Exit-Codes: 0 = ein Button wurde gefunden und geklickt, -1 = kein eindeutiger Button gefunden (z.B. Seite im Ladezustand, oder echte -Mehrdeutigkeit - dann bewusst NICHT geklickt, siehe select_target()), -2 = pyatspi/AT-SPI-Bus nicht erreichbar (Bruecke evtl. nicht aktiv), -3 = Ubiquitys eigene Hintergrundpruefung laeuft noch sichtbar - bewusst -nicht geklickt, siehe Nachtrag oben. -""" -import sys - -try: - import pyatspi -except ImportError: - print("pyatspi nicht verfuegbar", file=sys.stderr) - sys.exit(2) - -# Zweisprachig, da nicht jede Seite verlaesslich deutsch beschriftet ist -# (siehe Modul-Docstring). Diese Namen werden aus der Kandidatenliste -# AUSGESCHLOSSEN, nie geklickt - unabhaengig davon, ob sie der einzige -# sichtbare Button waeren. -EXCLUDE_LABELS = { - "zurück", - "zurueck", - "back", - "abbrechen", - "abbruch", - "cancel", - "beenden", - "quit", - "exit", - "verwerfen", -} - -# Bevorzugt geklickt, falls mehrere Kandidaten nach dem Ausschluss uebrig -# bleiben (siehe select_target()). Kein Ausschlusskriterium fuer -# Kandidaten, die HIER nicht drin stehen - die duerfen trotzdem als -# alleiniger Kandidat geklickt werden (Sole-Survivor-Regel), damit auch -# unbekannte/nicht uebersetzte Beschriftungen wie das reale "Continue" -# oben nicht zum Stillstand fuehren. -PREFER_LABELS = { - "weiter", - "continue", - "next", - "jetzt installieren", - "install now", - "fortfahren", - "proceed", - "installieren", - "install", - "neu starten", - "restart now", - "schließen", - "schliessen", - "close", - "finish", - "fertigstellen", - "done", -} - -MAX_DEPTH = 40 - -# Zweisprachig vorsichtshalber (siehe Multimedia-Codecs-Erfahrung oben), -# auch wenn dieser konkrete Text bisher immer deutsch beobachtet wurde. -VALIDATION_TEXT_MARKERS = ( - "wird überprüft", - "wird ueberprueft", - "being checked", - "checking the install", -) - - -def _node_text(node): - """Sammelt allen aus einem Accessible auslesbaren Text: .name, - .description UND (falls unterstuetzt) das separate Text-Interface. - WICHTIG (real beim Testen entdeckt, 29.08.2026): ein einfaches GtkLabel - exponiert seinen sichtbaren Text ueblicherweise NICHT ueber .name/ - .description (die bleiben dort oft leer) sondern ausschliesslich ueber - das AT-SPI-Text-Interface (queryText().getText(0, -1)) - ohne diesen - dritten Zugriffsweg fand find_showing_text() den sichtbar angezeigten - Status-Text nie, obwohl er laut Screenshot die ganze Zeit auf dem Schirm - stand.""" - parts = [] - try: - if node.name: - parts.append(node.name) - except Exception: - pass - try: - if node.description: - parts.append(node.description) - except Exception: - pass - try: - text_iface = node.queryText() - content = text_iface.getText(0, -1) - if content: - parts.append(content) - except NotImplementedError: - pass - except Exception: - pass - return " ".join(parts).strip().lower() - - -def find_showing_text(node, needle, depth=0): - """Sucht ein sichtbares Accessible, dessen Text (siehe _node_text()) den - Suchtext enthaelt - unabhaengig von seiner Rolle (Label/Expander/...), - da Ubiquitys Status-Panel-Text nicht zuverlaessig unter derselben Rolle - exponiert sein muss. Bei Unsicherheit ueber den Sichtbarkeitsstatus - bewusst konservativ (lieber einen Zyklus zu viel warten als einen - Klick mitten in die Pruefung setzen).""" - if node is None or depth > MAX_DEPTH: - return False - if needle in _node_text(node): - try: - state = node.getState() - return state.contains(pyatspi.STATE_SHOWING) - except Exception: - return True - try: - count = node.childCount - except Exception: - return False - for i in range(count): - try: - child = node.getChildAtIndex(i) - except Exception: - continue - if find_showing_text(child, needle, depth + 1): - return True - return False - - -def collect_buttons(node, depth=0, acc=None): - """Alle sichtbaren+aktivierten Push-Buttons im Baum einsammeln (Rolle, - Zustand). Absichtlich ALLE Kandidaten sammeln statt beim ersten Treffer - abzubrechen - select_target() braucht die vollstaendige Liste, um - Mehrdeutigkeit erkennen zu koennen.""" - if acc is None: - acc = [] - if node is None or depth > MAX_DEPTH: - return acc - try: - role = node.getRole() - except Exception: - return acc - - if role == pyatspi.ROLE_PUSH_BUTTON: - try: - state = node.getState() - if state.contains(pyatspi.STATE_SENSITIVE) and state.contains( - pyatspi.STATE_SHOWING - ): - acc.append(node) - except Exception: - pass - return acc - - try: - count = node.childCount - except Exception: - return acc - for i in range(count): - try: - child = node.getChildAtIndex(i) - except Exception: - continue - collect_buttons(child, depth + 1, acc) - return acc - - -def select_target(buttons): - """Waehlt aus allen sichtbaren+aktivierten Buttons genau einen aus, der - geklickt werden darf - oder None, wenn das nicht sicher moeglich ist. - - Regel (bewusst sicherheitsorientiert, siehe Modul-Docstring): - 1. Bekannte rueckwaerts-/abbrechende Beschriftungen (EXCLUDE_LABELS) - werden nie geklickt, unabhaengig vom Rest. - 2. Von den verbleibenden Kandidaten wird bevorzugt, wer eine bekannte - vorwaerts-/abschliessende Beschriftung traegt (PREFER_LABELS). - 3. Bleibt nach 1./2. KEIN bekannter Treffer, aber genau EIN Kandidat - uebrig, wird dieser geklickt (Sole-Survivor-Regel - deckt unbekannte/ - nicht uebersetzte Beschriftungen wie das real beobachtete "Continue" - ab, siehe Modul-Docstring). - 4. Bleiben mehrere unbekannte Kandidaten gleichzeitig uebrig, wird NICHT - geklickt (echte Mehrdeutigkeit - ein Fehlklick waere hier riskanter - als ein uebersprungener Zyklus, die Schleife in autoclicker.sh - versucht es 2 Sekunden spaeter erneut).""" - candidates = [] - for btn in buttons: - name = (btn.name or "").strip().lower() - if name in EXCLUDE_LABELS: - continue - candidates.append(btn) - - if not candidates: - return None - - preferred = [b for b in candidates if (b.name or "").strip().lower() in PREFER_LABELS] - if preferred: - return preferred[0] - - if len(candidates) == 1: - return candidates[0] - - return None - - -def main(): - try: - desktop = pyatspi.Registry.getDesktop(0) - except Exception as exc: - print(f"AT-SPI-Desktop nicht erreichbar: {exc}", file=sys.stderr) - return 2 - - apps = [] - for i in range(desktop.childCount): - try: - app = desktop.getChildAtIndex(i) - except Exception: - continue - if app is not None: - apps.append(app) - - for marker in VALIDATION_TEXT_MARKERS: - for app in apps: - if find_showing_text(app, marker): - print( - f"Hintergrundpruefung noch sichtbar ('{marker}'), warte statt zu klicken.", - file=sys.stderr, - ) - return 3 - - all_buttons = [] - for app in apps: - collect_buttons(app, 0, all_buttons) - - target = select_target(all_buttons) - if target is None: - names = [repr((b.name or "").strip()) for b in all_buttons] - print( - "kein eindeutiger Button gefunden, sichtbare Buttons: " - + (", ".join(names) if names else "(keine)"), - file=sys.stderr, - ) - return 1 - - try: - action = target.queryAction() - action.doAction(0) - except Exception as exc: - print(f"Klick auf '{target.name}' fehlgeschlagen: {exc}", file=sys.stderr) - return 1 - - print(f"geklickt: {target.name}") - return 0 - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/live-updates/opt/tuxflotte/scripts/autoclicker.sh b/live-updates/opt/tuxflotte/scripts/autoclicker.sh deleted file mode 100755 index 857e5e2..0000000 --- a/live-updates/opt/tuxflotte/scripts/autoclicker.sh +++ /dev/null @@ -1,113 +0,0 @@ -#!/bin/bash -### Klickt automatisiert durch Ubiquitys GTK-Installationsassistenten -### (automatic-ubiquity) - noetig, weil Ubiquitys eigenes "noninteractive"- -### Frontend die gefuehrte Partitionierung nicht zuverlaessig automatisieren -### kann (endlose choose_partition-Schleife in ubi-partman.py, real -### bestaetigt, siehe ADR-0023-Nachtrag). Der GTK-Assistent fuellt jede Seite -### bereits vollstaendig aus dem Preseed vor (siehe preseed.tpl) - es fehlt -### nur der "Weiter"/"Installieren"-Klick pro Seite. -### -### Klickt ueber AT-SPI (Barrierefreiheits-API), nicht mehr ueber -### Bildschirmkoordinaten/Enter-Taste (siehe atspi_click.py fuer die -### eigentliche Klicklogik). Der fruehere xdotool-Ansatz scheiterte real -### daran, dass Metacity mehrere ueberlappende X11-Fenster aehnlicher -### Groesse erzeugt (WM-Dekorationsrahmen, Hilfsfenster) - weder eine -### "groesstes sichtbares Fenster"-Heuristik noch die Enter-Taste (aktiviert -### auf der Partitionierungs-Uebersichtsseite einen Ausklapp-Pfeil statt des -### "Jetzt installieren"-Buttons) waren zuverlaessig genug (siehe -### ADR-0023-Nachtrag). AT-SPI identifiziert den Button stattdessen ueber -### seine Rolle+seinen Namen im Accessibility-Baum der Anwendung selbst - -### unabhaengig von Fenstergeometrie/-dekoration. -### -### Die AT-SPI-Bruecke selbst (GTK_MODULES=gail:atk-bridge, Session-/A11y- -### Bus) wird NICHT hier, sondern bereits VOR dem GTK-Start von Ubiquity in -### tuxflotte-atspi-env.sh aktiviert (eingebunden von start-ubiquity-dm, -### siehe Sed-Patch in initrd-hooks/casper-bottom/99casperboot) - eine erst -### nachtraeglich aktivierte Bruecke wird von einer bereits laufenden -### GTK-Anwendung nicht mehr nachgeladen. -### -### Wird per systemd-Service (siehe ...service im selben Ausliefer-Layer) bei -### JEDEM Boot gestartet, bricht aber sofort ab, wenn das eigene Boot-Keyword -### "tuxflotte-autoclick" nicht in /proc/cmdline steht - siehe backend_launch() -### in backends/mint/backend.sh, wo dieses Keyword gesetzt wird. Auf einem -### normalen (nicht automatisierten) Boot also wirkungslos. -set -u - -LOG=/var/log/tuxflotte-autoclicker.log -log() { - echo "$(date '+%Y-%m-%d %H:%M:%S') $*" >>"${LOG}" -} - -grep -qw tuxflotte-autoclick /proc/cmdline || exit 0 - -log "tuxflotte-autoclick erkannt, starte Autoklicker." -export DISPLAY=:0 - -is_ubiquity_running() { - pgrep -f '/usr/bin/ubiquity' >/dev/null 2>&1 -} - -# ubiquity-dm startet Ubiquity frueh im Boot zu einem nicht exakt -# vorhersagbaren Zeitpunkt - auf den Prozess warten statt auf eine feste -# Wartezeit zu vertrauen. AT-SPI braucht anders als der fruehere -# xdotool-Ansatz keinen eigenen X-Socket-Check - der Zugriff laeuft ueber -# den Accessibility-Bus, nicht direkt ueber X11. -ubiquity_ready=0 -for _ in $(seq 1 120); do - if is_ubiquity_running; then - ubiquity_ready=1 - break - fi - sleep 1 -done -if [ "${ubiquity_ready}" -ne 1 ]; then - log "ubiquity-Prozess nach 120s nicht erschienen, breche ab." - exit 1 -fi -log "ubiquity-Prozess erkannt." - -if ! python3 -c 'import pyatspi' >/dev/null 2>&1; then - log "pyatspi fehlt auf dem Live-Medium, installiere nach." - if ! apt-get install -y python3-pyatspi >>"${LOG}" 2>&1; then - log "pyatspi-Installation fehlgeschlagen, breche ab." - exit 1 - fi -fi - -ATSPI_CLICK=/opt/tuxflotte/scripts/atspi_click.py - -log "Starte Klick-Schleife." -# Harte Obergrenze als Sicherheitsnetz (60 Minuten) - falls die Installation -# haengen bleibt, soll dieser Dienst nicht unbegrenzt weiterlaufen. -end=$((SECONDS + 3600)) -clicks=0 -misses=0 -while [ "${SECONDS}" -lt "${end}" ]; do - if ! is_ubiquity_running; then - log "ubiquity-Prozess nicht mehr aktiv (vermutlich fertig oder abgestuerzt), beende Schleife nach ${clicks} Klick(s)." - break - fi - - out="$(python3 "${ATSPI_CLICK}" 2>&1)" - rc=$? - if [ "${rc}" -eq 0 ]; then - clicks=$((clicks + 1)) - misses=0 - log "Klick ${clicks}: ${out}" - elif [ "${rc}" -eq 2 ]; then - log "AT-SPI-Bus nicht erreichbar, breche ab: ${out}" - break - elif [ "${rc}" -eq 3 ]; then - # Ubiquitys eigene Hintergrundpruefung laeuft noch sichtbar (siehe - # atspi_click.py-Nachtrag) - bewusst NICHT als Fehlversuch zaehlen, - # nur abwarten. Real beim Testen entdeckt: ein Klick auf "Jetzt - # installieren" WAEHREND dieser Pruefung fuehrte wiederholt in die - # partman-rebuild-cache-Schleife statt zum eigentlichen Commit. - log "wartet auf Hintergrundpruefung: ${out}" - else - misses=$((misses + 1)) - log "kein Treffer (${misses}): ${out}" - fi - sleep 2 -done -log "Autoklicker beendet (${clicks} Klick(s) insgesamt)." diff --git a/live-updates/usr/share/ubiquity/tuxflotte-atspi-env.sh b/live-updates/usr/share/ubiquity/tuxflotte-atspi-env.sh deleted file mode 100755 index 4677341..0000000 --- a/live-updates/usr/share/ubiquity/tuxflotte-atspi-env.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/sh -### Wird per Ein-Zeilen-Sed-Patch (siehe initrd-hooks/casper-bottom/99casperboot) -### GANZ AM ANFANG von start-ubiquity-dm eingebunden ("."), also BEVOR -### ubiquity-dm den X-Server startet und Ubiquity selbst exec't. -### -### Zweck: die AT-SPI-Barrierefreiheits-Bruecke (atk-bridge) fuer Ubiquitys -### GTK-Prozess aktivieren, damit atspi_click.py (siehe -### /opt/tuxflotte/scripts/) Buttons ueber ihre Rolle/ihren Namen im -### Accessibility-Baum anklicken kann statt ueber Bildschirmkoordinaten. -### Der xdotool-Koordinaten-Ansatz ist an ueberlappenden X11-Fenstern durch -### die Metacity-Fensterdekoration gescheitert (mehrere Fenster aehnlicher -### Groesse, "groesstes Fenster"-Heuristik traf wiederholt das falsche - -### siehe ADR-0023-Nachtrag). -### -### WICHTIG: das muss VOR dem GTK-Init von Ubiquity passieren - eine erst -### nachtraeglich verfuegbare Bruecke wird von einer bereits laufenden -### GTK-Anwendung nicht mehr nachgeladen (GTK_MODULES wird nur beim Start -### ausgewertet). Deshalb blockierend (kein Hintergrund-"&" fuer die -### Paketinstallation) und deshalb im Skript, das ubiquity-dm selbst -### aufruft, statt im spaeter laufenden Autoklicker-Service. -### -### Absichtlich EIN gemeinsamer apt-get-Aufruf fuer alle drei Pakete (statt -### getrennter Aufrufe je Skript) - der Autoklicker installiert xdotool -### zeitlich nah, ein zweiter paralleler apt-get/dpkg-Aufruf haette real -### beobachtete Lock-Konflikte riskiert (debconf: "config.dat is locked by -### another process"). - -for pkg in at-spi2-core dbus-x11 python3-pyatspi; do - dpkg -s "$pkg" >/dev/null 2>&1 && continue - if [ "${_tuxflotte_atspi_apt_updated:-}" != "1" ]; then - apt-get update -qq - _tuxflotte_atspi_apt_updated=1 - fi - DEBIAN_FRONTEND=noninteractive apt-get install -y "$pkg" -done - -export GTK_MODULES="gail:atk-bridge" -export NO_AT_BRIDGE=0 - -# Eigene Session-Bus-Instanz, falls keine geerbt wurde - die minimale -# ubiquity-dm-X-Sitzung startet anders als eine normale Desktop-Sitzung -# vermutlich keinen eigenen Session-Bus. -if [ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ] && command -v dbus-launch >/dev/null 2>&1; then - eval "$(dbus-launch --sh-syntax)" - export DBUS_SESSION_BUS_ADDRESS DBUS_SESSION_BUS_PID -fi - -if command -v at-spi-bus-launcher >/dev/null 2>&1; then - at-spi-bus-launcher --launch-immediately >/var/log/tuxflotte-atspi-bus.log 2>&1 & - # Kurz abwarten, bis der a11y-Bus unter org.a11y.Bus registriert ist, - # bevor ubiquity-dm/Ubiquity (naechste Zeile in start-ubiquity-dm) - # GTK initialisiert. - sleep 1 -fi diff --git a/scripts/build.sh b/scripts/build.sh index e9cd683..c001001 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,6 +1,12 @@ #!/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:-}" @@ -10,18 +16,8 @@ BUILD_DIR="$BASE_DIR/build" WORK_DIR="$BUILD_DIR/work" OUTPUT_DIR="$BUILD_DIR/output" -# shellcheck source=lib/initrd.sh -source "$REPO_DIR/scripts/lib/initrd.sh" - -# Test-Device fuer den in bake_test_preseed() eingebrannten, nicht -# personalisierten Test-Preseed (Mint) - dasselbe "Default Lab"-Testgeraet, -# das schon fuer die Fedora-Verifikation genutzt wurde. Echte Personalisierung -# pro Kunde ist nicht Teil dieses Build-Skripts (siehe ADR-0011-Kontext). -TEST_DEVICE_ID="a0238a0b-d2b5-4516-a6ce-da7170041d11" -TEST_HOSTNAME="tuxflotte-mint-test" - usage() { - echo "Usage: $0 /path/to/source.iso " + echo "Usage: $0 /path/to/source.iso fedora" } check_input() { @@ -35,13 +31,10 @@ check_input() { exit 1 fi - case "$BACKEND" in - fedora|mint) ;; - *) - echo "Error: unbekanntes Backend '$BACKEND' (erwartet: fedora oder mint)" - exit 1 - ;; - esac + if [[ "$BACKEND" != "fedora" ]]; then + echo "Error: unbekanntes Backend '$BACKEND' (erwartet: fedora)" + exit 1 + fi } check_dependencies() { @@ -51,15 +44,6 @@ check_dependencies() { exit 1 fi done - - if [[ "$BACKEND" == "mint" ]]; then - for cmd in jq envsubst base64 cpio; do - if ! command -v "$cmd" >/dev/null 2>&1; then - echo "Error: missing dependency: $cmd" - exit 1 - fi - done - fi } prepare_dirs() { @@ -87,135 +71,39 @@ patch_grub() { # -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. - if [[ "$BACKEND" == "fedora" ]]; then - cp -f "$REPO_DIR/grub/EFI-BOOT-grub.cfg" \ - "$WORK_DIR/EFI/BOOT/grub.cfg" + 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" - else - # Mint hat, anders als Fedora, keine zweite ESP/FAT-Kopie des GRUB-Menüs, - # die separat gepatcht werden müsste (real gegen die vorhandene - # tuxflotte-mint-test.iso verifiziert - x86_64-efi/grub.cfg ist nur ein - # Loader-Stub, der per `source /boot/grub/grub.cfg` zurückverweist). - cp -f "$REPO_DIR/grub/mint-boot-grub.cfg" \ - "$WORK_DIR/boot/grub/grub.cfg" - - cp -f "$REPO_DIR/grub/mint-isolinux-live.cfg" \ - "$WORK_DIR/isolinux/live.cfg" - fi + cp -f "$REPO_DIR/grub/boot-grub2-grub.cfg" \ + "$WORK_DIR/boot/grub2/grub.cfg" } verify_workdir() { echo "Verifying workdir..." - if [[ "$BACKEND" == "fedora" ]]; then - grep -q "Tuxflotte" "$WORK_DIR/EFI/BOOT/grub.cfg" - grep -q "Tuxflotte" "$WORK_DIR/boot/grub2/grub.cfg" - else - grep -q "Tuxflotte" "$WORK_DIR/boot/grub/grub.cfg" - grep -q "Tuxflotte" "$WORK_DIR/isolinux/live.cfg" - fi + grep -q "Tuxflotte" "$WORK_DIR/EFI/BOOT/grub.cfg" + grep -q "Tuxflotte" "$WORK_DIR/boot/grub2/grub.cfg" echo "GRUB verification passed." } -bake_test_preseed() { - [[ "$BACKEND" == "mint" ]] || return 0 - - echo "Rendering test preseed (nicht personalisiert, siehe TEST_DEVICE_ID)..." - - local preseed_dir="$WORK_DIR/preseed" - local runtime_blueprint_file="$WORK_DIR/runtime_blueprint.json" - local server_response_file="$WORK_DIR/response.json" - - mkdir -p "$preseed_dir" - - cat > "$runtime_blueprint_file" < "$server_response_file" </dev/null | gzip) \ - >"${cpio_out}" || - { echo "Error: Casper-Bottom-Hook-Schicht konnte nicht gebaut werden." >&2; rm -rf "${layer_dir}"; rm -f "${cpio_out}"; return 1; } - - cat "${src_initrd}" "${cpio_out}" >"${dest_initrd}" || - { echo "Error: Initrd konnte nicht mit Hook-Schicht zusammengesetzt werden." >&2; rm -rf "${layer_dir}"; rm -f "${cpio_out}"; return 1; } - - rm -rf "${layer_dir}" - rm -f "${cpio_out}" -}