Files
taninux/docs/distribution.md
T
karim faaba27ed4 Display arrangement persistence + centering fix, packaging hardening
- core/display.py: write_positions() persists Arrangement's drag-and-drop
  layout into niri's config.kdl (one output { position x= y= } per output),
  validated via `niri validate` on a temp copy with a .kdl.bak backup before
  writing — same pattern as core/keybindings.py's rebind(). Previously the
  page only ever called `niri msg output … position set`, which niri treats
  as live-only and drops on the next login/reload.
- gui/pages/display.py: Arrangement's Apply now runs each output's `niri msg
  output … position set` synchronously instead of queuing them all on the
  single-shot ProcessRunner (which rejects a second run() while the first is
  still async) — a 2-monitor apply previously moved only the first output
  and silently dropped the rest. _dock_to_nearest keeps the free axis at the
  dragged position (so a shorter display can sit vertically centered next to
  a taller rotated one) rather than forcing corner alignment.
- core/panel.py, files/__init__.py: incidental fixes alongside the above.
- packaging/: signing-key generation script + build-user systemd setup for
  the [tanin] AUR auto-rebuild pipeline; PKGBUILD bumped to pkgrel=5.
- src/taninux/browser/: new module for browser theme sync (Fuji accent).
2026-07-13 14:19:50 +02:00

