diff --git a/Containerfile b/Containerfile index f0fa73a..91a48bf 100644 --- a/Containerfile +++ b/Containerfile @@ -114,6 +114,7 @@ RUN chmod 0644 /etc/containers/policy.json /etc/pki/containers/cosign.pub && \ # 2. Kopiere die Systemd-Overrides als Vendor-Drop-ins (kein /etc/-Override im Image) COPY configs/bootc-timer-override.conf /usr/lib/systemd/system/bootc-fetch-apply-updates.timer.d/override.conf COPY configs/bootc-override.conf /usr/lib/systemd/system/bootc-fetch-apply-updates.service.d/override.conf +COPY configs/remount-fs-ostree-skip.conf /usr/lib/systemd/system/systemd-remount-fs.service.d/skip-on-ostree.conf # 3. Kopiere die Session-Helfer und Desktop-Defaults COPY --chmod=755 scripts/notify-bootc-user.sh /usr/bin/ @@ -140,6 +141,8 @@ COPY configs/tmpfiles/noctalia-greeter-seed.conf /usr/lib/tmpfiles.d/noctalia-gr # Fehlt Wrapper, D-Bus, polkit oder Session -> Build-Abbruch statt # defektem Login-Screen. RUN set -u; \ + id greeter >/dev/null || { echo "FEHLER: Service-User greeter fehlt (21-greetd.sh pruefen)"; exit 1; }; \ + grep -q 'pam_gnome_keyring\.so' /etc/pam.d/greetd || { echo "FEHLER: Keyring-PAM in /etc/pam.d/greetd fehlt"; exit 1; }; \ wrapper="$(command -v noctalia-greeter-session || true)"; \ echo "Gefundener Wrapper: ${wrapper}"; \ test -n "${wrapper}" || { echo "FEHLER: noctalia-greeter-session nicht installiert (Terra-Repo/includepkgs pruefen)"; exit 1; }; \ diff --git a/build/20-desktop-labwc.sh b/build/20-desktop-labwc.sh index 33e3c21..871703e 100755 --- a/build/20-desktop-labwc.sh +++ b/build/20-desktop-labwc.sh @@ -18,25 +18,34 @@ dnf5 install -y \ swaybg \ swayidle \ wlopm \ + xdg-desktop-portal \ xdg-desktop-portal-wlr \ xdg-desktop-portal-gtk \ pipewire \ pipewire-pulseaudio \ wireplumber \ NetworkManager \ - foot \ + alacritty \ wl-clipboard \ xdg-user-dirs \ upower \ power-profiles-daemon \ bolt \ - lxqt-policykit \ + bluez \ + cups \ + ipp-usb \ + system-config-printer \ + avahi \ accountsservice \ google-noto-sans-fonts \ google-noto-sans-mono-fonts \ wdisplays \ brightnessctl \ - swaylock + swaylock \ + thunar \ + thunar-volman \ + tumbler \ + gvfs # Optionale Pakete (duerfen fehlen -> --skip-unavailable, eigener Aufruf, # damit ein fehlendes Optionales den Kern nicht zu Fall bringt) @@ -47,10 +56,20 @@ dnf5 install -y \ fwupd \ cliphist \ wlsunset \ + pipewire-codec-aptx \ || true # User-Services fuer Audio (Presets greifen nicht fuer nachinstallierte # Pakete auf bootc-Basis -> explizit global enablen, Fehler tolerieren) systemctl --global enable pipewire.socket pipewire-pulse.socket wireplumber.service || true +# Bluetooth-Daemon (System-Service, kein --global) +systemctl enable bluetooth.service + +# Drucken per Socket-Activation (Fedora-Standard: cups.socket statt Service) +systemctl enable cups.socket + +# mDNS-Discovery (Netzwerkdrucker finden, .local-Aufloesung) +systemctl enable avahi-daemon.socket + dnf5 clean all diff --git a/build/21-greetd.sh b/build/21-greetd.sh index 17e34cf..dc7ecca 100755 --- a/build/21-greetd.sh +++ b/build/21-greetd.sh @@ -29,6 +29,22 @@ dnf5 clean all # accounts-daemon: liefert User-Avatare auf dem Login-Screen. systemctl enable accounts-daemon.service +# Service-Account fuer die Greeter-Session. Weder greetd- noch Greeter-Paket +# legen ihn verlaesslich an - ohne ihn stirbt greetd ("user not found"). +# WICHTIG (bootc/altfiles): video/render existieren nur in /usr/lib/group +# (read-only Image-Default). useradd -G scheitert daran ("group does not +# exist"), weil es die Mitgliedschaft nicht nach /etc mergen kann. +# systemd-sysusers ist das einzige Werkzeug, das den Split korrekt schreibt. +# Build-Zeit (statt Erst-Boot): Eintrag ab Boot 1 vorhanden, kein Race. +mkdir -p /usr/lib/sysusers.d +cat > /usr/lib/sysusers.d/noctalia-greeter.conf <<'EOF' +u greeter - "Greeter" - /usr/sbin/nologin +m greeter video +m greeter render +EOF +systemd-sysusers /usr/lib/sysusers.d/noctalia-greeter.conf +id greeter + # System-Setup des Greeters: richtet u.a. /etc/pam.d/greetd ein. # Pfad laut PACKAGING.md: share/noctalia-greeter/setup_greeter_system.sh if [[ -x /usr/share/noctalia-greeter/setup_greeter_system.sh ]]; then @@ -37,6 +53,18 @@ else echo "WARN: setup_greeter_system.sh nicht gefunden - Greeter-State wird erst beim Boot angelegt" fi +# GNOME-Keyring beim Login still mit entsperren (wie GDM/SDDM). greetd +# authentifiziert via PAM, daher kann pam_gnome_keyring das Login-Passwort +# abgreifen und den "login"-Keyring oeffnen - ohne den Dialog +# "Choose password for new keyring" bei der ersten Secrets-Anfrage. +# Nach dem Greeter-Setup anhaengen (dessen PAM-Anpassungen bleiben vorn). +if ! grep -q 'pam_gnome_keyring\.so' /etc/pam.d/greetd 2>/dev/null; then + cat >> /etc/pam.d/greetd <<'EOF' +auth optional pam_gnome_keyring.so +session optional pam_gnome_keyring.so auto_start +EOF +fi + # bootc-Hygiene: /var-Inhalte aus dem Build werden beim Deployment verworfen # und wuerden nur den var-tmpfiles-Lint triggern. Die /etc-Anteile des Setups # (PAM) bleiben erhalten; /var/lib/noctalia-greeter wird zur Laufzeit via diff --git a/build/22-noctalia.sh b/build/22-noctalia.sh index e5e8f65..6eabd40 100755 --- a/build/22-noctalia.sh +++ b/build/22-noctalia.sh @@ -10,12 +10,54 @@ set -eoux pipefail ############################################################################### echo "Installing Noctalia Shell v5..." +# Versionsdynamik: Wallpaper-Pakete heissen f-backgrounds*. +# Bei Basis-Wechsel (z.B. F44 -> F45 im Containerfile) kommen automatisch +# die neuen Motive mit. Bricht das Schema je, knallt der Build laut +# (kein stiller leerer Picker). +FEDORA_VERSION="$(rpm -E %fedora)" + # Nur das Paket selbst: v5 ist nativ (C++/OpenGL ES), Bildformate und # Theming sind einkompiliert bzw. kommen als RPM-Abhaengigkeiten mit. # ImageMagick/Python/git waren v4-Bedarf und entfallen. +# +# Theming-Unterbau fuer die aktivierten Templates (siehe +# configs/skel/.config/noctalia/templates.toml): +# - flatpak: fehlt in der fedora-bootc-Basis, wird aber vom +# Flatpak-Preinstall-Layer/Service (50-xxx, Bazaar/Brave) benoetigt +# - adw-gtk3-theme: GTK-Theme, das Noctalias gtk-Hook umfaerbt (inkl. -dark). +# HINWEIS: Paket heisst -theme, nicht -gtk3! +# - dconf + Schemas: damit der Hook gtk-theme/color-scheme setzen kann. +# (nwg-look gibt es nicht in Fedora (nur COPR) und wird nicht gebraucht - +# der Hook setzt das Theme selbst.) dnf5 install -y \ --allowerasing \ noctalia \ - flatpak + flatpak \ + adw-gtk3-theme \ + dconf \ + gsettings-desktop-schemas \ + f${FEDORA_VERSION}-backgrounds \ + f${FEDORA_VERSION}-backgrounds-extras-gnome + +# Standard-Wallpaper fuer ~/Pictures neuer Benutzer (Noctalias Picker zeigt +# das XDG-Bilderverzeichnis; ohne Inhalt bleibt er leer). Fedora-eigene +# Motive (Defaults aller Desktops + Supplemental-Pool, offen lizenziert), +# deterministisch umbenannt. Vollauswahl bleibt zusaetzlich unter +# /usr/share/backgrounds (Picker-Verzeichnis dorthin umstellbar). +mkdir -p /etc/skel/Pictures +i=0 +while IFS= read -r img; do + i=$((i + 1)) + if [ "$i" -gt 12 ]; then + break + fi + ext="${img##*.}" + cp "$img" "/etc/skel/Pictures/fluffy-wallpaper-${i}.${ext}" +done < <(find /usr/share/backgrounds -type f \( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' \) | sort) +if [ "$i" -lt 1 ]; then + echo "FEHLER: keine Wallpaper unter /usr/share/backgrounds gefunden" + exit 1 +fi +ls -l /etc/skel/Pictures dnf5 clean all diff --git a/configs/flatpak-preinstall.service b/configs/flatpak-preinstall.service index 0166cca..e6aa4fb 100644 --- a/configs/flatpak-preinstall.service +++ b/configs/flatpak-preinstall.service @@ -7,7 +7,9 @@ ConditionPathExists=!/var/lib/flatpak/.preinstall-done [Service] Type=oneshot ExecStartPre=/usr/bin/flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo -ExecStart=/usr/bin/flatpak install -y flathub io.github.kolunmi.Bazaar com.brave.Browser +# Bazaar + Brave + GTK-Theme-Runtimes, damit Flatpak-GTK3-Apps dem +# Noctalia-Theme (adw-gtk3/-dark) folgen koennen. Laeuft einmalig. +ExecStart=/usr/bin/flatpak install -y flathub io.github.kolunmi.Bazaar com.brave.Browser org.gtk.Gtk3theme.adw-gtk3 org.gtk.Gtk3theme.adw-gtk3-dark ExecStartPost=/usr/bin/touch /var/lib/flatpak/.preinstall-done ExecStartPost=/usr/bin/systemctl disable flatpak-preinstall.service RemainAfterExit=yes diff --git a/configs/remount-fs-ostree-skip.conf b/configs/remount-fs-ostree-skip.conf new file mode 100644 index 0000000..5befc8f --- /dev/null +++ b/configs/remount-fs-ostree-skip.conf @@ -0,0 +1,7 @@ +# systemd-remount-fs scheitert auf bootc/composefs deterministisch +# (Overlay-Root laesst sich nicht remounten: "No changes allowed"). +# Die Mounts kommen bereits mit fstab-Optionen hoch - der Remount ist +# hier redundant. Auf klassischen Systemen (ohne ostree) laeuft der +# Service durch diese Bedingung unveraendert weiter. +[Unit] +ConditionPathExists=!/run/ostree-booted diff --git a/configs/skel/.config/alacritty/alacritty.toml b/configs/skel/.config/alacritty/alacritty.toml new file mode 100644 index 0000000..b1e8648 --- /dev/null +++ b/configs/skel/.config/alacritty/alacritty.toml @@ -0,0 +1,11 @@ +# Alacritty – fluffy-pancake (Noctalia-Zweig) +# Das Noctalia-Template "alacritty" schreibt themes/noctalia.toml +# (Platzhalter liegt bei, Import zeigt fest darauf). +[general] +import = [ + "~/.config/alacritty/themes/noctalia.toml", +] + +[font] +normal = { family = "Noto Sans Mono", style = "Regular" } +size = 10.0 diff --git a/configs/skel/.config/alacritty/themes/noctalia.toml b/configs/skel/.config/alacritty/themes/noctalia.toml new file mode 100644 index 0000000..e7584a4 --- /dev/null +++ b/configs/skel/.config/alacritty/themes/noctalia.toml @@ -0,0 +1,2 @@ +# Platzhalter, verwaltet vom Noctalia-Template "alacritty". +# Wird beim ersten Theme-Resolve mit der Palette befuellt. diff --git a/configs/skel/.config/labwc/autostart b/configs/skel/.config/labwc/autostart index af9f760..8d15129 100644 --- a/configs/skel/.config/labwc/autostart +++ b/configs/skel/.config/labwc/autostart @@ -10,8 +10,10 @@ kanshi >/dev/null 2>&1 & # 2. Hintergrund-Fallback (Noctalia setzt das Wallpaper selbst) swaybg -c '#1a1b26' >/dev/null 2>&1 & -# 3. PolicyKit-Agent (labwc startet kein XDG-Autostart von selbst) -lxqt-policykit-agent >/dev/null 2>&1 & +# 3. PolicyKit: kein externer Agent noetig - Noctalia bringt einen nativen +# mit (per Default aktiv, siehe ~/.config/noctalia/shell.toml -> +# [shell] polkit_agent). Genau EIN Agent pro Session! +# (Historie: lxqt-policykit-agent unter /usr/libexec/ - ausgebaut.) # 4. Desktop-Shell: Bar, Dock, Launcher, Control-Center, Lock, OSDs noctalia >/dev/null 2>&1 & diff --git a/configs/skel/.config/labwc/environment b/configs/skel/.config/labwc/environment index 1970063..847692c 100644 --- a/configs/skel/.config/labwc/environment +++ b/configs/skel/.config/labwc/environment @@ -7,3 +7,4 @@ GDK_BACKEND=wayland XDG_CURRENT_DESKTOP=labwc XDG_SESSION_TYPE=wayland MOZ_ENABLE_WAYLAND=1 +TERMINAL=alacritty diff --git a/configs/skel/.config/labwc/menu.xml b/configs/skel/.config/labwc/menu.xml index 635a9c0..bd0ace3 100644 --- a/configs/skel/.config/labwc/menu.xml +++ b/configs/skel/.config/labwc/menu.xml @@ -2,8 +2,11 @@ - - + + + + + diff --git a/configs/skel/.config/labwc/rc.xml b/configs/skel/.config/labwc/rc.xml index 58e2796..1daefca 100644 --- a/configs/skel/.config/labwc/rc.xml +++ b/configs/skel/.config/labwc/rc.xml @@ -16,7 +16,11 @@ - + + + + + diff --git a/configs/skel/.config/mimeapps.list b/configs/skel/.config/mimeapps.list new file mode 100644 index 0000000..57276ea --- /dev/null +++ b/configs/skel/.config/mimeapps.list @@ -0,0 +1,3 @@ +# Standard-Anwendungen – fluffy-pancake (Noctalia-Zweig) +[Default Applications] +inode/directory=thunar.desktop diff --git a/configs/skel/.config/noctalia/shell.toml b/configs/skel/.config/noctalia/shell.toml new file mode 100644 index 0000000..bb7ca33 --- /dev/null +++ b/configs/skel/.config/noctalia/shell.toml @@ -0,0 +1,7 @@ +# Noctalia Shell-Defaults – fluffy-pancake (Noctalia-Zweig) +# Nativer Polkit-Agent der Shell (statt externem lxqt-policykit-agent): +# Auth-Dialoge kommen als Noctalia-UI (floating, zentriert). +# Braucht eine logind-Session (via greetd+PAM gegeben). +# GUI-Aenderung (Settings -> Security) landet in settings.toml und gewinnt. +[shell] +polkit_agent = true diff --git a/configs/skel/.config/noctalia/templates.toml b/configs/skel/.config/noctalia/templates.toml new file mode 100644 index 0000000..4008c19 --- /dev/null +++ b/configs/skel/.config/noctalia/templates.toml @@ -0,0 +1,15 @@ +# Noctalia Template-Defaults – fluffy-pancake (Noctalia-Zweig) +# Schaltet App-Theming an: Terminal, GTK3/4 und labwc-Deko folgen der +# Noctalia-Palette (IDs aus dem Built-in-Katalog: +# `noctalia theme --list-templates`). +# - alacritty: schreibt ~/.config/alacritty/themes/noctalia.toml +# (braucht den import in alacritty.toml + Platzhalter, beides in /etc/skel) +# - gtk3/gtk4: schreibt noctalia.css + haengt den Import in gtk.css ein, +# setzt adw-gtk3(-dark) und color-scheme (braucht Paket adw-gtk3) +# - labwc: schreibt das openbox-Theme + setzt noctalia in rc.xml +# Aenderung per GUI (Settings -> Templates) landet in settings.toml und +# gewinnt ueber dieser Datei. Qt/KDE-Apps: Templates "qt"/"kcolorscheme" +# sind absichtlich aus (keine Qt-Apps installiert). +[theme.templates] +enable_builtin_templates = true +builtin_ids = ["alacritty", "gtk3", "gtk4", "labwc"] diff --git a/iso/iso.toml b/iso/iso.toml index 05f3153..1f12486 100644 --- a/iso/iso.toml +++ b/iso/iso.toml @@ -1,8 +1,14 @@ # ISO configuration for a bootc-based installer ISO # --- Kickstart: post-install bootc switch --- +# HINWEIS: lang/keyboard laesst Anaconda u.a. /etc/vconsole.conf schreiben +# (deutsche TTYs). Die :stable-Referenz unten wird beim lokalen ISO-Build +# per Justfile auf $target_image:$tag umgeschrieben (Test-ISOs!). [customizations.installer.kickstart] contents = """ +lang de_DE.UTF-8 +keyboard --vckeymap=de --xlayouts='de' +timezone Europe/Berlin --utc %post # Switch to the custom bootc image after installation bootc switch --mutate-in-place --transport registry humocs-man.duckdns.org/humocs-man/fluffy-pancake:stable diff --git a/scripts/kanshi-autoconfig b/scripts/kanshi-autoconfig index 5b0880b..7e5adc4 100755 --- a/scripts/kanshi-autoconfig +++ b/scripts/kanshi-autoconfig @@ -85,9 +85,11 @@ def render(outputs): lines = [ MARKER, f"# generiert am {datetime.now().isoformat(timespec='seconds')}", - "# Quelle: wlr-randr (live). Feintuning: wdisplays oder Hand-Edit", - "# (Hand-Edit: Marker-Zeile loeschen, dann fasst --apply-if-managed", - "# diese Datei nicht mehr an.)", + "# Quelle: wlr-randr (live). Feintuning: wdisplays oder Modus direkt", + "# in dieser Datei anpassen - bei unveraendertem Output-Set bleibt", + "# die Datei (inkl. deiner Modus-Tweaks) bei jedem Login erhalten.", + "# Neu generiert wird nur bei geaendertem Output-Set (Docking) oder", + "# per --apply. Marker-Zeile loeschen = ganz hand-gepflegt.", "", ] externals = [o for o in outputs if not o["internal"]] @@ -146,13 +148,28 @@ def apply(text): print(f"Geschrieben: {CONFIG_PATH}") +def config_output_names(path: Path): + """Output-Namen aus einer bestehenden kanshi-Config (ohne '*' Fallback).""" + names = set() + try: + for line in path.read_text().splitlines(): + parts = line.strip().split() + if len(parts) >= 2 and parts[0] == "output" and parts[1] != "*": + names.add(parts[1].strip("'\"")) + except OSError: + pass + return names + + def main(argv): outputs = detect_outputs() if not outputs: - print("WARN: keine Outputs erkannt - schreibe Fallback-Config", file=sys.stderr) + print("WARN: keine Outputs erkannt", file=sys.stderr) text = render(outputs) # Default ohne Schreib-Flag: nur anzeigen, nichts schreiben (sicher). if "--print" in argv or ("--apply" not in argv and "--apply-if-managed" not in argv): + if not outputs: + print("# (Fallback-Anteil, da keine Outputs erkannt)", file=sys.stderr) print(text) if outputs: print( @@ -160,9 +177,25 @@ def main(argv): file=sys.stderr, ) return 0 - if "--apply-if-managed" in argv and not is_managed(CONFIG_PATH): - print(f"{CONFIG_PATH} ist hand-gepflegt - lasse sie unangetastet.") - return 0 + if "--apply-if-managed" in argv: + if not CONFIG_PATH.exists(): + apply(text) # Erst-Login: anlegen + return 0 + if not is_managed(CONFIG_PATH): + print(f"{CONFIG_PATH} ist hand-gepflegt - lasse sie unangetastet.") + return 0 + if not outputs: + # Erkennung fehlgeschlagen -> niemals eine gute Config clobbern. + print("WARN: Erkennung fehlgeschlagen - lasse verwaltete Config unangetastet.", + file=sys.stderr) + return 0 + if {o["name"] for o in outputs} == config_output_names(CONFIG_PATH): + # Gleiches Output-Set (z.B. jeden Boot dieselbe VM-Anzeige): + # Modus-Tweaks des Users bleiben erhalten, kein Rewrite. + print(f"Outputs unveraendert ({', '.join(sorted(config_output_names(CONFIG_PATH)))})" + " - behalte Config (inkl. Modus-Tweaks) bei.") + return 0 + # Output-Set geaendert (angedockt/abgedockt): neu generieren. apply(text) return 0 diff --git a/scripts/seed-labwc-skel.sh b/scripts/seed-labwc-skel.sh index 89d5f37..9182e80 100755 --- a/scripts/seed-labwc-skel.sh +++ b/scripts/seed-labwc-skel.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# seed-labwc-skel: kopiert fehlende labwc/kanshi-Defaults aus /etc/skel. -# Nuetzlich nach Rebase von Kinoite auf den labwc-Zweig, weil /home +# seed-labwc-skel: kopiert fehlende Desktop-Defaults aus /etc/skel. +# Nuetzlich nach Rebase auf den labwc-Zweig, weil /home (/var/home) # erhalten bleibt und /etc/skel nur bei NEU angelegten Benutzern greift. # Bestehende Dateien werden NIEMALS ueberschrieben (cp -n). set -euo pipefail @@ -12,6 +12,11 @@ TARGETS=( ".config/labwc/rc.xml" ".config/labwc/menu.xml" ".config/kanshi/config.template" + ".config/alacritty/alacritty.toml" + ".config/alacritty/themes/noctalia.toml" + ".config/noctalia/templates.toml" + ".config/noctalia/shell.toml" + ".config/mimeapps.list" ) for rel in "${TARGETS[@]}"; do @@ -31,3 +36,15 @@ if [[ ! -e "${HOME}/.config/kanshi/config" ]]; then echo "Keine kanshi-Config gefunden. Erzeugen mit:" echo " kanshi-autoconfig --apply (schreibt ~/.config/kanshi/config)" fi + +# Wallpaper-Grundstock (Dateinamen unbekannt -> Glob statt Liste) +if [[ -d "${SKEL}/Pictures" ]]; then + mkdir -p "${HOME}/Pictures" + for pic in "${SKEL}"/Pictures/*; do + [[ -e "${pic}" ]] || continue + if [[ ! -e "${HOME}/Pictures/$(basename "${pic}")" ]]; then + cp -n "${pic}" "${HOME}/Pictures/" + echo "angelegt: ${HOME}/Pictures/$(basename "${pic}")" + fi + done +fi