Self-Hosted Home Lab

NAS private cloud — no inbound ports, zero-trust at the edge, declarative and versioned in Git.

A family-facing private cloud on a NAS: photos, files, media, and monitoring — all self-hosted, HTTPS everywhere, and declared as code, so every stack redeploys onto fresh hardware straight from this repo.

Architecture

Homelab architectureInternet traffic reaches Cloudflare edge for DNS, WAF, TLS, and Access, then enters the homelab through a Cloudflare Tunnel. LAN and Tailscale clients resolve the same hostnames via AdGuard Home and, like the tunnel, land on a reverse proxy that applies per-host access lists and routes to self-hosted services. Dockge and monitoring run alongside, outside the request path.InternetHTTPS onlyCloudflare (Edge)DNS · WAF / TLS · Access (OAuth / SSO)mTLS · service tokensCloudflare TunnelHomelab (NAS)cloudflaredtunnelLAN · TailscaleAdGuard · same namesReverse proxyTraefik · HTTPS · ACLsSelf-hosted servicesImmich · OpenCloud · ntfy · …Supporting services · not in the request pathDockgestack managementMonitoringKuma · Beszel → ntfyHomelab architectureInternet traffic reaches Cloudflare edge for DNS, WAF, TLS, and Access, then enters the homelab through a Cloudflare Tunnel. LAN and Tailscale clients resolve the same hostnames via AdGuard Home and, like the tunnel, land on a reverse proxy that applies per-host access lists and routes to self-hosted services. Dockge and monitoring run alongside, outside the request path.InternetHTTPS onlyCloudflare (Edge)DNS · WAF / TLS · Access (OAuth / SSO)mTLS · service tokensCloudflare TunnelHomelab (NAS)cloudflaredtunnelLAN · TailscaleAdGuard · same namesReverse proxyTraefik · HTTPS · ACLsSelf-hosted servicesImmich · OpenCloud · ntfy · …Supporting services · not in the request pathDockgestack managementMonitoringKuma · Beszel → ntfy
Cloudflare Tunnel and Tailscale both dial out — LAN and VPN still hit the same reverse proxy. Nothing is port-forwarded.

Design decisions

  1. No inbound ports

    All external traffic enters via Cloudflare Tunnel, and the Tailscale VPN dials out the same way. Every service here is published outbound-only; none of them needs a forwarded port or a public IP.

  2. One hostname everywhere

    Public DNS resolves to Cloudflare; AdGuard Home rewrites map the same names to internal IPs for LAN and VPN clients alike. Either way the request hits the same reverse proxy — same URLs, same TLS, same app logins, one bookmark.

  3. Encrypted lookups

    Lookups leave over DoH, so nothing on the path sees a plaintext hostname — the name resolution is encrypted, not just the request that follows it. AdGuard Home speaks DoH natively, with no second resolver bolted alongside.

  4. Auth at the edge

    Cloudflare Access enforces SSO/OAuth for humans, service tokens and mTLS for machines — every policy evaluated at the edge, not inside the apps. The apps keep their own logins behind that, and there is no public origin to go around it.

  5. Least privilege on the VPN

    VPN traffic reaches Traefik directly, skipping Cloudflare Access, so per-route allowlists carry it instead: family devices get only the public apps behind their own logins, and admin UIs answer to my devices alone.

  6. Layered monitoring

    Uptime Kuma covers container and HTTP liveness, Beszel covers resources, and Better Stack probes the public path from outside. Alerts converge on ntfy — and Better Stack also expects a heartbeat on a schedule, so a lab that goes dark entirely, ntfy included, still raises an alarm: the missing heartbeat is the alert.

    Live status page
  7. Secrets stay out of Git

    Every stack is compose-as-code with `.env.example` templates. Runtime secrets live only in ignored env files; config is reproducible, credentials are not.

Stack

  • ImmichPhoto / video library and phone backup
  • OpenCloudFile sync and collaboration
  • Plex / PlexampMedia (runs on the NAS; not in the repo)
  • Home AssistantHome automation
  • Cloudflare TunnelOutbound-only ingress, Access, mTLS
  • TailscaleACL-scoped VPN for family devices and admin
  • TraefikTLS termination, per-host routing and access lists
  • AdGuard HomeDNS over HTTPS upstream, ad blocking, LAN hostname rewrites
  • DockgeCompose stack manager
  • Uptime KumaContainer and HTTP liveness probes
  • BeszelCPU, RAM, disk, temperature metrics
  • ntfyPush alert sink for every monitoring layer

Depth lives in the Homelab Infrastructure README — this page is the portfolio view.