feat: slice 3 - wiki, sources and AARs in their neckbeard homes

Gate 4, slice 3: verfahren/, hosts/, vision/ and shared/ moved via git
mv - six AARs to docs/aar/ (four harvested by the 2026-08-09 retro,
two open), procedures and host knowledge to docs/wiki/ (admin,
deployment, architecture, new area vision), the retro protocol and the
commit mapping table to docs/sources/ (protokolle/, migration/). New:
the wiki index linking every page, and the mirror-topology page
carrying the why-two-places reasoning verbatim from the old CLAUDE.md
(F-013 preserved). All moved-path references retargeted; the link
checker drove the sweep to zero.

pruefe_prosa.py added (pattern C+D): SHA citations resolve via repo,
mapping table, optional component clones or a curated exemption list
(documented dead Gitea-force-push commits, a vendor-repo tag, an
Authentik uid that is hex but no git SHA, the external neckbeard
reference); wiki task prose without an issue reference errors, with a
visible pragma for deliberate checklists; the dead-tracker denylist
now covers every mirrored repo's retired Gitea tracker (F-005) - two
links re-verified against live GitLab titles and retargeted, five
defused into honest historical citations.

Verified: validate 0/0, gen_status --check current, drift 0. Demo on
the pre-migration state fires 6 findings (3 orphaned SHAs, 3 task
blocks); on the current tree exactly the 3 F-004 task blocks remain -
they turn green in slice 4 when the issues exist, which is why
pruefe_prosa joins CI only then.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Thore Cimbal
2026-08-11 12:00:00 +00:00
co-authored by Claude Fable 5
parent 70e81e2ff1
commit 92b448fe30
37 changed files with 424 additions and 120 deletions
+220
View File
@@ -0,0 +1,220 @@
---
type: wiki-page
area: architecture
related: []
---
# Branding: Marke, Farben, Bildsprache
Übergreifend, weil dieselben Farben in mehreren Oberflächen eingestellt werden
(Chat-Clients, Wikis, künftige Dienste) und sich das nicht pro Host oder Linie
trennen lässt: **Bestand** (welche Farbe wo eingetragen ist) und **Historie**
(was wann warum geändert wurde).
Hier im `management`-Repo, weil es als einziges der beteiligten Repos
**gespiegelt** ist und jede Werkzeugentscheidung überlebt: Wird das
BookStack-Experiment nach [ADR-0007](../../adr/0007-wiki-oberflaeche-docusaurus-vs-bookstack.md)
abgeräumt oder ein Client ersetzt, bleiben Marke und Paletten bestehen.
## Bildmarke
`threadnet-mark.png` (Bildmarke) und `threadnet-logo-wortmarke.png` (mit
Schriftzug), erstellt von sorb. Sie liegen im Wiki-Repo unter `static/img/` und
sind die Quelle für alle abgeleiteten Formate — Favicon, App-Icons für macOS,
Windows und Linux, Web-Icons.
⚠️ Beim Ableiten den **transparenten Rand wegschneiden** und mit `resize()`
skalieren, nicht mit `thumbnail()` — Letzteres verkleinert nur und lässt das Motiv
in großen Icons als Briefmarke zurück (real passiert, siehe
[AAR 2026-08-02](../../aar/2026-08-02-wiki-und-desktop-clients.md)).
⚠️ **Und danach mittig setzen — das ist ein zweiter, eigener Schritt.** Beim ersten
Anlauf wurde nur beschnitten und skaliert: Das Motiv füllte 81 % der Breite, saß
aber mit 3 % Rand oben und 40 % unten an der Oberkante. In runden und quadratischen
Icon-Slots fällt das sofort auf. Korrigiert am 2026-08-06 auf 21 % oben wie unten.
**Das Rezept, das jetzt gilt:** Bounding-Box des Motivs ermitteln, darauf
beschneiden, auf ~81 % der Kantenlänge skalieren, auf einer quadratischen,
transparenten Fläche **mittig einsetzen**. Alle Größen aus *derselben* Quelldatei
ableiten — dann können sie nicht auseinanderlaufen.
### Wo überall Icons liegen
Elf Artefakte, alle aus einer Quelle (Stand 2026-08-06, `v0.4.0`):
| Ort | Was |
|---|---|
| `apps/web/res/vector-icons/` | 1024, 512, 180, 152, 144, 120, 24 px |
| `apps/desktop/build/icon.png` | App-/Installer-Icon |
| `apps/desktop/build/icon.ico` | Windows, 7 Größen von 16 bis 256 |
| `apps/desktop/build/icon.icns` | macOS, via `iconutil` aus einem `.iconset` |
| `apps/desktop/build/icon.icon/Assets/element.png` | Layer des macOS-Icon-Composers |
Prüfen lässt sich die Gleichheit über die Prüfsumme von `vector-icons/1024.png`
gegen `build/icon.png` — weichen sie ab, ist eine Seite nachgezogen worden und die
andere nicht.
## Paletten
### aXion1337 Dark — das Stammschema
Gruvbox Dark. Grundtöne `#282828` / `#1d2021`, Text `#ebdbb2`, Akzent `#bd93f9`,
Sekundär `#fe8019`. Die acht Username-Farben sind der Gruvbox-Satz.
**`aXion1337 Light` ist das exakte helle Gegenstück** (Gruvbox Light) — gleiche
Rollenverteilung, gespiegelte Helligkeitsachse. Wer eines ändert, zieht das andere
mit.
### Terrakotta-Beige — sorbs BookStack-Schema
Am 2026-08-02 in der BookStack-Oberfläche eingestellt und von dort extrahiert
(die Werte stehen als CSS-Variablen im ausgelieferten HTML). Fünf der sieben sind
der Coolors-Satz `#264653 · #2A9D8F · #E9C46A · #F4A261 · #E76F51`:
| Rolle in BookStack | Wert | Ton |
|---|---|---|
| Primäre Farbe | `#264653` | Charcoal |
| Standard-Linkfarbe | `#5f757b` | gedämpftes Blaugrau |
| Regalfarbe | `#e76e51` | Burnt Sienna |
| Buchfarbe | `#e9c46a` | Saffron |
| Kapitelfarbe | `#f3a261` | Sandy Brown |
| Seitenfarbe | `#77bb41` | Grün |
| Seitenentwurfsfarbe | `#e32400` | Rot |
Bemerkenswert: **dieses von Hand eingestellte Schema ist bis auf zwei Ziffern die
offizielle Sunset-Boulevard-Palette** (siehe nächster Abschnitt) — `#e76e51` statt
`#e76f51`, `#f3a261` statt `#f4a261`. Beide Wege sind unabhängig voneinander auf
demselben Coolors-Satz gelandet. Die Irritation an der ersten Theme-Fassung war
also berechtigt und ließ sich an der Originalquelle belegen.
### theme-factory — die zehn benannten Themes
Quelle ist Anthropics [theme-factory-Skill](https://github.com/anthropics/skills/tree/main/skills/theme-factory):
je Theme vier Farben plus ein Schriftpaar. Sie sind seit 2026-08-02 **wörtlich
übernommen** (gitops `b10b607`), nachdem eine erste Fassung die Namen frei
interpretiert hatte.
| Theme | Hintergrund | hell/dunkel | Akzent · Sekundär · Highlight |
|---|---|---|---|
| Ocean Depths | `#f1faee` | hell | `#2d8b8b` · `#a8dadc` · `#457b9d` |
| Sunset Boulevard | `#264653` | dunkel | `#e76f51` · `#f4a261` · `#e9c46a` |
| Forest Canopy | `#faf9f6` | hell | `#2d4a2b` · `#7d8471` · `#a4ac86` |
| Modern Minimalist | `#ffffff` | hell | `#36454f` · `#708090` · `#d3d3d3` |
| Golden Hour | `#4a403a` | dunkel | `#f4a900` · `#c1666b` · `#d4b896` |
| Arctic Frost | `#fafafa` | hell | `#4a6fa5` · `#d4e4f7` · `#c0c0c0` |
| Desert Rose | `#5d2e46` | dunkel | `#d4a5a5` · `#b87d6d` · `#e8d5c4` |
| Tech Innovation | `#ffffff` | hell | `#0066ff` · `#00ffff` · `#1e1e1e` |
| Botanical Garden | `#f5f3ed` | hell | `#4a7c59` · `#f9a620` · `#b7472a` |
| Midnight Galaxy | `#e6e6fa` | hell | `#2b1e3e` · `#4a4e8f` · `#a490c2` |
⚠️ **Ob ein Theme hell oder dunkel gemeint ist, steht nicht verlässlich in den
Beschreibungen** — „Warm Sand · backgrounds" findet sich bei einem Theme, dessen
Showcase-Seite dunkel ist. Maßgeblich ist `theme-showcase.pdf` im Skill: sieben der
zehn sind hell, nur Sunset Boulevard, Golden Hour und Desert Rose dunkel.
„Midnight" Galaxy ist trotz des Namens ein helles Theme mit dunkelviolettem Akzent.
Wer die Werte prüfen will, rendert die PDF-Seiten und misst die Hintergrundfarbe,
statt der Prosa zu glauben.
Die übrigen Rollen (Flächenabstufungen, Username-Farben) sind aus diesen vier
Farben gemischt — so bleibt jedes Theme in sich stimmig, ohne dass Werte
dazuerfunden werden.
## Namensgebung: ThreadNet oder aXion1337.Chat?
**Beides, auf verschiedenen Ebenen — und das ist Absicht, kein Versehen.**
| Ebene | Name | Wo gesetzt |
|---|---|---|
| Betriebssystem, Startmenü, Installer, PWA | **ThreadNet** | `productName` in `apps/desktop/axion1337/build.json`, `name` in `apps/web/res/manifest.json` |
| in der Anwendung | **aXion1337.Chat** | `brand` in `element-values.yaml` (Prod) und `apps/desktop/axion1337/config.json` |
| eingebettetes Call-Widget | **aXion1337.Chat** | `VITE_PRODUCT_NAME` in `.env.production` (threadnet-call) |
| Anmeldeseite (Authentik) | **ThreadNet** | `branding_title` im Brand-Blueprint (gitops, `apps/authentik/authentik-blueprints.yaml`) |
Das Call-Widget folgt der Zeile darüber: Es läuft *in* der Anwendung, also heißt es
dort auch so. Die Anmeldeseite dagegen kommt **vor** der Anwendung — dort meldet man
sich am Werkzeug an, nicht in der Gemeinschaft. Deshalb ThreadNet.
Die Leitplanke dahinter steht in [`vision/threadnet.md`](../vision/threadnet.md):
*ThreadNet ist das Tool, axion1337.chat die Community.* Das Programm heißt
ThreadNet — auch wenn es jemand für eine andere Instanz nutzt; die Gemeinschaft
darin heißt aXion1337.Chat.
⚠️ **Nicht „geradeziehen".** Wer nur eine der beiden Stellen sieht, hält es für
eine Inkonsistenz. Ist es nicht.
**Attribution:** „ThreadNet — powered by Element" steht seit `v0.4.0` in
*Einstellungen → Hilfe & Info*, direkt unter der Client-Version, verlinkt auf
element.io. Element Web steht unter der AGPL; ein Fork unter eigenem Namen ist
erlaubt, die Nennung ist die faire Form davon. Bewusst **nicht** im Kopiertext der
Versionsangabe — der landet in Fehlerberichten, dort ist die Fork-Herkunft nur
Rauschen.
## Wo was eingestellt ist
| Oberfläche | Ort | Anmerkung |
|---|---|---|
| Element/ThreadNet-Web | `apps/production/custom-configs/element-values.yaml` (gitops), `setting_defaults.custom_themes` | 17 Themes; Änderungen chirurgisch, **nie die YAML neu serialisieren** |
| Web-Icons + PWA | `apps/web/res/vector-icons/`, `apps/web/res/manifest.json` (ThreadNet-Web) | `theme_color` = `#ed4f4c`, die Markenfarbe — nicht Elements `#76CFA6` |
| Desktop-Icons | `apps/desktop/build/` (ThreadNet-Web) | `.png`, `.ico`, `.icns`, Layer-Asset — alle aus derselben Quelle |
| ThreadNet Desktop | `apps/desktop/axion1337/config.json` (ThreadNet-Web) | eigene Kopie derselben Themes — beim Ändern beide mitziehen |
| BookStack | *Settings → Customization*, getrennt für hell und dunkel | liegt in der Datenbank, **nicht im Repo** — schriftlich hier und in `theme/sorbs-palette.md` |
| BookStack (Feinschliff) | `theme/*.css` im Wiki-BookStack-Repo | nur Flächen, Text, Ränder — die sieben Farben oben gehören in die Oberfläche |
| Docusaurus-Wiki | `src/css/custom.css` (homelab/wiki) | bislang nur Akzentfarbe |
| Titelbild Login | `apps/web/res/themes/element/img/backgrounds/alpenglow.jpg` (ThreadNet-Web), gesetzt in `SdkConfig.ts` | siehe unten — Bilddatei kommt nur über einen Build in den Container |
| Anmeldeseite Authentik | Brand-Blueprint in `apps/authentik/authentik-blueprints.yaml` (gitops) | Favicon und Hintergrund werden **von axion1337.chat referenziert**, nicht hochgeladen. **Logo ist noch Authentiks eigenes** → gitops#55 |
### Titelbild
Seit 2026-08-06 zeigt die Login-Seite ein Alpenglühen über einer Bergkette statt
Elements See: **John Towner** ([@heytowner](https://unsplash.com/@heytowner)),
[Unsplash](https://unsplash.com/photos/JgOeRuGD_Y4), *Unsplash License*.
Die Lizenz erlaubt kommerzielle Nutzung und Bearbeitung ohne Genehmigung und
**verlangt keine Namensnennung**. Genannt wird er trotzdem — in *Einstellungen →
Hilfe & Info* unter „Danksagungen". Verboten wäre nur der Weiterverkauf
unbearbeiteter Bilder und das Nachbauen eines konkurrierenden Bilddienstes; beides
trifft uns nicht.
⚠️ **Die Danksagung ist bewusst nicht übersetzt.** Elements Schlüssel
`credits|default_cover_photo` liegt in 32 Sprachdateien, 31 davon nennen deren
Fotografen namentlich. Nur `en`/`de` anzupassen hätte in 29 Sprachen eine **falsche
Attribution** stehen lassen — und diese 29 pflegen wir nicht, sie kommen aus Elements
Übersetzungsdienst. Deshalb steht die Zeile als fester Text im TSX, wie schon die
„powered by Element"-Attribution.
⚠️ **Authentik hängt an dieser Datei.** Der Flow-Hintergrund dort zeigt auf
`https://axion1337.chat/themes/element/img/backgrounds/alpenglow.jpg`. Wer das Bild im
Client umbenennt oder entfernt, macht die Anmeldeseite grau — und merkt es nicht,
weil im Client alles stimmt.
### Warum in Authentik kein PNG-Logo funktioniert
Der erste Versuch setzte `branding_logo` auf `vector-icons/512.png`. Ergebnis: das
Logo rendert in der Anmeldemaske in **Naturgröße**. Authentiks Default ist ein SVG,
das sich seiner Box anpasst — ein PNG tut das nicht, und der Slot begrenzt die Höhe
nicht.
Zurückgesetzt am 2026-08-06 auf Authentiks eigenes Logo. Ein Ersatz braucht eine
**Wortmarke im Querformat, am besten als SVG**; alles Vorhandene ist quadratisch,
auch `threadnet-logo-wortmarke.png` (Bildmarke *über* Schriftzug). Offen in
gitops#55.
⚠️ **Nicht über Authentiks Oberfläche einstellen.** Solange `branding_logo` im
Blueprint steht, gewinnt der Blueprint: eine Auswahl in der UI hält bis zur nächsten
Reconciliation und ist dann wieder weg.
⚠️ **Das BookStack-Schema lebt nur in der Datenbank.** Bei einem Volume-Verlust
ist es weg — deshalb steht es oben in dieser Tabelle. Wiederherstellen heißt:
sieben Felder in der Oberfläche neu eintragen.
Es steht bewusst an **zwei** Stellen schriftlich, und die Rollen sind verschieden:
`theme/sorbs-palette.md` im BookStack-Repo ist die betriebsnahe Kopie mit den
DB-Schlüsseln, liegt aber in der Gruppe `homelab` — die hat **keine Mirrors** und
ist von außerhalb des Labs nicht lesbar. Diese Datei hier ist die gespiegelte
und damit maßgebliche Fassung. Wer die Farben ändert, zieht beide mit; im
Zweifel gilt, was in der laufenden Instanz eingestellt ist.
## Offen
Ob die Terrakotta-Richtung das Stammschema ablösen oder eine Alternative neben
Gruvbox bleiben soll, ist nicht entschieden — das gehört in die Rebranding-Runde
(→ [`vision/threadnet.md`](../vision/threadnet.md), ThreadNet-Web#10).
+133
View File
@@ -0,0 +1,133 @@
---
type: wiki-page
area: architecture
related: []
---
# Lab-Netzwerk (Heimnetz: Fritzbox + UDM Pro)
Themen rund um das Homelab-Netz selbst — Router-Kaskade, VLANs, VPN-Zugänge.
Hosts im Lab: Overmind (git.lab, [hosts/overmind.md](../admin/overmind.md)),
der Mac. Kaskade: **Fritzbox (WAN) → UDM Pro**, kein Doppel-NAT, statische
Route in der Fritzbox für das Lab-VLAN.
> ✅ **Das VPN-Thema ist abgeschlossen und validiert** (sorb, 2026-08-02).
> Beide Zugänge laufen und sind abgenommen, ADR-0004 steht auf *akzeptiert*
> (Testreihe 17 in [#12](https://git.lab/axion1337.chat/management/-/issues/12)).
> Es gibt dazu **keine offenen Issues mehr** — auch die Restpunkte #11
> (MacBook-Profil) und #16 (LABNET-04, Feinschliff an den UniFi-Regeln) sind
> geschlossen. Alles Folgende ist **Bestand und Historie**, keine offene Arbeit.
**Zwei WireGuard-Zugänge (Stand 2026-08-01, beide gelöst/abgenommen):**
| Zugang | Server | Port | Tunnelnetz | Zweck |
|---|---|---|---|---|
| Roadwarrior „Thore" | UDM | 51840 | 10.58.74.0/24 | Handy/MacBook ins Lab (LABNET-01) |
| Site-to-Site „Matrix" | UDM | 51841 | 10.58.75.0/24 | Hetzner-Netz 10.0.0.0/24 ↔ Lab (LABNET-02, [ADR-0004](../../adr/0004-site-to-site-vpn-hetzner-lab.md)) |
### Verhältnis zu `homelab/docs`
Die Tabelle oben steht **absichtlich doppelt**. Maßgeblich für die
Soll-Konfiguration ist
[homelab/docs → MorninglightMountain](https://git.lab/homelab/docs/-/blob/main/netz/morninglightmountain.md)
(dort auch Portfreigaben, Firewall-Zonen, Diagnose-Merksätze) — dieses Repo
führt die **Historie**: was wann warum geändert wurde und mit welchem Issue.
Der Grund für die Doppelung ist der Mirror-Geltungsbereich aus der
[CLAUDE.md](../../../AGENTS.md): Die Gruppe `homelab` hat bewusst **keine Mirrors** und
ist von außerhalb des Labs nicht lesbar. Wer ohne Tunnel nachsehen muss, welcher
Tunnel überhaupt auf welchem Port liegt, findet es nur hier. Deshalb hält dieses
Dokument einen Kurzüberblick vor — Ports, Tunnelnetze, Zweck — und nichts
darüber hinaus. **Bei Widerspruch gilt `homelab/docs`.**
---
## LABNET-01 — WireGuard-Roadwarrior ins Lab kaputt (seit einigen Monaten)
**Status:** GELÖST 2026-08-01 ~15:20 — `git.lab` lädt vom Handy über 5G/VPN. ✅
Damit ist die Cutover-Voraussetzung für gitops#48 erfüllt.
**Drei gestapelte Ursachen (jede verdeckte die nächste):**
1. **Privater Endpunkt** in jeder UDM-generierten Client-Config (UDM kennt hinter
der Fritzbox ihre öffentliche IP nicht) → Fix: Endpunkt `178.25.213.70`;
dauerhaft gelöst über UniFi-Option **„Alternate Address for Clients"**.
2. **FritzOS reserviert UDP 51820 für seinen eigenen WireGuard-Stack** — die
Portfreigabe 51820→UDM lief ins Leere (erklärt die „invalid response"-Stürme
im Juli: zwei WG-Stacks auf einem Port) → Fix: UDM-WG auf **51840**.
3. **Docker-Routen-Kollision auf Overmind**: Dokploys Bridge-Netze belegen zehn
/20-Blöcke in 192.168.0.0/16; `192.168.0.0/20` verschluckte das VPN-Subnetz
192.168.5.0/24 → Antworten an VPN-Clients endeten in der Bridge (SYN kam an,
SYN-ACK verschwand — exakt der Chrome-Connection-Timeout, während Ping/DNS/
fremde Hosts funktionierten) → Fix: **VPN-Subnetz auf 10.58.74.0/24** (Docker
fasst 10.x nie an).
**Restarbeiten:** MacBook-WG-Profil → [Issue #11](https://git.lab/axion1337.chat/management/-/issues/11). ⚠️ Latente Wiederholungsgefahr
notiert: Overminds Docker-Pool deckt auch `192.168.176.0/20` ab = kollidiert mit
dem Fritzbox-Netz 192.168.178.x — aktuell folgenlos, aber bei künftigen Subnetz-
Entscheidungen 192.168.x auf Overmind grundsätzlich meiden (oder Docker
default-address-pools begrenzen).
**Bestätigte Ursachenkette (Diagnose-Session 2026-08-01):**
1. Handy-Profil „@home" hatte seit 07.07. die **private** UDM-WAN-IP
(192.168.178.20) als Endpunkt — die UDM kennt hinter der Fritzbox ihre
öffentliche IP nicht und schreibt sie in jede generierte Config
(⚠️ gilt für ALLE künftig exportierten Profile: Endpunkt manuell auf
178.25.213.70 ändern!).
2. Nach Endpunkt-Fix weiter tot: **FritzOS reserviert UDP 51820 für seinen
EIGENEN WireGuard-Stack** — die alte Portfreigabe 51820→UDM lief ins Leere
(erklärt auch die „invalid response"-Stürme im Juli: zwei WG-Stacks auf
einem Port). Fix: UDM-WG auf **51840** umgezogen + Freigabe angepasst.
3. Server + Schlüssel waren nie das Problem (WLAN-Handshake bewies beides).
Danach nur noch der ursprüngliche Blocker-Vermerk:
blockierte gitops#48 (Erreichbarkeits-Entscheidung „WireGuard statt exponieren")
sorb hatte einen funktionierenden VPN-Zugang fürs Handy ins Lab; seit einigen
Monaten „funktioniert das nicht mehr sauber" (Symptome noch zu präzisieren:
Handshake? Routing nur teilweise? DNS?). Setup-Rahmen laut sorb (2026-08-01):
UDM Pro hinter Fritzbox, ohne doppeltes NAT, statische Route in der Fritzbox
für das VLAN.
**Diagnose-Plan von VOR der Lösung** — ⚠️ abgearbeitet und überholt, steht hier
nur als Beleg, wie die Ursachen eingekreist wurden. Nichts davon ist zu tun:
1. Symptom präzisieren: Handshake kommt zustande? (`wg show` auf der UDM /
Client-Log) — trennt Portweiterleitungs- von Routing-Problemen
2. Fritzbox: Portfreigabe UDP (WireGuard-Port) → UDM noch vorhanden/korrekt?
(FritzOS-Updates werfen gern Freigaben/Exposed-Host-Einstellungen um)
3. ~~DS-Lite~~ **ausgeschlossen** (sorb 2026-08-01: Dualstack + feste IPs) —
damit auch kein DynDNS-Drift möglich. Verdacht konzentriert sich auf:
FritzOS-Update warf die UDP-Portfreigabe um, UniFi-OS-Update veränderte
WG-Server/Firewall, oder die statische Route griff nach Änderung nicht mehr.
4. (entfällt — feste IP)
5. UDM-Seite: WireGuard-Server-Config/Firewall-Regeln nach UniFi-OS-Updates
prüfen; statische Route Fritzbox → VLAN gegenchecken
6. Erst wenn 15 sauber: Client-Profil fürs Handy neu ausstellen, git.lab-DNS
(Lab-Resolver) in die AllowedIPs/DNS-Konfig aufnehmen — Erfolgsbeweis =
Issue-Board vom Handy über VPN erreichbar
**Verwandt:** gitops#48 (Cutover erst nach Lösung), perspektivisch ersetzt ein
funktionierender Roadwarrior auch Ad-hoc-Wünsche wie „GitLab exponieren".
## Zugehörige Issues — alle geschlossen
Seit dem Framework-Umbau (2026-08-01) leben offene Punkte als Issues im
[management-Projekt](https://git.lab/axion1337.chat/management/-/issues); die IDs bleiben in den Issue-Titeln erhalten.
Dieses File hält nur noch Bestand und Historie.
Zum Netz/VPN ist **nichts mehr offen** (Stand 2026-08-02):
| Issue | Thema | Stand |
|---|---|---|
| [#11](https://git.lab/axion1337.chat/management/-/issues/11) | LABNET-01-Rest — MacBook-WireGuard-Profil | geschlossen |
| [#12](https://git.lab/axion1337.chat/management/-/issues/12) | LABNET-02 — Site-to-Site-VPN (Design: [ADR-0004](../../adr/0004-site-to-site-vpn-hetzner-lab.md)) | geschlossen, Testreihe 17 protokolliert |
| [#16](https://git.lab/axion1337.chat/management/-/issues/16) | LABNET-04 — Feinschliff UniFi-Regeln | geschlossen |
Zwei Punkte tragen zwar LABNET im Text, gehören aber **nicht** zum VPN-Thema und
bleiben offen: [#13](https://git.lab/axion1337.chat/management/-/issues/13)
(LABNET-03, Rückbau der Gitea-Ausnahme für Übergabe-Issues — durch den Tunnel
erst möglich geworden, aber eine Repo-Frage) und
[#15](https://git.lab/axion1337.chat/management/-/issues/15) (CFGMON-15,
Widerruf der Einmal-Tokens aus der LABNET-02-Nacht — Credential-Hygiene, und der
Widerruf kann still einen Push-Mirror brechen, solange dessen hinterlegtes Token
unbekannt ist).
@@ -0,0 +1,64 @@
---
type: wiki-page
area: architecture
related:
- "docs/adr/0001-gitlab-kanonisch-push-mirror.md"
- "docs/adr/0002-issues-und-management-ins-lab.md"
- "docs/adr/0004-site-to-site-vpn-hetzner-lab.md"
- "docs/adr/0006-wikis-konsolidieren-docusaurus.md"
---
# Mirror-Topologie: Das Lab ist die Quelle der Wahrheit
Begründungsprosa übernommen aus der alten `CLAUDE.md` (Abschnitt
„Projektrealitäten", Wortlaut in der git-Historie vor der
neckbeard-Migration); die verbindlichen Regeln stehen in `AGENTS.md` §6
und den verlinkten ADRs. Erhalten per Feldtest-Befund F-013: Diese
Begründung samt Gegenargument und Rettungspfad ist der Wert — sie
erklärt, warum die Topologie so aussieht und so bleiben soll.
- Kanonische Repos liegen auf `git.lab/axion1337.chat/*` (nur im
Lab/VPN auflösbar). Gitea/rohana wird per **Push-Mirror** beliefert
und bleibt Flux-Source, Container-/npm-Registry und Release-Download
([ADR-0001](../../adr/0001-gitlab-kanonisch-push-mirror.md)).
- **Warum überhaupt zwei Orte — und warum das kein Altbestand ist:**
Auf git.lab liegen die *Baupläne*, auf Gitea eine Kopie, die der
Cluster **ohne verfügbares Lab** erreicht. Der Hetzner-Cluster muss
sich bauen und neu ausrollen lassen, wenn das Homelab aus ist, im
Umbau steckt oder niemand zu Hause ist — er darf deshalb nicht von
einem Host abhängen, der nur im Lab antwortet.
⚠️ **Die Flux-Quelle nicht „geradeziehen"** auf git.lab: Das sähe
aufgeräumter aus und würde die Verfügbarkeit der Produktion an das
Lab koppeln — genau das, was die Trennung verhindert.
- **Gespiegelt wird nur die Gruppe `axion1337.chat`** (die Produkt-Repos
und `management`). Die Gruppe **`homelab`** (`docs`, `wiki`,
`wiki-bookstack`) hat bewusst **keine Mirrors**: Sie beschreibt und
konfiguriert ausschließlich Lab-Infrastruktur, und seit dem
Site-to-Site-VPN ([ADR-0004](../../adr/0004-site-to-site-vpn-hetzner-lab.md))
erreichen auch Host-Sessions git.lab direkt — Tunnel einschalten
genügt. Betriebslehren, die von außen lesbar sein müssen, gehören
deshalb in die **AARs** unter `docs/aar/` (dieses Repo ist
gespiegelt), nicht nur in die READMEs der Lab-Repos.
- Landet doch ein Commit auf Gitea (z. B. aus einer Host-Session ohne
Lab-Route): **Kanonisierungs-Verfahren** in
[deploy-uebergabe](../deployment/deploy-uebergabe.md) — `.patch` von
Gitea ziehen, `git am` (erhält Autorschaft), Push über git.lab.
- ⚠️ gitops-Issue-Nummern haben sich beim Gitea-Umzug verschoben (Gitea
zählte PRs mit; z. B. Gitea#48 → GitLab#46) — alte „gitops#N"-Verweise
meinen die Gitea-Nummer; verbindlich ist der Migrations-Fußtext im
Issue ([ADR-0002](../../adr/0002-issues-und-management-ins-lab.md)).
- **Ausnahme** (bewusst entschieden, nur noch eine): der
TURN-Rotations-CronJob schreibt weiter nach Gitea, weil er im Cluster
läuft und git.lab nicht erreicht. **Die Rotation nicht von Hand
nachziehen und den PR nie auf Gitea mergen** — das erledigt seit
2026-08-02 der geplante CI-Job `canonize_rotation` im gitops-Repo
täglich von git.lab aus. Scheitert er, bleibt die Pipeline rot; diese
rote Pipeline **ist** der Alarm, einen zusätzlichen Termin gibt es
bewusst nicht.
- **Dokumentation** ([ADR-0006](../../adr/0006-wikis-konsolidieren-docusaurus.md)):
Das gitops-Wiki liegt seit 2026-08-02 auf git.lab (*Wiki*-Reiter im
Projekt); ⚠️ der `wiki`-**Branch** im gitops-Repo ist ein überholter
Mai-Abzug von `docs/` und nicht die gepflegte Fassung. Alle Quellen
zusammen erscheinen unter **axionwiki.lab**
([`homelab/wiki`](https://git.lab/homelab/wiki), Docusaurus) —
Inhalte werden beim Bau geholt, **Änderungen gehören ins Quell-Repo**.
+148
View File
@@ -0,0 +1,148 @@
---
type: wiki-page
area: architecture
related: []
---
# DNS-Zone `axion1337.de` und Mail-Policy
Übergreifend, weil die Zone alle Hosts abdeckt und die Mail-Policy sich nicht pro
Host trennen lässt.
| | |
|---|---|
| **Registrar / DNS** | IONOS (`ns1098.ui-dns.biz`, `ns1022.ui-dns.com`, `ns1070.ui-dns.org`, `ns1059.ui-dns.de`) |
| **Apex** | `217.160.0.140` / `2001:8d8:100f:f000::2e9` — IONOS-Hosting, nicht eigene Infrastruktur |
| **Mail** | IONOS (`mx00.ionos.de`, `mx01.ionos.de`) |
| **Stand** | 2026-08-06 (Mail-Records gemessen) |
**Ist-Stand der Mail-Härtung** (gemessen 2026-08-06 über DoH, um den Lab-Resolver
zu umgehen):
| Name | `www` | MX | SPF | `_dmarc` | Bewertung |
|---|---|---|---|---|---|
| `rohana` | löst auf ❌ | gelöscht | **gelöscht** ⚠️ | fehlt | ⚠️ schwächer als vorher |
| `selendis` | weg ✅ | IONOS ❌ | `~all` ❌ | fehlt | unangetastet |
| `matrix` | löst auf ❌ | IONOS ❌ | `~all` ❌ | fehlt | offen |
| `game` | löst auf ❌ | — | — | fehlt | teilweise |
| **Apex** | legitim ✅ | IONOS (genutzt) | `~all` | **`p=none`** ⚠️ | siehe ZONE-02 |
Kein einziger Name trägt bisher `_dmarc`, alle erben damit `p=none` vom Apex.
> **Die Aufstellung ist nicht garantiert vollständig.** Zonentransfer ist verweigert,
> DNS erlaubt kein Enumerieren. Die Records unten stammen aus gezielten Abfragen und
> der IONOS-Oberfläche. Für eine vollständige Prüfung entweder die ungefilterte
> IONOS-Liste durchgehen oder die Certificate-Transparency-Logs abfragen (zeigt alle
> Namen, für die je ein Cert ausgestellt wurde).
## Bekannter Bestand
| Name | A | AAAA | Ziel |
|---|---|---|---|
| `axion1337.de` | `217.160.0.140` | `2001:8d8:100f:f000::2e9` | IONOS-Hosting |
| `www` | `217.160.0.140` | dito | IONOS-Hosting — hier ist `www` **legitim** |
| `rohana` | `188.245.193.243` | `2a01:4f8:c17:93eb::1` | CFGMON, Gitea |
| `selendis` | `188.245.193.243` | `2a01:4f8:c17:93eb::1` | CFGMON, Grafana |
| `game` | `157.90.155.206` | — | Pterodactyl |
| `matrix` | `49.13.132.245` | — | Matrix-Homeserver |
| `ftp` | `217.160.233.227` | `2001:8d8:1000:30f5:…` | IONOS-Default |
| `www.rohana`, `www.selendis`, `www.game`, `www.matrix` | wie ohne `www` | teils | überflüssig, siehe ZONE-01 |
Mail-Records existieren auf `selendis` und `matrix` (MX ×2, SPF, DKIM-CNAMEs,
`autodiscover`), auf `rohana` und `game` nicht.
## Was die Mail-Records eigentlich tun
Damit die Rezepte in [ZONE-01](https://git.lab/axion1337.chat/management/-/issues/5)
nicht als Zahlensalat dastehen: Vier Mechanismen, die zusammenspielen. **Keiner
schützt allein.**
### Das Grundproblem
Der Absender einer Mail (`From:`) ist frei wählbar — SMTP prüft ihn nicht. Jeder
kann `rechnung@rohana.axion1337.de` in den Umschlag schreiben. Die folgenden
Records sind die Möglichkeit, dem widersprechen, **bevor** jemand darauf hereinfällt.
### SPF — „diese Server dürfen für mich senden"
TXT-Record am Namen selbst. Listet die berechtigten Absender-IPs.
Entscheidend ist das **Ende** des Eintrags:
| Endung | Bedeutung | Wirkung beim Empfänger |
|---|---|---|
| `~all` | Softfail | „war nicht auf der Liste" → wird meist **trotzdem zugestellt**, evtl. markiert |
| `-all` | Hardfail | „war nicht auf der Liste" → **ablehnen** |
`v=spf1 -all` ohne jeden Server davor heißt: *Für diesen Namen sendet niemand.*
Genau die richtige Aussage für `rohana`, `selendis`, `matrix` — die verschicken keine
Mail (für `matrix` verifiziert in MATRIX-01: weder Synapse noch MAS senden).
⚠️ **Es darf nur EIN SPF-Record je Name existieren.** Ein zweiter erzeugt
`PermError`, und dann prüfen viele Empfänger **gar nicht mehr** — die Härtung
schlägt ins Gegenteil um. Deshalb: bestehenden TXT **editieren**, nie einen zweiten
anlegen.
### DKIM — „diese Mail wurde unterwegs nicht verändert"
Signatur mit einem privaten Schlüssel, öffentlicher Teil als CNAME/TXT im DNS
(`s1-ionos._domainkey…`). Beweist Unversehrtheit und Herkunft.
Für Namen, die nicht senden, sind die DKIM-Einträge schlicht **Ballast** — sie
signieren nichts. Sie können weg.
### DMARC — „und das tust du, wenn SPF oder DKIM nicht passen"
TXT unter `_dmarc.<name>`. SPF und DKIM stellen nur **fest**; DMARC sagt, welche
**Konsequenz** das hat:
| Policy | Wirkung |
|---|---|
| `p=none` | nur beobachten — **kein Schutz**, Mail wird zugestellt |
| `p=quarantine` | in den Spam-Ordner |
| `p=reject` | ablehnen |
⚠️ **DMARC wird vererbt.** Fehlt `_dmarc.rohana`, gilt die Policy des
organisatorischen Namens `axion1337.de`. Die steht heute auf **`p=none`**
([ZONE-02](https://git.lab/axion1337.chat/management/-/issues/6)) — **damit erben
alle Subdomains „kein Schutz"**, egal wie sauber ihr SPF ist.
Das ist der wichtigste Hebel der ganzen Zone: **Der Apex wirkt auf alle Namen
gleichzeitig.** Mit `sp=` lässt sich für Subdomains sogar eine strengere Policy
setzen als für den Apex selbst.
### Null-MX — „hier nimmt niemand Mail an" (RFC 7505)
Ein MX-Record mit dem Ziel `.` (Punkt) und Priorität 0.
Der Grund, warum **Löschen nicht reicht**: Findet ein Absender **keinen** MX,
weicht er per RFC 5321 auf den **A/AAAA-Record** aus und versucht, direkt an den
Webserver zuzustellen. Der Name sieht dann nach „nimmt vielleicht Mail an" aus.
Null-MX sagt stattdessen ausdrücklich *nein* — Absender brechen sofort ab.
### Warum die Kombination
| Record | Beantwortet die Frage |
|---|---|
| **Null-MX** | Nimmt dieser Name Mail **an**? → nein |
| **SPF `-all`** | Darf jemand für diesen Namen **senden**? → niemand |
| **DMARC `p=reject`** | Was tun, wenn doch jemand behauptet, es zu dürfen? → ablehnen |
Erst zusammen ergeben sie eine Aussage, auf die sich ein Empfänger verlassen kann.
Einzeln bleibt jeweils eine Lücke — und **ersatzloses Löschen** hinterlässt die
größte: keine Aussage ist schwächer als eine schlechte Aussage.
**Real eingetreten:** Bei `rohana` sind MX und SPF gelöscht, die Ersatz-Records
fehlen (gemessen 2026-08-06). Vorher gab es wenigstens ein Softfail-SPF, jetzt gar
keine Aussage mehr — dazu die geerbte `p=none` vom Apex. Der Halbfertig-Zustand ist
schwächer als der Ausgangszustand.
## Offene Punkte → git.lab-Issues
Seit dem Framework-Umbau (2026-08-01) leben offene Punkte als Issues im
[management-Projekt](https://git.lab/axion1337.chat/management/-/issues); die IDs bleiben in den Issue-Titeln erhalten.
Dieses File hält nur noch Bestand und Historie.
- [ZONE-01 — IONOS-Default-Records bereinigen (Rezepte im Issue; rohana/selendis in Arbeit)](https://git.lab/axion1337.chat/management/-/issues/5)
- [ZONE-02 — Apex-DMARC ist `p=none` und schützt nichts](https://git.lab/axion1337.chat/management/-/issues/6)