Det har ar diagrammet du bad om fran borjan. Alla 14 Caddy-subdomaner som egna noder, alla 23 Tailscale-enheter (aven offline), varje docker-container per host med image+port+status (47 containers totalt: brain 6, ai-rag 5, lyxlimo-webb 2, underbar-webb 6, monitor 5, townhouse-gitea 18, demopc 5+), alla extra brain /opt-mappar (townhouse-generator, headplane, mcp-hub, traefik-legacy), brain-lyxlimo-bot RESTARTING-status, alla 6 externa cloud-APIs.
Live-data hamtad via SSH till brain, monitor, townhouse-gitea (townhouse-gemma4-2-cred), ai-rag, lyxlimo-webb, underbar-webb. Tailscale-listan visar 23 enheter totalt - 7 aktiva tagged servers + 16 personliga klienter (varav manga offline). monitor-cax11 har en EGEN Caddy (cloudflare-build) som routar ops.ibo.se - inte brain Caddy som jag forst trodde. townhouse-gitea har 18 containers inklusive 2 swarm tasks fran Dokploy + 3 file-drop containers (pingvin + filebrowser + caddy).
Forsta versionen - se KOMPLETT for groundtruth.
4 sequence-flow: Lyxlimo booking, Underbar review, CMS-deploy, Patch-approval.
Push-monitoring + execution + Stats-pipeline + Veo+YouTube+Pmax.
37 workflows i 6 kategorier + 10 ops-sub-pages.
41 tjanster i 5 sektioner enligt /srv/dashboard/index.html SECTIONS-array.
---
config:
theme: dark
layout: elk
title: Townhouse Infra — Network Topology & Hosts (2026-05-07)
---
flowchart LR
%% ============ EXTERNAL ============
subgraph EXT["INTERNET / EXTERNAL"]
direction TB
USR["End-Users<br/>browsers, mobile"]
CF["Cloudflare<br/>DNS + Proxy + WAF<br/>orange-cloud for public<br/>DNS-only for admin"]
GOOG["Google APIs<br/>Ads, GA4, Calendar,<br/>Gmail, Sheets, Veo, Gemini"]
DISCORD["Discord<br/>Webhooks for alerts"]
end
%% ============ HETZNER ============
subgraph HZ["HETZNER CLOUD - hel1-dc2 - 5 VPS - 32 EUR/mo"]
direction TB
subgraph BRAIN["BRAIN - CX33<br/>pub 204.168.246.143<br/>ts 100.91.241.68"]
BR_CADDY["Caddy host-installed<br/>:80 :443<br/>TLS-termination ALL subdomains<br/>Let's Encrypt + DNS-01"]
BR_N8N["n8n :5678<br/>27 workflows, 6 active<br/>Postgres + Redis + Workers"]
BR_PG["Postgres<br/>monitoring DB + lyxlimo_stats<br/>+ lyxlimo_bookings"]
BR_REDIS["Redis cache"]
BR_EXEC["brain-approve-exec<br/>:9991 docker container<br/>SSH-out to 7 hosts"]
BR_STATS["Flask stats.imagesbyolofsson.se<br/>systemd timer 06:00 daily"]
BR_VEO["/srv/lyxlimo-veo<br/>veo_client.py + ffmpeg"]
end
subgraph AIRAG["AI-RAG - CX33<br/>pub 89.167.42.116<br/>ts 100.120.67.52"]
AR_API["FastAPI :8000<br/>Acrylic-Nexus RAG"]
AR_CHROMA["ChromaDB<br/>vector store"]
AR_MCP["townhouse-mcp :1337<br/>aggregator"]
AR_DIUN["Diun cron 6,18<br/>21 image watchers"]
AR_VER["mon-service-versions.py<br/>cron 30 6,18"]
end
subgraph LYXWEBB["LYXLIMO-WEBB - CX23<br/>pub 204.168.245.109<br/>ts 100.75.14.44<br/>label underbar-4gb sic"]
LX_NGINX["nginx :80 :443<br/>lyxlimo.se + www<br/>+ lyxlimo.imagesbyolofsson.se"]
LX_HTML["/srv/lyxlimo/www/index.html<br/>direct-edit no Astro build<br/>5-step booking form"]
end
subgraph UNDERBARWEBB["UNDERBAR-WEBB - CX23<br/>pub 204.168.249.189<br/>NOT on Tailscale"]
UB_NGINX["underbar-nginx container<br/>:80 :443<br/>3 server blocks<br/>bind-mount /srv/underbar/www-stage"]
UB_CONTENT["underbar-content-api<br/>:8002 FastAPI<br/>products + images + notices"]
UB_REVIEWS["underbar-reviews-api<br/>:8001 FastAPI<br/>+ Gemini auto-validation"]
UB_PG_C["underbar-content-postgres"]
UB_PG_R["underbar-reviews-postgres"]
end
subgraph MONITOR["MONITOR-CAX11 - ARM<br/>pub 65.21.252.57<br/>ts 100.123.194.33<br/>hostname montior-cax11 sic"]
MO_BESZEL["Beszel hub :8090<br/>6 agents"]
MO_GLANCES["Glances :61208<br/>PyPI v3.4.0.5"]
MO_KUMA["Uptime Kuma"]
MO_HEALTH["Caddy health-staging<br/>+ approve-SPA"]
end
end
%% ============ LAPTOPS ============
subgraph LAPS["LOCAL LAPTOPS - on Tailscale"]
direction TB
subgraph TLLM["TOWNHOUSE-LLM - i7-1265U<br/>ts 100.71.126.116<br/>laptop"]
OLLAMA["Ollama :11434<br/>Qwen3-4B Q4_K_M<br/>Gemma-4-E4B Q4_K_M<br/>OpenAI-compat /v1/"]
end
subgraph TGITEA["TOWNHOUSE-GITEA - Core Ultra 5<br/>ts 100.83.211.41<br/>laptop"]
GITEA["Gitea :3000<br/>1.22.6<br/>Actions runner + Packages"]
ONEDEV["OneDev :6610<br/>5 repos in Townhouse hierarchy"]
DOKPLOY["Dokploy :3001<br/>swarm orchestrator"]
SB["SilverBullet :3030<br/>3 areas Linus/Claude/Gemini"]
AUTH["Authelia"]
FILEDROP["file-drop"]
CMS_SWARM["underbar-underbaradminui-j6sver<br/>swarm task nixpacks staticfile"]
end
DEMOPC["DEMOPC-TOWNHOUSE<br/>ts 100.75.223.96<br/>Windows laptop<br/>Ollama Desktop shared"]
end
%% ============ EDGE / VPN ============
subgraph EDGE["EDGE / VPN INFRA"]
OPNS["OPNsense<br/>ts 100.127.190.86<br/>FreeBSD<br/>exit-node + Unbound DNS<br/>Web UI :4443"]
OPNS_DASH["vps-opnsense-dashboard<br/>ts 100.103.201.116"]
TS_CTRL["Tailscale Coordinator<br/>CGNAT 100.64.0.0/10<br/>tag townhouse + ACL"]
end
%% ============ HARDWARE OFF-LINE ============
Z10["z10PE-D16-WS<br/>OFFLINE 2026-05-06<br/>2 x Xeon E5 v4 + 1TB ECC<br/>17 disks + GTX 1070 Ti<br/>no-POST diag pending"]
%% ============ FLOWS ============
USR -->|HTTPS 443| CF
CF -->|HTTPS to origin| BR_CADDY
CF -->|DNS-only admin paths<br/>via Tailscale ACL| BR_CADDY
BR_CADDY -->|reverse_proxy<br/>lyxlimo.se| LX_NGINX
BR_CADDY -->|reverse_proxy<br/>underbar.site<br/>via VPS-net 10.0.0.5| UB_NGINX
BR_CADDY -->|reverse_proxy<br/>reviews.imagesbyolofsson.se| UB_REVIEWS
BR_CADDY -->|/api proxy<br/>admin.underbar.site| UB_CONTENT
BR_CADDY -->|reverse_proxy<br/>admin.underbar.site default| DOKPLOY
BR_CADDY -->|reverse_proxy<br/>n8n.imagesbyolofsson.se| BR_N8N
BR_CADDY -->|reverse_proxy<br/>onedev.imagesbyolofsson.se| ONEDEV
BR_CADDY -->|reverse_proxy<br/>silverbullet.ibo.se| SB
BR_CADDY -->|reverse_proxy<br/>stats.ibo.se Tailscale-only| BR_STATS
BR_CADDY -->|reverse_proxy<br/>ops.ibo.se Tailscale-only| MO_HEALTH
UB_NGINX -.->|reads bind-mount| UB_CONTENT
UB_REVIEWS -->|Postgres| UB_PG_R
UB_CONTENT -->|Postgres| UB_PG_C
UB_REVIEWS -->|HTTPS| GOOG
LX_NGINX -.->|POST booking| BR_N8N
BR_N8N -->|Postgres| BR_PG
BR_N8N -->|HTTPS| GOOG
BR_N8N -->|webhook| DISCORD
BR_N8N -->|HTTP| BR_EXEC
BR_N8N -->|Ollama API| OLLAMA
BR_EXEC -->|SSH out| AIRAG
BR_EXEC -->|SSH out| LYXWEBB
BR_EXEC -->|SSH out| UNDERBARWEBB
BR_EXEC -->|SSH out| MONITOR
BR_EXEC -->|SSH out| TGITEA
BR_STATS -->|reads| BR_PG
BR_VEO -->|HTTPS| GOOG
DOKPLOY -->|deploys swarm task| CMS_SWARM
DOKPLOY -.->|pulls source| ONEDEV
GITEA -.->|repos mirror eval| ONEDEV
AR_DIUN -->|webhook| BR_N8N
AR_VER -->|webhook| BR_N8N
MO_BESZEL -->|TCP agents| BRAIN
MO_BESZEL -->|TCP agents| AIRAG
MO_BESZEL -->|TCP agents| LYXWEBB
MO_BESZEL -->|TCP agents| UNDERBARWEBB
MO_BESZEL -->|TCP agents| TGITEA
MO_GLANCES -.->|HTTP polls| BRAIN
MO_GLANCES -.->|HTTP polls| AIRAG
DEMOPC -.->|Tailscale<br/>SSH+VS Code| BRAIN
DEMOPC -.->|Tailscale<br/>SSH+VS Code| LYXWEBB
DEMOPC -.->|Tailscale<br/>SSH+VS Code| UNDERBARWEBB
OPNS -.->|exit-node + DNS<br/>CGNAT rebind override| TS_CTRL
TS_CTRL -.->|tag townhouse ACL| BRAIN
TS_CTRL -.->|tag townhouse ACL| AIRAG
TS_CTRL -.->|tag townhouse ACL| LYXWEBB
TS_CTRL -.->|tag townhouse ACL| MONITOR
TS_CTRL -.->|tag townhouse ACL| TLLM
TS_CTRL -.->|tag townhouse ACL| TGITEA
TS_CTRL -.->|tag townhouse ACL| DEMOPC
classDef brainNode fill:#4a148c,stroke:#fff,color:#fff
classDef dataNode fill:#1b5e20,stroke:#fff,color:#fff
classDef webNode fill:#0d47a1,stroke:#fff,color:#fff
classDef adminNode fill:#f57f17,stroke:#000,color:#000
classDef aiNode fill:#b71c1c,stroke:#fff,color:#fff
classDef extNode fill:#37474f,stroke:#fff,color:#fff
classDef offlineNode fill:#424242,stroke:#f00,stroke-width:3px,color:#fff,stroke-dasharray: 5 5
class BR_CADDY,BR_N8N,BR_EXEC,BR_STATS,BR_VEO brainNode
class BR_PG,BR_REDIS,UB_PG_C,UB_PG_R,AR_CHROMA dataNode
class LX_NGINX,LX_HTML,UB_NGINX,UB_CONTENT,UB_REVIEWS webNode
class GITEA,ONEDEV,DOKPLOY,SB,AUTH,FILEDROP,CMS_SWARM,MO_HEALTH,MO_BESZEL,MO_GLANCES,MO_KUMA adminNode
class OLLAMA aiNode
class USR,CF,GOOG,DISCORD,OPNS,OPNS_DASH,TS_CTRL,DEMOPC extNode
class Z10 offlineNode
---
config:
theme: dark
title: Townhouse — Application Flows (Lyxlimo Booking + Underbar Reviews + Deploy)
---
sequenceDiagram
autonumber
actor User as End-User
participant CF as Cloudflare
participant Caddy as Caddy on brain
participant LXN as lyxlimo-webb nginx
participant N8N as n8n on brain
participant PG as brain Postgres
participant Sheet as Google Sheets
participant Cal as Google Calendar
participant Gmail as Gmail
participant Disc as Discord
participant Approver as Approver web SPA
participant UBN as underbar-webb nginx
participant RevAPI as Reviews API 8001
participant Gemini as Google Gemini
participant CMS as admin.underbar.site CMS
participant ContAPI as Content API 8002
participant OneDev as OneDev
participant Dokploy as Dokploy
participant Swarm as docker swarm task
Note over User,Sheet: FLOW A — Lyxlimo booking lyxlimo.se
User->>CF: GET lyxlimo.se 5-step form
CF->>Caddy: HTTPS to origin
Caddy->>LXN: reverse_proxy
LXN-->>User: HTML + GA4 + Maps JS
User->>LXN: POST form fields
LXN->>N8N: POST /webhook/lyxlimo-booking
N8N->>N8N: Normalize + parse message
par Storage and observability
N8N->>PG: INSERT booking
N8N->>Sheet: append row 26 cols
N8N->>Disc: webhook notify
end
N8N-->>User: 202 Accepted thank-you
Note over Approver,Cal: Manual approval gate
N8N->>Approver: generate UUID-token<br/>POST approve.ibo.se URL to Discord
Approver->>N8N: GET /api/approval/:token
Approver->>N8N: POST /api/submit decision
alt approved
N8N->>Cal: createEvent OSA-invite
N8N->>Sheet: write calendar_event_link
N8N->>Gmail: send confirmation
else rejected
N8N->>Sheet: status=rejected
end
Note over User,Gemini: FLOW B — Underbar review submit underbar.site
User->>CF: GET underbar.site/leksaker.html
CF->>Caddy: HTTPS
Caddy->>UBN: via VPS-net 10.0.0.5
UBN-->>User: HTML + product-modal.js v=20260505-1
User->>UBN: open product modal click
UBN-->>User: render reviews from localStorage
User->>RevAPI: OPTIONS preflight
RevAPI-->>User: CORS headers underbar.site OK
User->>RevAPI: POST /api/reviews body
RevAPI->>RevAPI: Pydantic validate 5-1000 chars
RevAPI->>PG: INSERT status=pending
Note right of RevAPI: stored in underbar-reviews-postgres
RevAPI->>Gemini: POST validate review
Gemini-->>RevAPI: approve OR reject + reason
RevAPI->>RevAPI: UPDATE status + llm_reason
opt admin notify
RevAPI->>Disc: webhook
end
RevAPI-->>User: 202 Accepted
Note over User,Swarm: FLOW C — CMS deploy admin.underbar.site
User->>CF: GET admin.underbar.site
CF->>Caddy: HTTPS DNS-only
Caddy->>Caddy: Tailscale ACL 100.64.0.0/10
Note right of Caddy: path-routing<br/>/api/admin/reviews -> RevAPI<br/>/api + /uploads -> ContAPI<br/>default -> Dokploy nginx
Caddy->>Swarm: serve CMS index.html
User->>CMS: edit product or upload image
CMS->>ContAPI: POST /api with admin-auth
ContAPI->>PG: write underbar-content-postgres
Note over OneDev,Swarm: When code changes
User->>OneDev: git push to townhouse/underbar-admin-ui
OneDev-->>Dokploy: webhook
Dokploy->>OneDev: pull source nixpacks build
Dokploy->>Swarm: rolling update underbar-underbaradminui-j6sver
Swarm-->>CMS: new image live ~1.4s
Note over User,Disc: FLOW D — Patch approval health-staging
User->>Caddy: GET ops.ibo.se/health-staging
Caddy->>Caddy: Tailscale-only OPNsense override
Caddy-->>User: serve dashboard JSON
User->>Caddy: click Approve action
Caddy->>N8N: POST /webhook/mon/approve-action
N8N->>N8N: validate type host target
N8N->>RevAPI: out of scope
N8N->>PG: INSERT approval_log
N8N-->>User: 200 ok
---
config:
theme: dark
layout: elk
title: Townhouse — Monitoring & Automation Pipeline (2026-05-07)
---
flowchart TB
subgraph SRC["DATA SOURCES — push-cron from each host"]
direction LR
S1["mon-patch-report.sh<br/>cron 09:30 UTC daily<br/>6/7 hosts<br/>missing: townhouse-llm"]
S2["mon-image-local.sh<br/>cron 06:00 18:00 UTC<br/>6 hosts docker digest scan"]
S3["Diun on ai-rag<br/>cron 06:00 18:00<br/>21 public-registry images"]
S4["mon-service-versions.py<br/>cron 06:30 18:30<br/>HTTP-version probes<br/>+ GitHub Releases"]
S5["mon-cve-image.sh<br/>per-image trivy<br/>triggered after image change"]
S6["mon-cve-fleet-sweep.sh<br/>weekly cron Sun 04:17"]
S7["mon-disk-report.sh<br/>existing pre-2026-05"]
end
subgraph N8N["N8N WEBHOOK RECEIVERS — on brain :5678"]
direction TB
W1["[MON] Patch webhook receiver<br/>Pzu8d4DTU0W6YplC<br/>→ Fetch prev state<br/>→ Parse + classify<br/>→ NOT IN auto-resolve<br/>→ alert_needed gate"]
W2["[MON] ImageLocal webhook<br/>tiw9OuuBsIYnMmWw"]
W3["[MON] Image webhook receiver<br/>737UwzzYVCOfGd5z<br/>(Diun source)"]
W4["[MON] ServiceVersion webhook<br/>PcXY3Z0EeXvKMZbM"]
W5["[MON] Approve action<br/>5ynBxmhR5HlfRoH2<br/>tightened ok contract<br/>single-read-then-parse"]
W6["[MON] CVE webhook<br/>existing"]
W7["[MON] Disk webhook<br/>existing"]
end
subgraph STO["BRAIN POSTGRES — monitoring DB"]
T1[("patch_packages<br/>NOT IN auto-resolve")]
T2[("patch_host_state<br/>+ patch_host_summary view")]
T3[("image_status<br/>Diun events")]
T4[("image_local<br/>per-host digest")]
T5[("service_versions")]
T6[("cve_findings")]
T7[("approval_log<br/>recent_actions exposed")]
T8[("disk_history")]
end
subgraph DASH["HEALTH DASHBOARD pipeline"]
DH["discover-health.py on brain<br/>cron */15 min<br/>queries Postgres<br/>scp JSON to monitor"]
JSON["/data/health-staging.json<br/>+ recent_actions 30min window"]
UI["ops.imagesbyolofsson.se/health-staging<br/>graf-vy + list-mode<br/>pulse-overlay<br/>apis-staging styling"]
end
subgraph ACT["EXECUTION + ALERTING"]
EXEC["brain-approve-exec :9991<br/>Docker container on brain_default net<br/>SSH out via /root/.ssh<br/>UserKnownHostsFile /dev/null"]
REBOOT["systemctl reboot --no-block<br/>via SSH"]
APT["apt-get install pkg<br/>via SSH"]
DC["docker compose up -d --force-recreate<br/>via SSH"]
DALERT["Discord #alerts-bezzel<br/>+ patch-channel<br/>state-changed gated"]
end
subgraph SEC["SECONDARY MONITORING on monitor-cax11"]
BES["Beszel hub :8090<br/>6 agents<br/>cannot self-monitor"]
GLA["Glances :61208<br/>PyPI v3.4.0.5"]
KUMA["Uptime Kuma<br/>HTTPS endpoints"]
DALERT2["Discord webhooks<br/>18 alerts heavy/lite"]
end
subgraph STATS["LYXLIMO STATS pipeline"]
FETCH["fetch_stats.py on brain<br/>systemd timer 06:00 daily"]
ADS["Google Ads API<br/>r5zEiVt-a028 dev token<br/>customer 8324523542"]
GA4["GA4 Data API<br/>property 440588771"]
SPG[("brain Postgres<br/>lyxlimo_stats DB")]
FLASK["Flask stats.ibo.se<br/>Tailscale-only<br/>Caddy DNS-01 cert"]
end
subgraph VIDEO["LYXLIMO VEO PIPELINE on brain"]
VEO["veo_client.py<br/>generate_for_pmax 16s<br/>2 x 8s ffmpeg concat"]
FF["ffmpeg<br/>concat horizontal + square<br/>+ vertical via 9:16 Veo"]
YT["YouTube Data API v3<br/>youtube.upload scope<br/>10000 units/day"]
ADS_LINK["Google Ads SDK<br/>asset_group_asset link<br/>required: ≥10s"]
end
subgraph BHA["BRAIN-HANDS-APPROVER planned"]
GEN["Generator on townhouse-llm<br/>cron Sunday 23:00<br/>Ollama Qwen3-4B + Gemma-4-E4B"]
PROP[("ad_proposals table<br/>NOT YET CREATED")]
APPR["Approver UI<br/>NOT YET BUILT"]
end
S1 --> W1
S2 --> W2
S3 --> W3
S4 --> W4
S5 --> W6
S6 --> W6
S7 --> W7
W1 --> T1
W1 --> T2
W2 --> T4
W3 --> T3
W4 --> T5
W6 --> T6
W7 --> T8
W5 --> T7
W1 -->|state-changed gate| DALERT
W3 -->|new digest| DALERT
W6 -->|critical CVE| DALERT
W7 -->|threshold| DALERT
T1 --> DH
T2 --> DH
T3 --> DH
T4 --> DH
T5 --> DH
T6 --> DH
T7 --> DH
T8 --> DH
DH --> JSON
JSON -->|scp Tailscale| UI
UI -->|user clicks Approve| W5
W5 -->|HTTP /exec| EXEC
EXEC -->|reboot-host| REBOOT
EXEC -->|patch-package| APT
EXEC -->|image upgrade| DC
EXEC -->|trigger CVE rescan async| S5
BES -->|TCP agent| DALERT2
GLA -.->|HTTP polls| BES
KUMA --> DALERT2
FETCH -->|read| ADS
FETCH -->|read| GA4
FETCH -->|write| SPG
FLASK -->|read| SPG
VEO --> FF
FF -->|MP4 16s| YT
YT -->|video_id| ADS_LINK
VEO -.->|future autonomous trigger| GEN
GEN -.->|future| PROP
PROP -.->|future| APPR
APPR -.->|future| ADS_LINK
classDef srcNode fill:#1a237e,stroke:#fff,color:#fff
classDef n8nNode fill:#4a148c,stroke:#fff,color:#fff
classDef storeNode fill:#1b5e20,stroke:#fff,color:#fff
classDef execNode fill:#b71c1c,stroke:#fff,color:#fff
classDef alertNode fill:#e65100,stroke:#fff,color:#fff
classDef futureNode fill:#424242,stroke:#fff,stroke-dasharray: 5 5,color:#fff
class S1,S2,S3,S4,S5,S6,S7 srcNode
class W1,W2,W3,W4,W5,W6,W7 n8nNode
class T1,T2,T3,T4,T5,T6,T7,T8,SPG storeNode
class EXEC,REBOOT,APT,DC,VEO,FF,YT,ADS_LINK,FETCH execNode
class DALERT,DALERT2 alertNode
class GEN,PROP,APPR futureNode
---
config:
theme: dark
layout: elk
title: Townhouse — n8n Workflows & ops Dashboard Ecosystem (2026-05-07)
---
flowchart TB
subgraph OPS["ops.imagesbyolofsson.se — Tailscale-only via OPNsense override"]
direction TB
OPS_INDEX["index.html<br/>landing page"]
OPS_TOPO["/topology<br/>5 VPS visual map<br/>served from brain"]
OPS_MEM["/memory<br/>memory-projekt dashboard<br/>served from brain"]
OPS_WF["/workflows<br/>n8n Workflow Map<br/>SVG canvas + zoom + filters<br/>data: /data/workflows.json<br/>37 workflows · 11 active"]
OPS_WFS["/workflows-staging<br/>same UI · staging tag"]
OPS_API["/apis-staging<br/>API Endpoint Map<br/>24 integrations registered<br/>shares workflows.json"]
OPS_HEALTH["/health-staging<br/>Patch+CVE+Disk+Image dashboard<br/>graf-mode + list-mode<br/>data: /data/health-staging.json<br/>recent_actions 30min pulse"]
OPS_ARCH["/architecture<br/>Per-host mermaid views<br/>overview + 7 host-specific<br/>15 embedded mermaid diagrams"]
OPS_BHA["/architecture-bha<br/>Brain-Hands-Approver design<br/>6 mermaid diagrams"]
OPS_APPR["/health/alerts/approve<br/>SPA preview-then-confirm<br/>POST /webhook/mon/approve-action"]
end
subgraph N8N_MON["n8n MONITORING — 7 active 2 off"]
direction TB
WF_PATCH["[MON] Patch webhook receiver<br/>Pzu8d4DTU0W6YplC<br/>/webhook/mon/patch-report<br/>postgres+http<br/>10 nodes"]
WF_CVE["[MON] CVE webhook receiver<br/>d5tZRc7O2ychQH42<br/>/webhook/mon/cve-report<br/>postgres+http+discord<br/>8 nodes"]
WF_DISK["[MON] Disk webhook receiver<br/>xbovPyA7v4Y540pQ<br/>/webhook/mon/disk-report<br/>postgres+http+discord<br/>9 nodes"]
WF_IMG["[MON] Image webhook receiver<br/>737UwzzYVCOfGd5z<br/>/webhook/mon/image-report<br/>Diun source<br/>postgres+http"]
WF_IMGL["[MON] ImageLocal webhook receiver<br/>tiw9OuuBsIYnMmWw<br/>/webhook/mon/image-local<br/>postgres+http"]
WF_SVC["[MON] ServiceVersion webhook receiver<br/>PcXY3Z0EeXvKMZbM<br/>/webhook/mon/service-version<br/>HTTP probes + GitHub Releases"]
WF_APPR["[MON] Approve action<br/>5ynBxmhR5HlfRoH2<br/>/webhook/mon/approve-action<br/>tightened ok contract<br/>5 nodes"]
WF_CERT["[MON] Cert expiry sweep<br/>OFF — scheduled<br/>exec+postgres+http+discord"]
WF_TREND["[MON] Disk-space trend<br/>OFF — scheduled<br/>postgres+http+discord+exec"]
end
subgraph N8N_LYX["n8n LYXLIMO — 2 active 5 off legacy copies"]
direction TB
WF_BOOK["Lyxlimo Booking v2 Sheets-observability<br/>q288IvsYAzfoRG53<br/>/webhook/lyxlimo-booking<br/>postgres+discord+sheets<br/>7 nodes"]
WF_AVAIL["Lyxlimo Availability Check<br/>yaJGhiwmbTU7SdoL<br/>/webhook/lyxlimo-availability<br/>postgres<br/>4 nodes"]
WF_LYX_OFF["5 inaktiva booking-kopior<br/>only-short-info, copy mail response,<br/>Booking Apr 19, copy 2 - copy copy,<br/>original Booking — rollback-safe"]
end
subgraph N8N_APR["n8n APPROVAL — 2 active"]
direction TB
WF_APR_GET["Approval API GET /api/approval/:token<br/>bAeLGXMCmVvVJfCb<br/>sheets only · 4 nodes"]
WF_APR_POST["Approval API POST /api/submit<br/>wqL1CewpyAHEfprg<br/>sheets+discord+gmail+gcal<br/>13 nodes — calendar invite live"]
end
subgraph N8N_CAL["n8n CALENDAR — both off"]
direction TB
WF_CAL_AUTO["Add event to Google Calendar automatically<br/>OFF · gcal manual"]
WF_CAL_BOOK["Calendar-Booking<br/>fsonz9WA77EM1hr9<br/>OFF · gcal+gmail+sheets+discord"]
end
subgraph N8N_MKT["n8n MARKETING — all 3 off pending Standard-access"]
direction TB
WF_MKT_GADS["[Marketing] Automate Google Ads search term analysis<br/>qhPTLsrHjJjIxPi0 · 22 nodes<br/>gemini+http+discord"]
WF_MKT_GA4["[Marketing] Google Analytics<br/>p9P0VsiHJB6sRgzx · 16 nodes<br/>gemini+gmail+discord"]
WF_MKT_WEEK["Online Marketing Weekly Report<br/>16 nodes · facebook+http+gemini"]
end
subgraph N8N_JUNK["n8n JUNK — 14 inactive imports/templates"]
direction TB
WF_JUNK["My workflow 1-5 + SpaceX +<br/>Brave Search Goggles + SEO audits +<br/>2x Veo TikTok + 2x SSL monitoring +<br/>Google Ads MCP examples — cleanup-candidates"]
end
subgraph SVC["BACKING SERVICES — on brain unless noted"]
direction LR
SVC_PG[("Postgres<br/>monitoring + lyxlimo + stats")]
SVC_REDIS[("Redis cache")]
SVC_EXEC["brain-approve-exec :9991<br/>SSH-out container"]
SVC_DISC["Discord webhooks<br/>#alerts-bezzel + #patch-channel"]
SVC_GOOG["Google Workspace APIs<br/>Sheets · Calendar · Gmail<br/>SA: townhouse-mcp-sa@<br/>gen-lang-client-0056474916"]
SVC_ADS["Google Ads API<br/>customer 8324523542<br/>dev token r5zEiVt-a028"]
SVC_GA4["GA4 Data API<br/>property 440588771"]
SVC_GEMINI["Google Gemini<br/>review validation +<br/>marketing analysis"]
SVC_OLLAMA["Ollama on townhouse-llm<br/>100.71.126.116:11434"]
end
BROWSER["Linus + Agents<br/>browser via Tailscale"]
OPNS["OPNsense override<br/>routes ops.ibo.se<br/>to monitor-cax11"]
BROWSER --> OPNS
OPNS -->|Tailscale 100.x| OPS_INDEX
OPS_INDEX --> OPS_TOPO
OPS_INDEX --> OPS_MEM
OPS_INDEX --> OPS_WF
OPS_INDEX --> OPS_WFS
OPS_INDEX --> OPS_API
OPS_INDEX --> OPS_HEALTH
OPS_INDEX --> OPS_ARCH
OPS_INDEX --> OPS_BHA
OPS_HEALTH --> OPS_APPR
OPS_WF -.->|reads| WF_DATA[/"/data/workflows.json<br/>generated daily<br/>n8n REST scan on brain"/]
OPS_WFS -.->|reads| WF_DATA
OPS_API -.->|reads| WF_DATA
OPS_HEALTH -.->|reads| HEALTH_DATA[/"/data/health-staging.json<br/>discover-health.py */15min<br/>scp from brain to monitor"/]
OPS_ARCH -.->|embeds| MERMAID_EMB[/"15 mermaid diagrams<br/>per-host views<br/>+ overview"/]
OPS_BHA -.->|embeds| MERMAID_BHA[/"6 mermaid diagrams<br/>BHA design"/]
OPS_APPR -->|POST| WF_APPR
WF_APPR --> SVC_EXEC
WF_APPR --> SVC_PG
SVC_EXEC -.->|SSH| HOSTS[("7 SSH targets:<br/>brain ai-rag lyx-webb<br/>ub-webb monitor gitea")]
HOSTS -.->|cron push| WF_PATCH
HOSTS -.->|cron push| WF_DISK
HOSTS -.->|cron push| WF_IMG
HOSTS -.->|cron push| WF_IMGL
HOSTS -.->|cron push| WF_SVC
HOSTS -.->|trivy push| WF_CVE
WF_PATCH --> SVC_PG
WF_CVE --> SVC_PG
WF_DISK --> SVC_PG
WF_IMG --> SVC_PG
WF_IMGL --> SVC_PG
WF_SVC --> SVC_PG
WF_CVE --> SVC_DISC
WF_DISK --> SVC_DISC
WF_PATCH -->|state-changed gate| SVC_DISC
LYX_FORM[/"lyxlimo.se 5-step form<br/>POST"/] --> WF_BOOK
WF_BOOK --> SVC_PG
WF_BOOK --> SVC_GOOG
WF_BOOK --> SVC_DISC
WF_BOOK -->|generate token<br/>post URL| SVC_DISC
LYX_FORM --> WF_AVAIL
WF_AVAIL --> SVC_PG
APPR_SPA[/"approve.imagesbyolofsson.se<br/>React SPA"/] -->|GET| WF_APR_GET
APPR_SPA -->|POST decision| WF_APR_POST
WF_APR_GET --> SVC_GOOG
WF_APR_POST --> SVC_GOOG
WF_APR_POST --> SVC_DISC
WF_MKT_GADS -.->|reads| SVC_ADS
WF_MKT_GA4 -.->|reads| SVC_GA4
WF_MKT_GADS -.->|analysis| SVC_GEMINI
WF_MKT_GA4 -.->|analysis| SVC_GEMINI
WF_MKT_GA4 -.->|report| SVC_GOOG
WF_MKT_WEEK -.->|consolidated| SVC_DISC
WF_APPR -.->|reboot-host| HOSTS
WF_CERT -.->|when on| SVC_EXEC
WF_TREND -.->|when on| SVC_EXEC
classDef opsNode fill:#1a1a2e,stroke:#C9A84C,color:#C9A84C
classDef monNode fill:#4a148c,stroke:#fff,color:#fff
classDef lyxNode fill:#2e7d32,stroke:#fff,color:#fff
classDef apprNode fill:#0d47a1,stroke:#fff,color:#fff
classDef calNode fill:#37474f,stroke:#aaa,color:#aaa,stroke-dasharray: 3 3
classDef mktNode fill:#bf360c,stroke:#aaa,color:#fff,stroke-dasharray: 3 3
classDef junkNode fill:#212121,stroke:#666,color:#888,stroke-dasharray: 5 5
classDef svcNode fill:#1b5e20,stroke:#fff,color:#fff
classDef dataNode fill:#3e2723,stroke:#C9A84C,color:#fff
class OPS_INDEX,OPS_TOPO,OPS_MEM,OPS_WF,OPS_WFS,OPS_API,OPS_HEALTH,OPS_ARCH,OPS_BHA,OPS_APPR opsNode
class WF_PATCH,WF_CVE,WF_DISK,WF_IMG,WF_IMGL,WF_SVC,WF_APPR monNode
class WF_CERT,WF_TREND,WF_CAL_AUTO,WF_CAL_BOOK calNode
class WF_BOOK,WF_AVAIL lyxNode
class WF_LYX_OFF junkNode
class WF_APR_GET,WF_APR_POST apprNode
class WF_MKT_GADS,WF_MKT_GA4,WF_MKT_WEEK mktNode
class WF_JUNK junkNode
class SVC_PG,SVC_REDIS,SVC_EXEC,SVC_DISC,SVC_GOOG,SVC_ADS,SVC_GA4,SVC_GEMINI,SVC_OLLAMA svcNode
class WF_DATA,HEALTH_DATA,MERMAID_EMB,MERMAID_BHA dataNode
---
config:
theme: dark
layout: elk
title: Townhouse — Service Catalog from dashboard.imagesbyolofsson.se
---
flowchart TB
subgraph DASH["dashboard.imagesbyolofsson.se — service catalog<br/>Tailscale-only · /srv/dashboard on brain · 5 sections · 41 services"]
DBINDEX["Townhouse · Dashboard<br/>SECTIONS data structure<br/>live HEAD-probes per card<br/>tags: public · tailscale · internal · localhost"]
end
subgraph SEC1["SEKTION 01 — OPERATIONS"]
direction TB
S1A["n8n<br/>brain · public<br/>11 active 26 inactive"]
S1B["Approval system<br/>approve.ibo.se<br/>brain · public · token-gated"]
S1C["Approve-Exec service<br/>brain · internal<br/>:9991 SSH-out"]
S1D["Uptime Kuma<br/>status.ibo.se<br/>monitor · public"]
S1E["Beszel hub<br/>monitor :8090 · tailscale<br/>Discord alerts"]
S1F["Glances per nod<br/>:61208 on all 9 nodes<br/>tailscale"]
S1G["Patch+CVE pipeline<br/>ops.ibo.se · public<br/>7/7 reporting"]
S1H["Dokploy<br/>dokploy.ibo.se · public<br/>townhouse-gitea container deploy"]
end
subgraph SEC2["SEKTION 02 — AI"]
direction TB
S2A["LobeChat<br/>chat.ibo.se · tailscale<br/>multi-provider AI chat<br/>Casdoor-auth · demopc dual-GPU"]
S2B["Ollama @ demopc<br/>100.75.223.96:11434<br/>16 GB VRAM RTX 2070 + GTX 1070 Ti<br/>qwen2.5:7b/3b · gemma4:e2b · 3x hermes"]
S2C["Ollama @ townhouse-llm<br/>100.71.126.116:11434<br/>CPU-only · Qwen3-4B + gemma-4-E4B"]
S2D["townhouse-mcp aggregator<br/>ai-rag :1337 · tailscale<br/>Hetzner 14 + GitHub 26 + GA4 5 tools<br/>n8n-bridge FAIL"]
S2E["RAG-API<br/>ai-rag :8000 · tailscale<br/>FastAPI + ChromaDB"]
S2F["BHA Generator<br/>planned · status unknown<br/>demopc / townhouse-llm"]
S2G["BHA Publisher<br/>planned · brain<br/>Google Ads API push"]
S2H["BHA Approver<br/>approve.ibo.se · public<br/>weekly review"]
end
subgraph SEC3["SEKTION 03 — DATA"]
direction TB
S3A["Stats Lyxlimo<br/>stats.ibo.se · tailscale<br/>brain · daily fetch 06:00<br/>Postgres + Flask"]
S3B["Underbar Reviews<br/>reviews.ibo.se · public<br/>underbar-webb 10.0.0.5:8001"]
S3C["Underbar CMS Admin<br/>admin.underbar.site · tailscale<br/>products + categories + hero + audit"]
S3D["Postgres x 7<br/>brain n8n + monitoring · gitea ·<br/>onedev · dokploy · underbar x 2 · lobechat"]
S3E["ChromaDB<br/>ai-rag · internal<br/>RAG embeddings"]
S3F["MinIO LobeChat<br/>demopc :9001 · localhost<br/>S3-compat · A:/AI/lobechat/data"]
S3G["Cloudflare R2<br/>cloud · public<br/>bf4df5...r2.cloudflarestorage.com"]
S3H["Google Ads<br/>cloud · public<br/>2 accounts OAuth2<br/>Lyxlimo + Townhouse-MCC"]
S3I["Google Analytics 4<br/>cloud · public<br/>property 440588771"]
S3J["AdLoop MCP<br/>demopc · localhost<br/>Vanliga datorn"]
end
subgraph SEC4["SEKTION 04 — TOOLS"]
direction TB
S4A["Gitea<br/>gitea.ibo.se · public<br/>14 repos · 3 orgs · Actions runner"]
S4B["OneDev<br/>onedev.ibo.se · public<br/>3 Underbar repos · CI"]
S4C["SilverBullet<br/>silverbullet.ibo.se · public<br/>3 ytor · method-aware ACL"]
S4D["Pingvin Share<br/>townhouse-gitea · public<br/>self-hosted file share"]
S4E["File Browser<br/>townhouse-gitea · internal<br/>filesystem browser"]
S4F["Authelia<br/>auth.ibo.se · public<br/>SSO · OIDC-provider"]
S4G["Casdoor LobeChat<br/>demopc :8000 · localhost<br/>OAuth-provider · admin/123 BYTAS"]
S4H["Tailscale ACL<br/>tailnet · internal<br/>tag:townhouse + 100.64.0.0/10"]
end
subgraph EDGE["edge — already mapped in diagram 1"]
BR["brain"]
AIR["ai-rag"]
LXW["lyxlimo-webb"]
UBW["underbar-webb"]
MON["monitor"]
TGT["townhouse-gitea"]
TLLM["townhouse-llm"]
DPC["demopc"]
IPHONE["iphone laptop edge devices<br/>9 nodes total per dashboard"]
end
DBINDEX --> SEC1
DBINDEX --> SEC2
DBINDEX --> SEC3
DBINDEX --> SEC4
S1A -.host.-> BR
S1B -.host.-> BR
S1C -.host.-> BR
S1D -.host.-> MON
S1E -.host.-> MON
S1F -.host.-> EDGE
S1G -.host.-> MON
S1H -.host.-> TGT
S2A -.host.-> DPC
S2B -.host.-> DPC
S2C -.host.-> TLLM
S2D -.host.-> AIR
S2E -.host.-> AIR
S2F -.host.-> DPC
S2G -.host.-> BR
S2H -.host.-> BR
S3A -.host.-> BR
S3B -.host.-> UBW
S3C -.host.-> UBW
S3D -.distributed.-> EDGE
S3E -.host.-> AIR
S3F -.host.-> DPC
S3J -.host.-> DPC
S4A -.host.-> TGT
S4B -.host.-> TGT
S4C -.host.-> TGT
S4D -.host.-> TGT
S4E -.host.-> TGT
S4F -.host.-> TGT
S4G -.host.-> DPC
classDef catNode fill:#1a1a2e,stroke:#C9A84C,color:#C9A84C,stroke-width:2px
classDef opsNode fill:#4a148c,stroke:#fff,color:#fff
classDef aiNode fill:#b71c1c,stroke:#fff,color:#fff
classDef dataNode fill:#1b5e20,stroke:#fff,color:#fff
classDef toolNode fill:#0d47a1,stroke:#fff,color:#fff
classDef plannedNode fill:#424242,stroke:#aaa,color:#aaa,stroke-dasharray: 5 5
classDef edgeNode fill:#37474f,stroke:#fff,color:#fff
class DBINDEX catNode
class S1A,S1B,S1C,S1D,S1E,S1F,S1G,S1H opsNode
class S2A,S2B,S2C,S2D,S2E aiNode
class S2F,S2G,S2H plannedNode
class S3A,S3B,S3C,S3D,S3E,S3F,S3G,S3H,S3I,S3J dataNode
class S4A,S4B,S4C,S4D,S4E,S4F,S4G,S4H toolNode
class BR,AIR,LXW,UBW,MON,TGT,TLLM,DPC,IPHONE edgeNode
---
config:
theme: dark
layout: elk
title: Townhouse — KOMPLETT inventering 2026-05-07 (alla 23 Tailscale-enheter, alla 14 subdomäner, alla containers per host)
---
flowchart LR
subgraph EXT["INTERNET"]
USR["End-Users + Linus + Agents"]
CF["Cloudflare<br/>DNS + WAF + R2 storage"]
GOOG["Google APIs<br/>Ads + GA4 + Cal + Gmail<br/>Sheets + Veo + Gemini + YouTube"]
DISC["Discord<br/>2 webhooks alerts + patch"]
end
subgraph CADDY["brain Caddy — 14 subdomans (TLS via CF DNS-01)"]
direction TB
D1["n8n.ibo.se → brain :5678"]
D2["approve.ibo.se → brain /srv/approve/www + n8n proxy<br/>Lyxlimo SPA"]
D3["auth.ibo.se → townhouse-gitea :9091<br/>Authelia OIDC SSO"]
D4["status.ibo.se → monitor :3001<br/>Uptime Kuma"]
D5["stats.ibo.se → brain :8050<br/>Lyxlimo Flask · Tailscale-only"]
D6["onedev.ibo.se → townhouse-gitea :6610"]
D7["silverbullet.ibo.se → townhouse-gitea :3030<br/>method-aware ACL FUNGERAR 2026-05-07"]
D8["reviews.ibo.se → underbar-webb 10.0.0.5:8001"]
D9["dokploy.ibo.se → townhouse-gitea :3001"]
D10["final-stage.ibo.se → townhouse-gitea :8084 + Content API<br/>Tailscale-only preview"]
D11["underbar-admin.ibo.se → townhouse-gitea :80 + APIs<br/>LEGACY parallell admin · Tailscale-only"]
D12["admin.underbar.site → swarm CMS + APIs<br/>Tailscale-only"]
D13["chat.ibo.se → demopc LobeChat"]
D14["dashboard.ibo.se → brain /srv/dashboard<br/>Tailscale-only · 41 services index"]
end
subgraph BRAIN["BRAIN cx33 · 204.168.246.143 · ts 100.91.241.68"]
direction TB
BR_CADDY["Caddy host-installed<br/>14 server-blocks · Cloudflare DNS-01"]
BR_N8N["brain-n8n container<br/>:5678 · 37 workflows · 11 active"]
BR_PG["brain-postgres :5432<br/>monitoring + lyxlimo + lyxlimo_stats"]
BR_RED["brain-redis :6379"]
BR_EXEC["brain-approve-exec :9991<br/>SSH-out container · healthy"]
BR_BES["beszel-agent v0.18.7"]
BR_BOT["brain-lyxlimo-bot<br/>RESTARTING (1) BROKEN"]
BR_OPT["/opt/townhouse-generator<br/>BHA Generator-stub"]
BR_HP["/opt/headplane<br/>Headscale-related?"]
BR_MCP["/opt/mcp-hub"]
BR_STA["/opt/stats — Flask + systemd timer 06:00"]
BR_VEO["/srv/lyxlimo-veo<br/>veo_client.py + ffmpeg"]
BR_DASH["/srv/dashboard/index.html<br/>SECTIONS catalog"]
BR_OPS["/srv/ops/www<br/>topology + workflows + memory + index"]
BR_APR["/srv/approve/www<br/>React SPA"]
BR_TRAE["/opt/traefik · pre-Caddy legacy"]
end
subgraph AIRAG["AI-RAG cx33 · 89.167.42.116 · ts 100.120.67.52"]
AR_RAG["rag-api :8000 · FastAPI"]
AR_CHR["rag-chromadb :8000 internal · 0.5.15"]
AR_MCP["townhouse-mcp :1337 · aggregator<br/>Hetzner 14 + GitHub 26 + GA4 5 tools"]
AR_DIUN["diun · cron 6,18 watch 21 images"]
AR_BES["beszel-agent v0.18.7"]
end
subgraph LYXW["LYXLIMO-WEBB cx23 · 204.168.245.109 · ts 100.75.14.44 · webb1"]
LX_NGX["lyxlimo-nginx :80 :443"]
LX_HTML["/srv/lyxlimo/www/index.html<br/>direct-edit no-Astro"]
LX_BES["beszel-agent v0.18.7"]
end
subgraph UBW["UNDERBAR-WEBB cx23 · 204.168.249.189 · ts 100.119.68.48 · webb2"]
UB_NGX["underbar-nginx :80 :443<br/>3 server-blocks"]
UB_CONT["underbar-content-api 10.0.0.5:8002 · healthy"]
UB_REV["underbar-reviews-api 10.0.0.5:8001<br/>Gemini auto-validate"]
UB_PG_C["underbar-content-postgres pg16-alpine"]
UB_PG_R["underbar-reviews-postgres pg16-alpine"]
UB_BES["beszel-agent v0.18.7"]
end
subgraph MON["MONITOR-CAX11 ARM · 65.21.252.57 · ts 100.123.194.33"]
MO_BES["monitor-beszel hub :8090<br/>Discord 18 alerts"]
MO_BESA["beszel-agent latest"]
MO_KUMA["monitor-uptime-kuma :3001 · healthy"]
MO_HOMEP["monitor-homepage :3000 · healthy"]
MO_CADDY["monitor-caddy cloudflare-build :80 :443<br/>routes ops.ibo.se"]
MO_OPS["/opt/monitor/www<br/>10 sub-pages: workflows + workflows-staging + apis-staging<br/>+ health-staging + architecture + architecture-bha<br/>+ topology + memory + index + alerts/approve"]
end
subgraph TGT["TOWNHOUSE-GITEA Core Ultra 5 · ts 100.83.211.41 · laptop"]
direction TB
TG_GITEA["gitea :3000 :2222 · 1.22 · 14 repos 3 orgs"]
TG_GITEA_PG["gitea-postgres pg16"]
TG_RUN["gitea-runner act_runner"]
TG_OD["onedev :6610-6611 · 1dev/server"]
TG_OD_PG["onedev-postgres pg16-alpine"]
TG_DOK["dokploy :3001 swarm v0.29.2 · healthy"]
TG_DOK_PG["dokploy-postgres pg16"]
TG_DOK_RED["dokploy-redis :7"]
TG_SB["silverbullet :3030 · healthy"]
TG_AUTH["authelia :9091 · 4.38 · healthy"]
TG_AUTH_RED["authelia-redis"]
TG_PINGVIN["file-drop-pingvinshare<br/>self-hosted file-share · healthy"]
TG_FB["file-drop-filebrowser · healthy"]
TG_FDC["file-drop-caddy :80 :8080"]
TG_BES["beszel-agent latest"]
TG_SWARM_CMS["underbar-underbaradminui-j6sver swarm task<br/>nixpacks staticfile · :80 default"]
TG_SWARM_FS["underbar-finalstage-hgj4fl swarm task<br/>:8084 preview"]
TG_STAGE["underbar-stage-nginx :8081"]
end
subgraph TLLM["TOWNHOUSE-LLM i7-1265U · ts 100.71.126.116 · laptop"]
TL_OLL["Ollama :11434<br/>Qwen3-4B Q4_K_M · gemma-4-E4B Q4_K_M<br/>OpenAI-compat /v1/"]
end
subgraph DPC["DEMOPC-TOWNHOUSE Win11 · ts 100.75.223.96 · dual-GPU"]
DPC_OLL["Ollama Desktop :11434<br/>RTX 2070 + GTX 1070 Ti = 16 GB VRAM<br/>qwen2.5:7b/3b · gemma4:e2b · 3x hermes"]
DPC_LOBE["LobeChat<br/>multi-provider AI chat"]
DPC_CASD["Casdoor :8000<br/>OAuth-provider · admin/123 BYTAS"]
DPC_MIN["MinIO :9001<br/>S3-compat A:/AI/lobechat/data"]
DPC_LOBE_PG["LobeChat Postgres"]
DPC_AL["AdLoop MCP<br/>Vanliga datorn"]
DPC_DOCK["demopc-docker-desktop ts 100.98.15.107"]
end
subgraph EDGE_TS["EDGE on Tailscale · 23 enheter totalt"]
direction TB
TS_OPN["opnsense ts 100.127.190.86<br/>FreeBSD exit-node + Unbound DNS<br/>OFFLINE 9d"]
TS_OPNDB["vps-opnsense-dashboard ts 100.103.201.116"]
TS_IVER["iver-7vrk6m3 ts 100.114.112.107<br/>Linus jobbdator · OFFLIMITS"]
TS_PHONES["mobile/iPad: demo-phone · ipad157 · iphone-13<br/>+ moa.biserud@: moasdator + samsung-sm-s921b"]
TS_OFFLINE["Offline: parrot 7d · winmachine 94d<br/>desktop-6sgh53h 8h · desktop-igva7s9 175d<br/>townhouse 17d · ubuntulaptop 3d · iphone-13 144d"]
end
subgraph CLOUD["EXTERNAL CLOUD"]
CL_R2["Cloudflare R2<br/>bf4df5...r2.cloudflarestorage.com"]
CL_GADS["Google Ads · 2 OAuth2 accounts<br/>Lyxlimo + Townhouse-MCC<br/>customer 8324523542"]
CL_GA4["GA4 property 440588771"]
CL_GEMI["Gemini API"]
CL_VEO["Veo 3.1 preview API"]
CL_YT["YouTube Data API v3<br/>10000 units/day"]
end
OFFLINE["z10PE-D16-WS workstation<br/>OFFLINE 2026-05-06 · no-POST<br/>2x Xeon E5 v4 + 1TB ECC + 17 disks"]
USR --> CF
CF --> CADDY
CADDY --> BRAIN
CADDY -.proxy.-> AIRAG
CADDY -.proxy.-> LYXW
CADDY -.proxy.-> UBW
CADDY -.proxy.-> MON
CADDY -.proxy.-> TGT
CADDY -.proxy.-> DPC
BR_N8N --> BR_PG
BR_N8N --> BR_RED
BR_N8N --> BR_EXEC
BR_N8N --> DISC
BR_N8N --> GOOG
BR_N8N -.calls.-> TL_OLL
BR_N8N -.calls.-> DPC_OLL
BR_EXEC -.SSH.-> AIRAG
BR_EXEC -.SSH.-> LYXW
BR_EXEC -.SSH.-> UBW
BR_EXEC -.SSH.-> MON
BR_EXEC -.SSH.-> TGT
BR_STA --> CL_GADS
BR_STA --> CL_GA4
BR_VEO --> CL_VEO
BR_VEO --> CL_YT
BR_VEO --> CL_GADS
BR_BOT -.broken.-> BR_N8N
AR_RAG --> AR_CHR
AR_MCP -.tools.-> CL_GADS
AR_MCP -.tools.-> CL_GA4
AR_DIUN --> BR_N8N
LX_NGX --> LX_HTML
LX_NGX -.POST booking.-> BR_N8N
UB_NGX -.bind-mount.-> UB_CONT
UB_REV --> UB_PG_R
UB_CONT --> UB_PG_C
UB_REV --> CL_GEMI
UB_REV --> DISC
MO_OPS -.reads.-> BR_PG
MO_BES --> DISC
MO_KUMA --> DISC
MO_BESA -.collect.-> MO_BES
BR_BES -.collect.-> MO_BES
AR_BES -.collect.-> MO_BES
LX_BES -.collect.-> MO_BES
UB_BES -.collect.-> MO_BES
TG_BES -.collect.-> MO_BES
TG_GITEA --> TG_GITEA_PG
TG_OD --> TG_OD_PG
TG_DOK --> TG_DOK_PG
TG_DOK --> TG_DOK_RED
TG_DOK -->|deploys| TG_SWARM_CMS
TG_DOK -->|deploys| TG_SWARM_FS
TG_AUTH --> TG_AUTH_RED
TG_OD -.git source.-> TG_DOK
TG_GITEA -.mirror eval.-> TG_OD
TG_RUN -.runner.-> TG_GITEA
DPC_LOBE --> DPC_OLL
DPC_LOBE --> DPC_CASD
DPC_LOBE --> DPC_MIN
DPC_LOBE --> DPC_LOBE_PG
DPC_LOBE --> CL_R2
TS_OPN -.exit-node.-> EDGE_TS
classDef brainNode fill:#4a148c,stroke:#fff,color:#fff
classDef webNode fill:#0d47a1,stroke:#fff,color:#fff
classDef dataNode fill:#1b5e20,stroke:#fff,color:#fff
classDef adminNode fill:#f57f17,stroke:#000,color:#000
classDef aiNode fill:#b71c1c,stroke:#fff,color:#fff
classDef extNode fill:#37474f,stroke:#fff,color:#fff
classDef brokenNode fill:#7f1d1d,stroke:#f87171,color:#fff,stroke-width:3px
classDef offlineNode fill:#212121,stroke:#666,color:#888,stroke-dasharray: 5 5
classDef cloudNode fill:#3e2723,stroke:#C9A84C,color:#fff
classDef caddyNode fill:#1a1a2e,stroke:#C9A84C,color:#C9A84C
class BR_CADDY,BR_N8N,BR_EXEC,BR_STA,BR_VEO,BR_DASH,BR_OPS,BR_APR,BR_OPT,BR_MCP,BR_HP,BR_TRAE brainNode
class BR_PG,BR_RED,UB_PG_C,UB_PG_R,AR_CHR,TG_GITEA_PG,TG_OD_PG,TG_DOK_PG,TG_AUTH_RED,TG_DOK_RED,DPC_LOBE_PG,DPC_MIN dataNode
class LX_NGX,LX_HTML,UB_NGX,UB_CONT,UB_REV,AR_RAG,AR_MCP webNode
class TG_GITEA,TG_OD,TG_DOK,TG_SB,TG_AUTH,TG_PINGVIN,TG_FB,TG_FDC,TG_RUN,TG_SWARM_CMS,TG_SWARM_FS,TG_STAGE,MO_BES,MO_KUMA,MO_HOMEP,MO_CADDY,MO_OPS,BR_BES,AR_BES,LX_BES,UB_BES,TG_BES,MO_BESA adminNode
class TL_OLL,DPC_OLL,DPC_LOBE,DPC_CASD,DPC_AL aiNode
class USR,CF,GOOG,DISC,TS_OPN,TS_OPNDB,TS_IVER,TS_PHONES,DPC_DOCK extNode
class BR_BOT brokenNode
class TS_OFFLINE,OFFLINE offlineNode
class CL_R2,CL_GADS,CL_GA4,CL_GEMI,CL_VEO,CL_YT cloudNode
class D1,D2,D3,D4,D5,D6,D7,D8,D9,D10,D11,D12,D13,D14 caddyNode