homelab-architecture: add Mermaid topology / auth / MCP / data plane diagrams

This commit is contained in:
2026-05-21 00:35:24 +02:00
parent 7ef5aea9db
commit 9f6d0dd195
+132
View File
@@ -378,3 +378,135 @@ must target *exactly these silent-failure classes*.
`/mnt/pve/unas` (catches a regression of the tier-1 rule). `/mnt/pve/unas` (catches a regression of the tier-1 rule).
4. Container unhealthy/restart-looping > 5 m (the gluetun pattern). 4. Container unhealthy/restart-looping > 5 m (the gluetun pattern).
5. local-zfs `rpool` or NFS pool > 85 %; 6. TLS cert < 14 d. 5. local-zfs `rpool` or NFS pool > 85 %; 6. TLS cert < 14 d.
## Topology — at a glance
### Physical / CT layout
```mermaid
flowchart TB
subgraph Host["Proxmox host · 192.168.1.20 · Intel Core Ultra 7 155H · 64 GiB"]
direction TB
haos["VM 100 · haos<br/>(.60)<br/>Home Assistant"]
shepard["CT 101 · shepard<br/>(.49)<br/>Shepard product stack"]
dns["CT 102 · dns<br/>(.2)<br/>AdGuard Home"]
backrest["CT 103 · backrest<br/>(.3)<br/>Backrest / restic"]
docker104["<b>CT 104 · docker</b><br/>(.40) · 16c/48G/200G<br/>~65 containers · Intel Arc passthrough"]
nc["CT 105 · nextcloud<br/>(.41)<br/>Nextcloud AIO (CIFS to UNAS)"]
zoraxy["CT 108 · zoraxy<br/>(.4)<br/>reverse proxy + ACME"]
obs(["CT 109 · observe<br/>(.6) · <i>planned</i><br/>Prom / Graf / Arcane / Homarr / Tinyauth"])
id["CT 110 · id<br/>(.5)<br/>Pocket-ID (moved here 2026-05-20)"]
dev["CT 111 · dev<br/>(.42) · 12c/32G/60G<br/>Coder + Gitea + workspaces · Intel Arc"]
db(["CT 113 · db<br/>(.?) · <i>planned</i><br/>shared Postgres + pgbouncer"])
end
UNAS[("UNAS<br/>192.168.1.31<br/>NFSv3 + CIFS")]
UDM[["UDM-SE · 192.168.1.1<br/>UniFi gateway · DNS → AdGuard"]]
Inet([Internet · ACME challenges · jottacloud · LiteLLM upstreams])
UDM <--> Host
UDM <--> Inet
UNAS <--> shepard
UNAS <--> backrest
UNAS <--> docker104
UNAS <--> nc
UNAS <--> dev
classDef planned stroke-dasharray:5 5,fill:#222,stroke:#aaa,color:#aaa
class obs,db planned
```
### Auth plane — Pocket-ID is the universal IdP
Every web service that supports OIDC federates against Pocket-ID. Coder/Gitea/Vaultwarden access through Zoraxy; Zoraxy + Tinyauth fronts the non-OIDC-native ones.
```mermaid
flowchart LR
user(["fkrebs · browser / VS Code / Claude"]) --> zx[Zoraxy<br/>CT 108]
zx --> coder[Coder · CT 111]
zx --> gitea[Gitea · CT 111]
zx --> nc2[Nextcloud · CT 105]
zx --> immich[Immich · CT 104]
zx --> lobe[LobeChat · CT 104]
zx --> n8n[n8n · CT 104]
zx --> mcp[MCP gateway · CT 104]
zx --> vw[Vaultwarden · CT 104]
coder --> pid[(Pocket-ID<br/>CT 110)]
gitea --> pid
nc2 --> pid
immich --> pid
lobe --> pid
n8n --> pid
mcp --> pid
vw -.->|via Tinyauth<br/>when CT 109 lands| pid
classDef pending stroke-dasharray:4 4,color:#888
class vw pending
```
### MCP plane — gateway control, child workers
The MCP gateway on CT 104 is the OIDC-gated front; ~23 child MCP servers run on the same docker network (`ai-internal`). When CT 109 "observe" is built, the gateway moves to CT 109 and reaches CT 104's docker daemon via a socket-proxy; the children stay put.
```mermaid
flowchart LR
client[["Claude Code / Cursor / LobeChat"]]
gw["MCP gateway<br/>(CT 104 → CT 109 when 109 lands)<br/>mcp.nuclide.systems"]
client -- Bearer / OIDC --> gw
subgraph "CT 104 · ai-internal docker net"
direction TB
coderm[coder-mcp]
immm[mcp-immich]
n8nm[mcp-n8n]
fetch[mcp-fetch]
time[mcp-time]
cw[mcp-crawl4ai]
seq[mcp-sequential-thinking]
ham[home-assistant-mcp]
kr[kroki-mcp]
others[...18 more]
end
gw --> coderm
gw --> immm
gw --> n8nm
gw --> fetch
gw --> time
gw --> cw
gw --> seq
gw --> ham
gw --> kr
gw --> others
coderm -.spawns/controls.-> CoderWS[(Coder workspaces<br/>CT 111)]
ham -.bridges to.-> HAOS[(Home Assistant<br/>VM 100)]
```
### Data plane — what lives where
```mermaid
flowchart TB
subgraph Tier1["Tier-1 / latency-sensitive · local NVMe"]
pid_d[Pocket-ID sqlite · CT 110]
immich_pg[Immich Postgres · CT 104]
shared_pg[shared-postgres · CT 104]
coder_pg[coder-db · CT 111]
gitea_pg[gitea-db · CT 111]
garage["Garage S3 · CT 104<br/>(moved off NFS 2026-05-19)"]
n8n_local["n8n data · CT 104<br/>(reverted from NFS 2026-05-19)"]
end
subgraph Bulk["Bulk · UNAS NFSv3"]
media["Immich media, Paperless docs,<br/>arr-stack media, audiobooks"]
coder_homes[Coder workspace homes · /mnt/pve/unas/services/coder]
gitea_data[Gitea repos · /mnt/pve/unas/services/gitea]
vw_data["Vaultwarden data<br/>(tier-1 leak — plan to move local)"]
end
subgraph BulkCIFS["Bulk · UNAS CIFS (Nextcloud only)"]
nc_data[Nextcloud user files]
end
subgraph Backup["Off-host backup"]
jottacloud[(jottacloud<br/>via Backrest)]
end
Tier1 -. WAL-G .-> garage
Bulk -. only media/data-dir .-> jottacloud
classDef gap fill:#5a2a2a,stroke:#c44,color:#fcc
class vw_data,jottacloud gap
```
The red blocks above are gaps: Vaultwarden is on NFS when it shouldn't be; off-host backup currently covers only one UNAS path, not service data. See `stacks/storage.md` for the verified state and the cleanup TODO list.