This repository has been archived on 2026-09-17. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
nixos-config/Plan.md
pijukka ef9d2a1a2b Archive nixos-config after the per-host repo split
tnix, pinix and blunix now build and deploy from their own repositories.
This is the last commit here; the repository is archived on Forgejo and
mirrored to pinix's cgit. See Plan.md and docs/repo-split-inventar.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 13:30:29 +02:00

276 lines
14 KiB
Markdown

# Plan: nixos-config in drei eigenständige Repositories aufteilen
Stand: 17.09.2026 — Entscheidungen aus der Plan-Review eingearbeitet.
## Ausgangslage
Alle drei Maschinen (`tnix`, `pinix`, `blunix`) werden aktuell über ein
gemeinsames Repository `nixos-config` verwaltet (1750 Commits, ein Flake,
gemeinsame `globalServices/`, eine `secrets/secrets.nix` für alle Hosts).
Ziel sind drei eigenständige Repositories, deren Grenzen der Rolle der
jeweiligen Maschine folgen. Hostnamen bleiben unverändert.
| Repo | Host | Rolle |
| -------- | -------- | -------------------------------------------- |
| `tnix` | `tnix` | persönliche Maschine (Laptop) |
| `pinix` | `pinix` | persönliche, autonome Server-Infrastruktur |
| `blunix` | `blunix` | gemeinsam nutzbare Plattform (`0ff.space`) |
## Rollen
### tnix
- persönlich, lokal, die eigentliche Arbeitsmaschine
- Konfiguration betrifft primär die eigene Arbeitsumgebung (inkl.
home-manager)
### pinix
- Raspberry Pi 4 (aarch64), persönlicher autonomer Server
- IPv6, soll möglichst unabhängig funktionieren
- hostet persönliche Dienste und Tools
- **cgit** als persönlicher Git-Server (nur im pinix-Tailnet)
- **eigener Identity-Stack** (Dex + LLDAP + Headscale unter `domain2`)
- **Headscale ist das Admin-Tailnet**: alle drei Hosts sind Mitglied
(Stand seit 14.09.2026, bleibt so)
- Uplink: pinix hat die Funktionen des (offline genommenen) Mango-Routers
übernommen
- **`lukasrosier.com`** gehört hierher und läuft auf pinix, **IPv6-only**
(bisher bewusst auf blunix — Umzug ist Teil der Aufteilung; kein
IPv4-Proxy über blunix)
### blunix
- VPS, **bleibt dauerhaft** als gemeinsame Plattform
(Roadmap-Punkt „VPS durch IPv6 ersetzen" damit erledigt/umformulieren)
- Dienste, die mit anderen Menschen geteilt werden, über `0ff.space`:
Launcher/Startseite, Prosody/XMPP, xmpp-web, Forgejo, künftige
Kommunikationsdienste
- **eigener Identity-Stack** (Dex + LLDAP + Headscale für `0ff.space`);
der blunix-Headscale ist nur für geteilte Nutzer, nicht für die Admin-
Verbindung zwischen den eigenen Hosts
- **Forgejo** als Git-Server
## Git: Source of Truth und Clones
Jedes Repo hat sein Origin auf „seinem" System; auf den anderen Systemen
liegen Clones. Bearbeitung ist überall möglich: direkt auf dem Host, oder
auf `tnix` lokal bzw. agentisch per SSH, mit Remote-Build auf dem Zielhost.
Maßgeblich ist immer das versionierte Origin.
| Repo | Origin (Source of Truth) | Clones / Mirror |
| --------------- | ------------------------------ | -------------------------------- |
| `tnix` | `~/tnix` auf `tnix` | Mirror auf pinix/cgit |
| `pinix` | pinix/cgit | Clone auf tnix |
| `blunix` | blunix/Forgejo | Clone auf tnix |
| `ereader-viewer`| pinix/cgit | Flake-Input des `pinix`-Repos |
| `website` | pinix/cgit (bisher Forgejo) | Auto-Pull auf pinix |
| `memory` | pinix/cgit (aus `memory/`) | Clone auf tnix |
| `nixos-config` | Archiv, read-only | im Backup |
## Entscheidungen
1. **Gemeinsame Module werden kopiert**, kein viertes common-Repo.
`globalServices/` (sshd, security, zsh, journald, packages, …) landet
als Kopie in jedem Repo und darf pro Rolle auseinanderlaufen. Ebenso
bekommt jedes Repo sein eigenes `variables.nix`/`variables-local.nix`
mit nur den dort gebrauchten Optionen.
2. **Git-Historie: frischer Start.** Die neuen Repos beginnen mit einem
Initial-Commit. `nixos-config` wird vorher mit dem vollständigen
aktuellen Stand committet und danach read-only archiviert.
3. **Secrets pro Repo.** Jedes Repo bekommt eine eigene
`secrets/secrets.nix` mit nur den eigenen Host-Keys als Empfänger;
betroffene `.age`-Dateien werden kopiert und per `agenix -r` neu
verschlüsselt. Geteilte Secrets (z. B. `dns-challenge`, `domain`,
`mailPW`) werden pro Repo dupliziert — wo sinnvoll, später getrennt
rotiert.
4. **Build-unabhängig, nicht laufzeit-unabhängig.** Jedes Repo baut ohne
die anderen. Zur Laufzeit bleiben bewusste Kopplungen (siehe unten),
die als Werte in `variables.nix` statt als Cross-Repo-Importe
abgebildet werden.
5. **Agents (agent-codex, board-agent, orga-agent, `agents/`)** werden
ins `blunix`-Repo übernommen, aber **nicht importiert** (deaktiviert).
Über Reaktivierung und Repo-Zugriff wird später entschieden.
6. **GoToSocial** läuft aktuell nirgends und ist **nicht** Teil der
Aufteilung — kommt danach als eigener Schritt ins `blunix`-Repo.
7. **ereaderViewer** (`path:/home/builder/ereader/viewer`) wird ein eigenes
Repo auf pinix/cgit und per Git-URL als Flake-Input eingebunden.
## Bekannte Laufzeit-Kopplungen
- **Admin-Tailnet:** blunix und tnix hängen am pinix-Headscale. Fällt
pinix aus, ist blunix nur noch öffentlich per SSH erreichbar.
- **Traefik auf blunix → pinix-Backends:** keine mehr aktiv — alle
Routen dorthin sind tot und werden auskommentiert übernommen
([Inventar](docs/repo-split-inventar.md)).
- **Forgejo-Hostkey** auf allen Hosts; pinix kann das blunix-Repo im
Notfall klonen. SSH blunix → pinix (`nixbuild.nix`) entfällt.
- **tnix-Backup-Skripte** ziehen per rsync von pinix und blunix.
- **`lukasrosier.com` auf pinix:** bewusst IPv6-only, keine Kopplung
an blunix.
## Backup
Zentraler Ordner, als Ganzes auf einen USB-Stick kopierbar, unabhängig von
der Erreichbarkeit von pinix oder blunix:
```text
nixos-backup/
├── tnix.bundle
├── pinix.bundle
├── blunix.bundle
├── ereader-viewer.bundle
├── website.bundle
├── memory.bundle
└── nixos-config.bundle # Archiv
```
Umfang: **nur die Git-Repos**, vollständig mit allen Branches (`git bundle
create … --all` oder `git clone --mirror`). Nicht enthalten: Flake-Inputs
für Offline-Rebuilds, private Keys zum Entschlüsseln der Secrets,
Dienst-Daten (die sichert weiterhin restic).
## Vorgehensweise
1. **Laufenden Stand sichern:** uncommittete Änderungen (live-intent,
ereader-viewer, tailnet-dns, tnix-Configs, docs, …) in `nixos-config`
committen und pushen.
2. **Inventar erstellen** ([`docs/repo-split-inventar.md`](docs/repo-split-inventar.md)): jedes Modul, jeder Service, jedes Secret, jedes
Skript, jede Datei unter `docs/`, `services/`, `scripts/`, `home/`,
`agents/` → Zuordnung `tnix` / `pinix` / `blunix` / kopieren / Archiv;
dazu alle Cross-Host-Referenzen (`tailnetIPs.*`, Traefik-Routen,
Webhooks, known_hosts, nixbuild).
3. **Neue Repos auf cgit:** `ereader-viewer` (Flake-Input umstellen),
`website` (von Forgejo umziehen, inkl. `scripts/resize-image.sh`),
`memory` (aus `memory/`). — *Erledigt 17.09.2026:* alle drei unter
`/var/lib/git` angelegt; `ereader-viewer` frisch importiert und als
`git+file`-Input eingebunden (pinix-Switch ergab dasselbe System);
`website` als Mirror aller Branches, Forgejo-Kopie bleibt bis Schritt 5
parallel und synchron (Auto-Pull auf blunix); `memory` per
`git subtree split`.
4. **tnix als Pilot:** Repo aufbauen, Muster für kopierte globalServices,
`variables.nix` und `secrets.nix` festlegen. Rebuild auf tnix,
Origin unter `~/tnix`, Mirror auf cgit. — *Erledigt 17.09.2026*
(`~/tnix` @ `0d77a25`). Festgelegtes Muster für pinix/blunix:
- flaches Layout ohne `hosts/<name>/`: `configuration.nix`,
`globalServices/` (nur tatsächlich importierte Kopien, ohne
`secretFiles.nix`), `localServices/`, `user/`, `secrets/`, `tests/`
- `variables.nix` nur mit den Optionen, die das Repo liest
- `secrets/secrets.nix` nur mit eigenen Keys, `.age`-Dateien per
`agenix -r` neu verschlüsselt, Inhalte per `agenix -d` gegengeprüft
- `flake.lock` aus `nixos-config` übernehmen, damit nixpkgs-Revisionen
gleich bleiben; vor dem Switch `diff-closures` gegen das laufende
System (Pilot-Check)
- Mirror: Bare-Repo auf cgit + `post-commit`-Hook (`git push --mirror`)
Ergebnis-Diff tnix: nur 15 ungenutzte Secrets weg, `fastpi` aus
`/etc/hosts`, wpa-Units mit neuen Restart-Triggern. `switch` sauber,
WLAN/Tailnet/SSH/cgit danach geprüft. tnix wird ab jetzt nur noch aus
`~/tnix` deployt; `hosts/tnix` hier ist eingefroren.
5. **pinix:** Repo aufbauen, `lukasrosier.com` von blunix übernehmen
(Auto-Pull-Hook für das `website`-Repo). Website-Bilder aus
`/var/www/website-data` (von blunix kopiert am 17.09.) mit
Verzeichnis-Listing ausliefern, `data.0ff.space`-URLs im `website`-Repo
umstellen, Default-Ziel von `scripts/resize-image.sh` anpassen; danach
Nachzügler von blunix per rsync abgleichen. — *Erledigt 17.09.2026
bis auf den letzten DNS-Schritt* (Repo `pinix` @ `e9cf08b` auf cgit,
Arbeitskopie `~/pinix` auf tnix, Build-Verzeichnis
`pinix:/home/drone/pinix-build`):
- pinix läuft aus dem neuen Repo; `diff-closures` vorher zeigte nur
erwartete Änderungen. Headscale scheiterte beim Switch einmal am
gleichzeitigen Traefik-Neustart (OIDC-Discovery EOF) und lief beim
automatischen Restart; danach `running`, keine failed Units.
- Dex/Headscale-Client-Secret neu generiert (nicht mehr mit blunix
geteilt), gegen Dex' Token-Endpunkt geprüft (richtig 400, falsch 401).
- Website: `website.nix` mit `post-receive`-Hook in `website.git`
(Branch `dev`, der auch auf blunix live war); Bilder unter
`/pictures/` und `/booklet.pdf` aus `/var/www/website-data`. Im
`website`-Repo URLs relativ gemacht (`df5f230`); alle 26 verlinkten
Dateien 200, von blunix aus über pinix' öffentliches IPv6 mit
gültigem Zertifikat getestet. Forgejo-Kopie von `website` ist ab
hier veraltet (Archiv in Schritt 7).
- DNS: Cloudflare-Proxy bleibt (Entscheidung 17.09.). Apex hat
MX/NS/TXT, daher proxied AAAA statt CNAME für `lukasrosier.com` und
`www`, gepflegt von `wan-dns-update` (folgt der NAT66-Adresse).
- **Offen:** die alten A-Einträge (`23.88.33.137`, blunix) für
`lukasrosier.com` und `www` löschen. Solange sie existieren,
bevorzugt Cloudflare blunix als Ursprung — Besucher sehen noch die
alte Kopie mit `data.0ff.space`-Bildern (funktioniert). Nach dem
Löschen `data.`-Kopie der Bilder erst in Schritt 6 entfernen.
- Altes `.git` der Website-Checkout auf pinix liegt unter
`/home/drone/website-checkout-git.bak-20260917`.
- *Nachtrag 17.09.2026:* A-Einträge gelöscht (auf ausdrückliche
Anweisung). Über IPv4 (Cloudflare) und IPv6 liefert jetzt pinix aus
(`version.json` = `df5f230`, Bilder 200).
Rebuild lokal auf pinix (rsync-Zyklus). Origin auf cgit, Clone auf tnix.
6. **blunix** (zuletzt, vorsichtig — Aussperr-Risiko): Repo aufbauen,
Website und Agents entfernen bzw. deaktivieren, Traefik-Routen auf
pinix-Backends bereinigen. Rebuild auf blunix. Origin auf Forgejo,
Clone auf tnix. — *Erledigt 17.09.2026* (`lukas/blunix` auf Forgejo,
privat per Push-to-Create, @ `fd4c876`; Checkout
`/home/drone/blunix`, Clone `~/blunix` auf tnix):
- Agents, orga-Dienste, tasks, graphify-refresh, oauth2-proxy,
`website-production` und `nixbuild.nix` sind aus; tote Routen,
Dex-Clients, AdGuard-Rewrites und die pinix-IP in Forgejos
Webhook-Allowlist auskommentiert. Closure ~1 GB kleiner (Chromium,
numpy & Co. hingen an den Agents).
- Aussperr-Check vor dem Switch: sshd, Firewall, Netz, tailscaled
unverändert (nur SSH-*Client*-Config/known_hosts durch
`nixbuild.nix`). `hosts/blunix/localServices/sshd.nix` war nie
importiert (lauscht auf alten 100.64-Adressen) — Archiv.
- Korrektur zum Inventar: `bindPW.age` wird auf blunix gelesen
(Prosody-Include `/run/agenix/0ff.space.cfg.lua`), ist mitgenommen.
- Headscale scheiterte beim Switch wie auf pinix einmal an der
gleichzeitig neu startenden Dex/Traefik-Kette und lief beim Restart.
Danach `running`, keine failed Units; öffentlich geprüft: `0ff.space`,
`git.`, `dex.`, `lldap.`, `head.`, `data.`, `hdm.`, `upload.`, XMPP
5222/5269, intern `schema.`.
- **Befund pinix (offen):** Seit dem pinix-Switch um 13:08 hatte der
technische Node `pinix-dns` (`tailscaled-pinix`) keine
Control-Verbindung mehr (`PollNetMap` gegen `127.0.0.1:443`), der
Datenpfad zu cgit lief weiter. `systemctl restart tailscaled-pinix`
hat es behoben. Der Prozess sieht trotz `BindReadOnlyPaths` die
Host-`/etc/hosts` (dex./head. → 127.0.0.1); Mechanismus nicht
geklärt. Nach pinix-Switches, die `/etc/hosts` ändern, prüfen.
- Die Admin-Sitzung unter `/home/drone/nixos-config` auf blunix ist
unverändert; blunix wird ab jetzt nur noch aus `/home/drone/blunix`
deployt.
- Die Bilder-Kopie unter `blunix:/var/www/data/external/pictures`
bleibt (Entscheidung 17.09.2026).
7. **nixos-config archivieren** (Forgejo: read-only/archiviert), Checkouts
unter `/home/drone/nixos-config` durch die neuen Repos ersetzen. —
*Erledigt 17.09.2026* (dieser Commit ist der letzte):
- Alle `nixos-config*`-Verzeichnisse auf blunix (6, inkl. Wiki-Checkout)
und pinix (10) nach `/home/drone/archiv-nixos-config-20260917/`
verschoben, nicht gelöscht. Uncommittete Stände darin waren alte
Zwischenstände (letzter Commit 12.09.), inhaltlich längst in der
Historie. Ersetzt durch `/home/drone/blunix` (Clone) bzw.
`/home/drone/pinix-build` (rsync-Ziel).
- Archiv-Hinweis oben in README.md, AGENTS.md, CLAUDE.md.
- Danach: `git push --mirror` auf pinix-cgit (`nixos-config.git`), dann
`nixos-config` und `website` auf Forgejo archiviert.
- Die Plan-Fortschreibung für Schritt 8 und 9 liegt ab hier in
`~/tnix/docs/repo-split/` (tnix ist die Admin-Arbeitsmaschine).
8. **Backup-Skript** für `nixos-backup/` schreiben und testen: Ordner auf
USB kopieren, auf einer anderen Maschine aus den Bundles klonen.
9. **Doku nachziehen:** README/CLAUDE.md/AGENTS.md pro Repo,
`docs/roadmap.md` (VPS-Punkt), `docs/repos.md`.
## Weitere Festlegungen
- **LLDAP:** Nutzer und Gruppen bleiben so, wie sie aktuell auf den
Systemen aktiv sind (blunix-LLDAP für `0ff.space`, pinix-LLDAP für
`domain2`) — keine Migration im Zuge der Aufteilung.
- **Doku zu Mango** (CLAUDE.md, `docs/networking.md` u. a.) ist veraltet
und wird in Schritt 9 nachgezogen.
## Designziel
```text
tnix = meine persönliche Maschine
pinix = meine persönliche/private Server-Infrastruktur
blunix = gemeinsam nutzbare Plattform-Infrastruktur
```
Die technische Struktur — Repo-Grenzen, Git-Hosting, Identität, Secrets —
folgt dieser Trennung.