Security Architecture
Network security
Problem: Shared WiFi, no router access, roommates shouldn't see services.
Solution: Three layers of protection:
Cloudflare Tunnel — Zero ports exposed on LAN. Traffic flow:
Internet → Cloudflare → Tunnel → Traefik → Service. No router port forwarding needed.127.0.0.1binding — Traefik's ports (80,443) bind to127.0.0.1, not0.0.0.0. No other containers expose host ports at all. This means roommates on the same WiFi cannot discover or connect to any service — onlycloudflared(inside Docker) can reach Traefik. Verify withdocker compose ps— you should see127.0.0.1:80->80not0.0.0.0:80->80.Tailscale VPN — Mesh VPN using WireGuard under the hood. Runs in userspace (no kernel modules). Advertises the Docker network as a subnet route, so your phone/laptop can reach all services directly when on the Tailscale network. Acts as an exit node for remote access.
CrowdSec — Community-driven intrusion detection. Reads Traefik access logs. Automatically bans malicious IPs. The Traefik bouncer blocks banned IPs at the proxy level before requests reach any service.
SSO & Access control
Authentik provides three authentication mechanisms:
- Forward-auth (via Traefik) — every request to subdomains listed in
setup_rbac.pyis intercepted. Unauthenticated users see the Authentik login page atauth.h5h.me. Includessh.h5h.me(Dashboard, Admin-only) — there is no public tier in the tunneled surface. - Social login — users can sign in with Google via OAuth (provisioned by
setup_rbac.py). - OIDC provider — Authentik acts as an identity provider for apps that support OpenID Connect (Grafana is pre-configured; group
adminsmaps to GrafanaAdmin, otherwiseViewer, with anonymous Viewer enabled).
(See authentik_rbac.md for the exact tier → service mapping — which is regenerated from setup_rbac.py by make gen-docs.)
Container hardening
no-new-privilegeson all sensitive containers- Docker socket mounted as
:roeverywhere - No host ports exposed except Traefik (
127.0.0.1:80/443) - Health checks on critical databases and infrastructure limits restart loops
- Log rotation on all containers via JSON file driver (10 MB × 3 files max)
- CrowdSec bouncer is first middleware in the Traefik chain
- Internal Docker network (
h5h_internal,internal: true) isolates all databases
Alerting (Prometheus)
Prometheus alert rules fire on:
- High unauthorized request rate (401/403)
- High server error rate (5xx)
- Infrastructure downtime
- Container OOM kills (fires immediately when any container is killed, annotated locally in Grafana as red vertical lines)
Log aggregation
- Promtail ships Docker container logs + Traefik access logs (JSON) to Loki
- Grafana queries Loki for the Security & Access dashboard