Back to projects
personal

Homelab

Self-hosted infrastructure on a Synology NAS — reverse proxy, SSO, DNS, monitoring, WireGuard tunnel, and automated deployment.

Docker Traefik WireGuard Prometheus Grafana Authentik View docs

A self-hosted infrastructure stack maintained with the same rigour as production systems. The discipline is the point.

Architecture

  • Synology DS923+ NAS as the primary Docker host (London)
  • Hetzner VPS (Helsinki) as WireGuard endpoint and TCP proxy for public services
  • Traefik v3 reverse proxy with TLS termination and CrowdSec bouncer
  • Authentik SSO with Google OAuth upstream — OIDC for Grafana, Immich, Portainer; forwardAuth for Pi-hole, Traefik dashboard, Prometheus
  • Pi-hole with split-horizon DNS for *.gread.uk and *.internal.gread.uk
  • Prometheus + Grafana + Loki observability pipeline

How it’s managed

Everything is version-controlled in a private GitHub repo. A post-merge git hook handles deployment: secret substitution, config file deployment, conditional Astro site builds, and Docker container management. git pull on the NAS is the deployment mechanism.

Stack

Docker Docker
Traefik Traefik
WireGuard WireGuard
Authentik Authentik
Prometheus Prometheus
Grafana Grafana
Loki Loki
CrowdSec CrowdSec
Pi-hole Pi-hole
Immich Immich
Home Assistant Home Assistant
Portainer Portainer
Uptime Kuma Uptime Kuma
Nginx Nginx
Cloudflare Cloudflare
graph TB
  subgraph ext["Internet"]
    User(["External User"])
    VPS["Hetzner VPS — nginx TCP proxy"]
  end

  subgraph lan["Home Network"]
    Router["Router"]

    subgraph nas["Synology NAS (DS923+)"]
      WireGuard["WireGuard"]
      Traefik["Traefik :443"]
      CrowdSec["CrowdSec"]
      PiHole["Pi-hole :53"]

      subgraph containers["Containers"]
        Authentik["Authentik"]
        Grafana["Grafana"]
        Prometheus["Prometheus"]
        Portainer["Portainer"]
        Uptime["Uptime Kuma"]
        Immich["Immich"]
      end
    end

    subgraph havm["Home Assistant VM"]
      HA["Home Assistant"]
    end

    Client(["LAN Client"])
  end

  User -- HTTPS --> VPS
  VPS -- WireGuard tunnel --> WireGuard
  WireGuard --> Traefik
  Traefik -- stream --> CrowdSec

  Client -- DNS --> PiHole
  Client -- HTTPS --> Traefik

  Router -- DNS --> PiHole

  Traefik --> Authentik
  Traefik --> Grafana
  Traefik --> Prometheus
  Traefik --> Portainer
  Traefik --> Uptime
  Traefik --> Immich
  Traefik --> HA