- Full Obsidian vault content - Host configs (ice, grizzley, ubuntu, proxmox, truenas, panda, hyte) - Media stack documentation - Traefik HA setup - Automation scripts - Bachelor party planning
17 KiB
title, created, updated, type, tags, sources
| title | created | updated | type | tags | sources | |||||
|---|---|---|---|---|---|---|---|---|---|---|
| Homelab Network Architecture | 2026-04-29 | 2026-04-29 | concept |
|
Homelab Network Architecture
Complete traffic flow and routing topology for the homelab cluster. Covers Traefik dual-instance HA, VRRP failover, certificate distribution, Docker network segmentation, and all routing rules.
Traffic Flow Overview
Internet (Cloudflare DNS)
│
▼ *.tophermayor.com A → home public IP
══════════════════════════════════════════════════════════════════════
VRRP VIP 192.168.50.80/27 (eth0.50) — keepalived
┌─────────────────────────────────────────────────────────────┐
│ PRIMARY: ubuntu traefik (when up) │
│ BACKUP: grizzley traefik-pi (when ubuntu fails) │
└─────────────────────────────────────────────────────────────┘
│
▼ port 80/443
┌──────────────────────────────────────────────────────────────────┐
│ grizzley traefik-pi │
│ Edge ingress controller (ACME master, Cloudflare DNS challenge) │
│ IP: 192.168.50.84 | Ports: 80,443,2222,8080,19132udp,19134udp │
│ Network: traefik-proxy │
│ Certs: /mnt/truenas/traefik-certs/grizzley (NFS) │
└──────────────────────────────────────────────────────────────────┘
│
├──[grizzley-local services]──────────────────────────► served directly
│ vaultwarden, uptime-kuma, komodo, homepage,
│ aiostreams, aiomanager, aiometadata,
│ opencode-ice, homeassistant, proxmox, truenas
│
└──[everything else]────────────────────────────────────► forwarded to ubuntu
(upstream-ingress.yml load-balances to ubuntu:443)
DNS Zones
| Zone | Example | Resolution |
|---|---|---|
Public (*.tophermayor.com) |
gitea.tophermayor.com, jellyfin.tophermayor.com |
Cloudflare → home public IP |
Local (*.local.tophermayor.com) |
sonarr.local.tophermayor.com, proxmox.local.tophermayor.com |
UniFi Controller DHCP/DNS |
Cloudflare proxies all *.tophermayor.com — origin IP is hidden, DDoS protection active.
Network Segmentation
Physical / VLAN
| Network | Subnet | Gateway | Hosts |
|---|---|---|---|
| Production (VLAN 50) | 192.168.50.0/24 | 192.168.50.1 | ice, grizzley, ubuntu, proxmox, truenas |
| Default (VLAN 1) | 192.168.1.0/24 | 192.168.1.1 | Management workstations |
| Trusted (VLAN 3) | 192.168.3.0/24 | — | Trusted devices |
| WireGuard VPN | 192.168.4.0/24 | — | VPN clients |
| Docker bridge | 172.16.0.0/12 | — | Container internal networking |
Docker Networks (ubuntu)
| Network | Driver | Subnet | Connected Services |
|---|---|---|---|
proxy-net |
bridge | 172.18.0.0/16 | traefik (primary ingress), homepage-ubuntu |
app-net |
bridge | 172.20.0.0/16 | general application containers |
uefi-proxynet |
bridge | 172.26.0.0/16 | — |
authentik_authentik-internal |
bridge | — | authentik server/worker/redis |
monitoring_monitoring-internal |
bridge | — | prometheus, grafana, loki, alertmanager |
immich_immich-internal |
bridge | — | immich stack |
reccollection-internal |
bridge | — | reccollection stack |
ai-subscriptions_default |
bridge | — | ai-subscriptions |
infisical_infisical |
bridge | — | infisical stack |
Docker Networks (grizzley)
| Network | Driver | Connected Services |
|---|---|---|
traefik-proxy |
bridge | traefik-pi, homepage-grizzley, komodo, aiostreams, aiomanager, aiometadata, vaultwarden, uptime-kuma |
aiomanager_default |
bridge | aiomanager stack |
aiometadata_aiometadata-internal |
bridge | aiometadata stack |
komodo_komodo-internal |
bridge | komodo stack |
homepage_default |
bridge | homepage-grizzley |
desktop-test_default |
bridge | test containers |
High Availability (VRRP / Keepalived)
Two Traefik instances provide failover via keepalived VRRP on VLAN 50.
| Parameter | Value |
|---|---|
| Interface | eth0.50 (VLAN 50) |
| Virtual Router ID | 51 |
| ubuntu priority | PRIMARY (higher) |
| grizzley priority | BACKUP (90) |
| Virtual IP | 192.168.50.80/27 |
| Auth | PASS (HomelabH) |
| Health check | /etc/keepalived/check_traefik.sh — 2s interval, fall 2, rise 2 |
When ubuntu Traefik fails health checks, keepalived promotes grizzley to MASTER and the VIP moves to grizzley's interface. Traffic for *.tophermayor.com and *.local.tophermayor.com then routes to grizzley's traefik-pi (192.168.50.84).
Certificate Architecture
Cloudflare DNS Challenge (grizzley traefik-pi)
│
▼
ACME writes certs to /etc/traefik/certs/acme.json
│
▼ (real-time via NFS)
/mnt/truenas/traefik-certs/grizzley (NFS share from TrueNAS)
│
▼ (read by ubuntu traefik at startup/reread)
ubuntu traefik serves same wildcard certs (*.tophermayor.com)
Both instances serve the same Cloudflare-issued wildcard certificate (*.tophermayor.com) for all public-facing services. The ACME challenge only runs on grizzley — ubuntu syncs certs via NFS.
Traefik Instance Comparison
| Aspect | ubuntu (PRIMARY) | grizzley (BACKUP / ACME) |
|---|---|---|
| Container | traefik |
traefik-pi |
| Image | traefik:v3.6.7 |
traefik:v3.6.7 |
| IP | 192.168.50.61 | 192.168.50.84 |
| Port 80/443 | Direct | Direct |
| HTTP→HTTPS | ✓ | ✓ |
| Cloudflare ACME | ✗ (reads via NFS) | ✓ (origin) |
| Static configs | middlewares.yml |
middlewares.yml |
| Dynamic configs | 29 files | 4 files |
| Networks | proxy-net, app-net, uefi-proxynet |
traefik-proxy |
| Metrics port | — | 8080 |
| SSH proxy port | — | 2222 |
| UDP Minecraft | — | 19132, 19134 |
| upstream-ingress | (receives traffic) | forwards to ubuntu |
Traefik Dynamic Configs
grizzley (Edge / ACME)
| File | Contents |
|---|---|
pi-routers.yml |
Wildcard cert triggers (traefik-wildcard.local.tophermayor.com, traefik-wildcard.tophermayor.com) |
grizzley-services.yml |
11 local routers: vaultwarden, uptime-kuma, komodo, homepage, opencode-ice, aiostreams, aiomanager, aiometadata, homeassistant, proxmox, truenas |
upstream-ingress.yml |
Forwards all unmatched traffic to ubuntu Traefik (HTTPS 192.168.50.61) |
metrics.yml |
Internal metrics endpoints |
middlewares.yml |
IP allowlists (local-only, homepage-localonly), security headers |
ubuntu (Primary Router)
| File | Contents |
|---|---|
gitea.yml |
gitea.tophermayor.com → gitea:3000 |
immich.yml |
immich.tophermayor.com → immich_server:2283 |
jellyfin.yml |
jellyfin.tophermayor.com → jellyfin:8096 (rate limit + jellyfin headers) |
media-stack.yml |
sonarr, radarr, lidarr, prowlarr, qbittorrent, sabnzbd, readarr, sonarr-anime, radarr-anime, lazylibrarian, nzbdav → via gluetun VPN tunnel |
opencode.yml |
opencode.tophermayor.com → host.docker.internal:4096 |
proxmox.yml |
proxmox.local.tophermayor.com → https://192.168.50.11:8006 |
homepage-widgets.yml |
Internal routes (sonarr-internal, radarr-internal, etc.) → gluetun VPN tunnel |
upstream-ingress.yml |
Homepage routes to homepage-ubuntu:3003 and homepage-grizzley:3000 |
whisper.yml |
whisper.local.tophermayor.com → faster-whisper-server:8394 |
truenas.yml |
truenas.local.tophermayor.com → TrueNAS web UI |
navidrome.yml |
navidrome.tophermayor.com |
audiobookshelf.yml |
audiobooks.tophermayor.com |
calibre-web.yml |
calibre-web.local.tophermayor.com |
kavita.yml |
kavita.tophermayor.com |
rustfs.yml |
rustfs S3 routes |
stremio.yml |
stremio routes |
jellyseerr.yml |
jellyseerr.tophermayor.com |
comparaison.yml |
comparison service |
inventory.yml |
inventory service |
cabo-voting.yml |
Cabo voting app |
gsd-mcp.yml |
GSD MCP server |
ai-subscriptions.yml |
AI subscriptions service |
hermes-dashboard.yml |
Hermes dashboard routes |
homeassistant.yml |
Home Assistant route |
umm.yml |
Unified media manager |
middlewares.yml |
Full middleware stack (see below) |
All Traefik Routes
grizzley traefik-pi (Local Services)
| Domain | Service | Backend | Middleware | Cert |
|---|---|---|---|---|
vaultwarden.tophermayor.com |
vaultwarden | vaultwarden:80 | — | cloudflare |
status.tophermayor.com |
uptime-kuma | uptime-kuma:3001 | — | cloudflare |
komodo.local.tophermayor.com |
komodo | komodo:9120 | — | cloudflare |
homepage.local.tophermayor.com |
homepage | homepage-grizzley:3000 | homepage-localonly | cloudflare |
opencode-ice.local.tophermayor.com |
opencode-ice | 192.168.50.197:4096 | local-only | cloudflare |
aiostreams.tophermayor.com |
aiostreams | aiostreams:3002 | — | cloudflare |
aiomanager.tophermayor.com |
aiomanager | aiomanager:1610 | — | cloudflare |
aiometadata.tophermayor.com |
aiometadata | aiometadata:1337 | — | cloudflare |
ha.tophermayor.com |
homeassistant | 192.168.30.196:8123 | — | cloudflare |
proxmox.local.tophermayor.com |
proxmox | 192.168.50.11:8006 | local-only | cloudflare |
truenas.local.tophermayor.com |
truenas | 192.168.50.12:8080 | local-only | cloudflare |
traefik-grizzley.local.tophermayor.com |
dashboard | api@internal | local-only | cloudflare |
metrics-grizzley.local.tophermayor.com |
metrics | api@internal | local-only | cloudflare |
grizzley traefik-pi (Upstream → ubuntu)
Traffic NOT matched above is forwarded via upstream-ingress.yml:
| Rule | Target |
|---|---|
HostRegexp(^[a-z0-9-]+\.local\.tophermayor\.com$) && !homepage && !traefik-grizzley && !metrics-grizzley && !traefik-wildcard && !opencode-ice |
→ ubuntu:443 |
HostRegexp(^[a-z0-9-]+\.tophermayor\.com$) && !traefik-wildcard |
→ ubuntu:443 |
ubuntu traefik (Public Routes — *.tophermayor.com)
| Domain | Backend | Middleware |
|---|---|---|
gitea.tophermayor.com |
gitea:3000 | homelab-public |
immich.tophermayor.com |
immich_server:2283 | homelab-public |
jellyfin.tophermayor.com |
jellyfin:8096 | ratelimit, jellyfin-headers |
audiobooks.tophermayor.com |
audiobookshelf | homelab-public |
navidrome.tophermayor.com |
navidrome | homelab-public |
kavita.tophermayor.com |
kavita:5000 | homelab-public |
opencode.tophermayor.com |
host.docker.internal:4096 | local-only, opencode-streaming, opencode-cors |
ha.tophermayor.com |
192.168.30.196:8123 | (see homeassistant.yml) |
jellyseerr.tophermayor.com |
jellyseerr | homelab-public |
ubuntu traefik (Local Routes — *.local.tophermayor.com)
| Domain | Backend | Middleware | Notes |
|---|---|---|---|
sonarr.local.tophermayor.com |
gluetun:8989 | local-only | Via VPN tunnel |
radarr.local.tophermayor.com |
gluetun:7878 | local-only | Via VPN tunnel |
lidarr.local.tophermayor.com |
gluetun:8686 | local-only | Via VPN tunnel |
sabnzbd.local.tophermayor.com |
gluetun:8080 | local-only | Via VPN tunnel |
qbittorrent.local.tophermayor.com |
qbittorrent | local-only | |
prowlarr.local.tophermayor.com |
prowlarr | local-only | |
readarr.local.tophermayor.com |
readarr | local-only | |
sonarr-anime.local.tophermayor.com |
sonarr-anime | local-only | Via VPN tunnel |
radarr-anime.local.tophermayor.com |
radarr-anime | local-only | Via VPN tunnel |
flaresolverr.local.tophermayor.com |
flaresolverr | local-only | |
bazarr.local.tophermayor.com |
bazarr:6767 | local-only | |
lazylibrarian.local.tophermayor.com |
lazylibrarian | local-only | |
nzbdav.local.tophermayor.com |
nzbdav | local-only | |
calibre-web.local.tophermayor.com |
calibre-web:8083 | local-only | |
stremio.local.tophermayor.com |
stremio-server | local-only | |
proxmox.local.tophermayor.com |
192.168.50.11:8006 | proxmox-headers, local-only | |
truenas.local.tophermayor.com |
192.168.50.12:8080 | local-only | |
opencode-ice.local.tophermayor.com |
192.168.50.197:4096 | local-only | |
whisper.local.tophermayor.com |
faster-whisper-server:8394 | local-only | |
traefik.local.tophermayor.com |
api@internal | local-only | Dashboard |
Internal Widget Routes (sonarr-internal, etc.)
These are *-internal.local.tophermayor.com routes for Homepage widgets, accessible only inside the network via the gluetun VPN tunnel. From homepage-widgets.yml:
| Internal Domain | Backend (via gluetun) |
|---|---|
sonarr-internal.local.tophermayor.com |
gluetun:8989 |
radarr-internal.local.tophermayor.com |
gluetun:7878 |
lidarr-internal.local.tophermayor.com |
gluetun:8686 |
sabnzbd-internal.local.tophermayor.com |
gluetun:8080 |
seerr-internal.local.tophermayor.com |
seerr:5055 |
jellyfin-internal.local.tophermayor.com |
jellyfin:8096 |
prometheus-internal.local.tophermayor.com |
prometheus:9090 |
Special Protocols
| Protocol | Port | Host | Purpose |
|---|---|---|---|
| HTTP→HTTPS | 80 | grizzley | Redirects to 443 |
| HTTPS | 443 | grizzley | All TLS traffic |
| QUIC/HTTP3 | 443/udp | grizzley | HTTP3 support |
| Traefik metrics | 8080 | grizzley | Prometheus scraping |
| Gitea SSH proxy | 2222 | grizzley | → ubuntu:2222 |
| Minecraft Bedrock | 19132/udp | grizzley | Bedrock server (standby) |
| Minecraft Bedrock | 19134/udp | grizzley | Bedrock server (sison) |
Middleware Chains (ubuntu)
homelab-public
Applied to: gitea, immich, audiobookshelf, navidrome, kavita, jellyseerr, etc.
chain: [compress, security-headers, buffering, ratelimit]
Security Headers
Applied to most services:
browserXssFilter: true
contentTypeNosniff: true
forceSTSHeader: true
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 31536000 # 1 year
customFrameOptionsValue: SAMEORIGIN
Jellyfin-specific Headers
Adds CSP allowing jsDelivr CDN for the Ultrachromic theme:
contentSecurityPolicy: "style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://fonts.googleapis.com; ..."
Authentik ForwardAuth (SSO)
Applied to: sonarr, radarr, lidarr, prowlarr, bazarr, sabnzbd, transmission, qbittorrent, flaresolverr, jellyseerr, listsync, dockge, it-tools, bentopdf, code-ai, and more.
Each service has its own middleware with X-authentik-host query param:
http://authentik-server:9000/outpost.goauthentik.io/auth/traefik?X-authentik-host=<domain>
local-only IP Allowlist
sourceRange:
- 127.0.0.1/32
- 192.168.50.0/24 # Production
- 192.168.1.0/24 # Management
- 192.168.3.0/24 # Trusted
- 192.168.4.0/24 # WireGuard VPN
- 172.16.0.0/12 # Docker
- 10.0.0.0/8 # VPN/Docker
Rate Limiting
average: 100
burst: 50
VPN Tunnel (gluetun)
Media automation services route through gluetun VPN container for privacy when connecting to torrent/indexer services:
- sonarr → gluetun:8989
- radarr → gluetun:7878
- lidarr → gluetun:8686
- sabnzbd → gluetun:8080
gluetun ports: 8000, 8388, 8888 (TCP), 8388 (UDP) — exposed on ubuntu's Docker network.
SSH Routing
Gitea SSH is proxied through grizzley:
Internet → grizzley:2222 (SNI * → any)
→ forwards to ubuntu:2222
→ gitea container handles git SSH protocol
UniFi Controller
Network services (DHCP, DNS, VLAN tagging) managed by UniFi Controller at 192.168.1.1 (or similar). All internal DNS for *.local.tophermayor.com resolves through the UniFi DNS forwarder.
Related
- traefik — Traefik entity page
- grizzley — RPi5 edge node (ACME master, backup ingress)
- ubuntu — Primary Docker host (primary ingress router)
- truenas — NFS storage for cert sync
- traefik-ha — HA concept page
- homepage — Dashboard services with widget routes
- authentik — SSO identity provider
- sso-authentik — SSO configuration details