173 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# TANINUX — Verteilung als „Distro"
Ziel: ein Calamares-Installer, der eine fertige TANINUX-Umgebung aufsetzt.
Modell: **eigenes Binär-Repo `[tanin]` nur für eigene Pakete**, alles Standard
aus den **offiziellen Arch-Repos** (wie CachyOS/EndeavourOS).
## Pakete
| Paket | Repo | Inhalt |
|------------------|-------------|-----------------------------------------------------|
| `taninux` | `[tanin]` | App: tsettings + thub + TUI, Helper, polkit, .desktop |
| `tanin-eww` | `[tanin]` | eww Panel/Dock-Config + Scripts (→ /usr/share) |
| `tanin-setup` | `[tanin]` | seedet `~/.config` aus /usr/share + Portal/Session-Fix |
| `tanin-desktop` | `[tanin]` | **Metapackage**: depends = eigene + Arch-Pakete |
`tanin-desktop` zieht per `depends` die Arch-Pakete aus den normalen Repos und
die eigenen aus `[tanin]`. AUR bleibt Opt-in → `paru` ist `optdepends`, kein
hartes `depends` (Metapackage baut also nichts aus dem AUR).
## Dotfile-Auslieferung (wichtig)
AUR/Binär-Pakete dürfen **nicht** nach `/home` schreiben. Daher:
1. Default-Configs ins Paket nach `/usr/share/tanin/` (oder `/etc/skel/`).
2. `tanin-setup` kopiert sie beim ersten Start nach `~/.config` (idempotent,
überschreibt nichts ohne `--force`) und richtet das Session-Portal ein
(siehe „Dark Mode / Portal" unten).
## Phasen
1. **Fundament**`packaging/taninux/PKGBUILD` (fertig), LICENSE (✅ da,
GPL-3.0-or-later), `cd packaging/taninux && makepkg -si` lokal testen.
2. **Meta + Config**`tanin-desktop` (Skelett da), `tanin-eww`, `tanin-setup`.
3. **Eigenes Repo `[tanin]`**. Hosts:
- **Code** → `git.openbureau.ch/karim/taninux` (PKGBUILD-`source`, woher `makepkg` klont)
- **Projekt + Repo** → `taninux.kgva.ch` (PKGBUILD-`url`/Homepage **und** pacman-`Server`)
DB bauen + signieren:
```sh
repo-add -s tanin.db.tar.zst *.pkg.tar.zst # -s signiert mit Packager-Key
```
Hosten — zwei Optionen:
- **Gitea/Forgejo Arch-Registry** (falls git.openbureau.ch das kann): Pakete
pushen, `Server = https://git.openbureau.ch/api/packages/karim/arch/<repo>`.
`taninux.kgva.ch` als Reverse-Proxy/Vanity davor.
- **Statisches Verzeichnis** hinter `taninux.kgva.ch`: `*.pkg.tar.zst` + `tanin.db`.
`pacman.conf`-Snippet für **bestehende** User (unverändert, siehe Warnung):
```ini
[tanin]
# TEMPORÄR + UNSICHER: TrustAll akzeptiert JEDES Paket ohne Signaturprüfung.
# Nur zum Bootstrappen, solange die DB noch nicht signiert ist. Sobald der
# Packager-Key steht -> auf "Required DatabaseOptional" umstellen (siehe unten).
SigLevel = Optional TrustAll
Server = https://taninux.kgva.ch/$arch
```
> **Wichtig:** Dieses Snippet bleibt bewusst auf `Optional TrustAll`, auch
> nachdem Signing verdrahtet ist (siehe unten) — würde man es hier auf
> `Required` umstellen, würde das nächste `-Syu` bei allen bestehenden
> Usern gegen das *heute* unsignierte Repo fehlschlagen. Neue Installs
> (ISO/Calamares) bekommen `Required DatabaseOptional` bereits vorkonfiguriert
> (siehe `iso/overrides/airootfs/etc/pacman.conf`). Bestehende User steigen
> über den **Cutover**-Abschnitt unten manuell um, sobald das Repo signiert
> ausgeliefert wird.
#### Repo-Signing
Verdrahtet (`packaging/`):
- `packaging/gen-signing-key.sh` erzeugt den Packager-Key EINMALIG
(Ed25519, `gpg --batch --gen-key`, interaktive Passphrase — kein
Hardcoding) und druckt danach die Export-/Cutover-Schritte aus.
- `build-tanin-repo.sh`, `finish-tanin-repo.sh`, `aur-autoupdate.sh` lesen
`GPGKEY` aus der Umgebung und **brechen fail-closed ab**, wenn er fehlt —
es wird nie stillschweigend unsigniert gebaut. Pakete werden mit
`makepkg --sign` (bzw. bei `aur-autoupdate.sh`, das im isolierten
`makechrootpkg`-Chroot baut, per `gpg --detach-sign` direkt nach dem
Kopieren aus dem Chroot) signiert, die DB mit `repo-add -s -k "$GPGKEY"`.
Noch manuell/offen:
1. `packaging/gen-signing-key.sh` einmal ausführen (noch nicht geschehen —
dieser Repo-Stand enthält KEINEN Key) und den privaten Key sicher
sichern (siehe Skript-Output).
2. Public Key exportieren nach `iso/overrides/airootfs/etc/pacman.d/tanin-repo.gpg`
(+ `iso/build-profile/...`, wird bei jedem `bootstrap-profile.sh`-Lauf
aus `overrides/` neu kopiert) und öffentlich unter
`taninux.kgva.ch/tanin.gpg` (o. ä.) ablegen.
3. In `iso/overrides/airootfs/root/customize_airootfs.sh` eine zweite
`pacman-key --lsign-key <packager-fpr>`-Zeile ergänzen (siehe Kommentar
dort) — ohne die bleibt der Key zwar importiert, aber nicht getrustet.
4. `GPGKEY` in `packaging/systemd/tanin-aur-update.service` setzen (dort
als Kommentar vorbereitet) und den geheimen Key ins `GNUPGHOME` des
`tanin-build`-Users legen (siehe „Build-Infrastruktur" unten).
5. Sobald das ausgelieferte Repo tatsächlich signierte Pakete + DB serviert:
bestehende User per **Cutover**-Anleitung (unten) umstellen.
6. **Calamares / ISO** ✅ — `archiso`-Profil mit `[tanin]` vorkonfiguriert +
Calamares `packages`-Modul, das `tanin-desktop` installiert
(`iso/build-profile/`, gebaute ISO in `iso/out/`). Neue Installs starten
direkt mit `Required DatabaseOptional`.
#### Cutover für bestehende User (Optional TrustAll → Required DatabaseOptional)
Erst durchführen, wenn Schritt 14 oben erledigt sind und `taninux.kgva.ch`
(bzw. die Gitea-Registry) tatsächlich signierte Pakete + eine signierte DB
ausliefert — vorher würde `Required` jedes `-Syu` brechen.
```sh
# 1) Packager-Pubkey importieren + lokal signieren (einmalig, als root)
curl -o /tmp/tanin-repo.gpg https://taninux.kgva.ch/tanin.gpg # oder gleicher Pfad wie oben
pacman-key --add /tmp/tanin-repo.gpg
pacman-key --lsign-key <packager-fingerprint> # Fingerprint aus gen-signing-key.sh
# 2) In /etc/pacman.conf das [tanin]-SigLevel umstellen
# von SigLevel = Optional TrustAll
# auf SigLevel = Required DatabaseOptional
# 3) Testen
sudo pacman -Sy
sudo pacman -S tanin-desktop --dbonly # oder ein beliebiges [tanin]-Paket
```
Schlägt Schritt 3 fehl ("signature is unknown trust" o. ä.), war entweder
Schritt 1 unvollständig (Key nicht lsigned) oder das Repo liefert noch
nicht signierte Pakete — dann bei `Optional TrustAll` bleiben.
## Dark Mode / Portal (Session-Fix)
libadwaita-Apps (Nautilus etc.) lesen Hell/Dunkel über
`org.freedesktop.portal.Settings`. Damit das Portal startet, muss die Session
`graphical-session.target` aktivieren. `tanin-setup` legt dafür
`~/.config/systemd/user/<wm>-session.target` an und ergänzt die Compositor-
Autostarts:
```sh
exec-once = dbus-update-activation-environment --systemd --all
exec-once = systemctl --user start <wm>-session.target
```
## Build-Infrastruktur
Der tägliche AUR-Rebuild (`packaging/aur-autoupdate.sh`, via
`packaging/systemd/tanin-aur-update.timer`) braucht `makechrootpkg` /
`arch-nspawn` / `mkarchroot` als root — effektiv root-äquivalent (baut
beliebige, aus dem AUR gezogene `PKGBUILD`s in einem chroot). Das lief bisher
per NOPASSWD-`sudo` auf dem persönlichen Account `karim`. Stattdessen jetzt:
ein dedizierter, gesperrter Systemaccount **`tanin-build`**
(`packaging/systemd/setup-build-user.sh`, Home `/var/lib/tanin-build`, kein
Passwort/Login) — nur dieser Account bekommt den NOPASSWD-Sudo-Grant
(`packaging/systemd/tanin-aur-update.sudoers`), und der systemd-Service läuft
mit `User=tanin-build`/`Group=tanin-build`. Ein kompromittiertes AUR-PKGBUILD
(oder ein Bug in der Pipeline) kann so nicht mehr `karim`s eigentlichen
Account root-äquivalent übernehmen — nur den isolierten Build-Account, der
sonst nichts kann.
Konsequenzen für Pfade: Der systemd-Unit nutzt `%h`-Spezifier, die jetzt gegen
`tanin-build`s Home auflösen, nicht mehr `/home/karim`. `setup-build-user.sh`
synct dafür einmalig einen Checkout nach `/var/lib/tanin-build/taninux` (muss
nach `git pull` erneut laufen) und legt `/var/lib/tanin-build/.gnupg` an — dort
muss der geheime Packager-Key (siehe „Repo-Signing" oben) importiert sein,
sonst kann `tanin-build` nichts signieren. Einrichtung: `sudo
packaging/systemd/setup-build-user.sh` (erstellt User, synct Repo, installiert
Sudoers-Drop-in + `.service`/`.timer` als System-Units).
## Hosts
- **Code:** `git.openbureau.ch/karim/taninux` (+ Repo für die eww-Config,
Absprache mit der eww-Instanz).
- **Projekt/Repo:** `taninux.kgva.ch` (Homepage + `[tanin]`-pacman-Server).
## Offene Voraussetzungen
- **LICENSE**-Datei ablegen (Vorschlag GPL-3.0-or-later):
`curl -L https://www.gnu.org/licenses/gpl-3.0.txt -o LICENSE`.
- `taninux.kgva.ch` ans Repo-Hosting hängen (Gitea-Arch-Registry oder statisch).