faaba27ed4
- 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).
173 lines
8.7 KiB
Markdown
173 lines
8.7 KiB
Markdown
# 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 1–4 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).
|