Self-hosted media server, gaming platform, and identity provider running on Windows 11 / Docker Desktop. 26 Compose projects, 39 containers.
flowchart LR
Internet([Internet])
Client([ZeroTier Client])
subgraph public[Public Edge]
CF[Cloudflare Tunnel]
end
subgraph zerotier[ZeroTier Overlay - 10.145.13.136]
direction TB
AUTH[Authentik SSO]
JF[Jellyfin / Media]
ARR[Radarr / Sonarr / Prowlarr]
MON[Prometheus + Grafana + cAdvisor]
DASH[Homarr Dashboard]
end
subgraph vpn[VPN Sidecar Namespace]
QB[qBittorrent]
RM[RomM]
GV[GameVault]
end
Internet --> CF
CF --> GV
CF --> RM
Client --> zerotier
Client --> AUTH
AUTH -.OIDC/LDAP.-> JF
AUTH -.OIDC.-> ARR
QB -.WireGuard egress.-> Internet
RM -.ProtonVPN egress.-> Internet
GV -.ProtonVPN egress.-> Internet
This repository documents a Windows 11 homelab built around Docker Desktop, self hosted media services, game libraries, identity, monitoring, and operations tooling. The stack is organized as production style infrastructure: one Compose project per service, explicit network boundaries, Authentik SSO for user facing applications, and documented operational decisions instead of one off edits. It also includes custom PowerShell and Python tooling for disk-health monitoring, Authentik automation, library repair, and service maintenance.
| Category | Service | Purpose |
|---|---|---|
| Media Server | Jellyfin | Self-hosted video and music streaming |
| Media Library | AudioBookShelf | Audiobook and ebook library server |
| Media Library | Shelfmark | Book and audiobook shelf interface |
| Media Library | Komga | Comics and manga library server |
| Media Automation | Radarr | Movie library management |
| Media Automation | Sonarr | TV library management |
| Media Automation | Prowlarr | Indexer management for Arr services |
| Media Automation | Autoscan | Media library scan trigger service |
| Media Automation | Kapowarr | Comic acquisition and management |
| Media Automation | LazyLibrarian | Book acquisition and management |
| Downloading | qBittorrent | P2P client with VPN-isolated egress via WireGuard/ProtonVPN |
| Requests | Seerr | Media request management |
| Books | Calibre / Calibre-Web Automated | Book library ingestion and Calibre automation |
| Gaming | RomM | Retro game library and metadata platform routed through VPN sidecar |
| Gaming | GameVault | Self-hosted PC game library routed through VPN sidecar |
| Identity | Authentik | SSO, OIDC, OAuth2, LDAP, and invite flows |
| Dashboard | Homarr | Homelab dashboard with guarded access |
| Operations | Dockge | Docker Compose stack management |
| Operations | Dozzle | Container log viewer |
| Operations | DIUN | Container image update notifications |
| Monitoring | Prometheus, Grafana, cAdvisor | Container and host metrics stack |
| Monitoring | Scrutiny | SMART disk-health monitoring UI |
| Monitoring | Uptime Kuma | Service uptime checks and notifications |
| Networking | Nginx Traffic Proxy | Internal proxy for selected service traffic |
| Networking | Byparr | Indexer antibot helper service |
| Remote Access | RustDesk | Self-hosted relay and rendezvous service |
Every service lives in its own directory under <ServiceName>/docker-compose.yml. There is no monolithic root Compose file, so services can be started, stopped, inspected, and updated independently without taking down the full stack.
User-facing services are scoped to private access patterns, with ZeroTier overlay binding used where appropriate instead of broad 0.0.0.0 exposure. Publicly reachable paths are intentionally limited: GameVault and RomM are exposed through Cloudflare Tunnel, and RustDesk publishes relay protocol ports because that is required for its service model.
Three services route traffic through WireGuard/ProtonVPN sidecars using network_mode: service:<sidecar>: qBittorrent, RomM, and GameVault. This keeps VPN-dependent application traffic in the sidecar network namespace and makes egress behavior explicit in Compose.
Authentik is the central identity provider for user-facing apps through OIDC, OAuth2, and LDAP. The Auth/ directory contains Python API automation for providers, app bindings, LDAP outpost setup, and invite-flow configuration.
Prometheus, Grafana, and cAdvisor provide container metrics. Scrutiny tracks disk SMART health. Custom PowerShell tooling in DiskHealth/ monitors a 16-drive array and integrates alerting through Telegram.
| Tool | What it does |
|---|---|
DiskHealth/ |
PowerShell SMART monitoring with Telegram alerting for a 16-drive array |
TelegramAlerts/ |
Uptime Kuma notification setup scripts |
HomelabMCP/ |
Custom Model Context Protocol (MCP) server exposing homelab operations such as service status, log inspection, and Compose inventory through a local tool interface |
HostQoS/ |
Docker upload bandwidth throttle using host-side PowerShell and Linux traffic control |
Tools/scripts/ |
Repair and maintenance utilities for Arr services, AudioBookShelf, Komga, and Shelfmark |
Auth/configure-*.py |
Authentik API automation for OIDC providers, LDAP outpost setup, and invite flows |
Calibre/overrides/ |
Custom Calibre-Web Automated ingest hook override |
- User-facing services are protected by Authentik authentication where supported.
- Services are bound to private network paths where practical instead of public host-wide exposure.
- VPN sidecars isolate egress for qBittorrent, RomM, and GameVault.
- Secrets and environment files are excluded from version control.
- API-generated Authentik exports and plugin downloads are treated as local artifacts, not source files.
- Authentik bootstrap credentials are removed after initial setup.
- Docker socket access is limited to services that require it, including Dockge, Dozzle, Homarr, DIUN, and cAdvisor.
<ServiceName>/docker-compose.yml # One Compose project per service
Tools/scripts/ # Maintenance and repair utilities
DiskHealth/ # SMART monitoring scripts
STACK_INVENTORY.md # Verified live service inventory
DECISIONS.md # Architecture and security decisions log
OPERATIONS.md # Standard operating procedures
BACKUPS.md # Data tier classification
A few decisions in this stack worth calling out:
| Decision | Why | Tradeoff |
|---|---|---|
| One Compose project per service (no monolithic root file) | Service-level blast radius isolation; individual restart, update, inspect without touching neighbors | More directories to navigate; no single docker compose up for the whole stack |
| ZeroTier overlay for private access (vs. opening LAN ports) | Encrypted mesh; same IP regardless of network; no port forwarding | Clients must install ZeroTier; not friction-free for non-technical users |
VPN sidecars via network_mode: service:<sidecar> |
Egress isolation enforced at the network namespace; explicit and visible in Compose | One extra container per VPN-routed service; sidecar must be recreated with its paired app |
| Cloudflare Tunnel for the two public services | No ISP-facing ports, no static IP needed, edge filtering for free | Bound to Cloudflare; would need migration if Cloudflare changes terms |
| Authentik for SSO across user-facing apps | One identity, OIDC + OAuth2 + LDAP under one roof, invite flows | Heavyweight for a small homelab; PostgreSQL + Redis + worker + outpost |
| Per-service .env files (vs. shared secrets store) | Simpler; aligns with Compose conventions; each service is self-contained | No centralized rotation; secret reuse requires manual sync |
| Decision log and operations runbook | Architecture choices and operational commands are recorded before changes become routine | More documentation to maintain as the stack evolves |
Docker, Docker Compose, Authentik, OIDC, LDAP, OAuth2, ZeroTier, WireGuard, ProtonVPN, Prometheus, Grafana, cAdvisor, Nginx, Cloudflare Tunnels, Model Context Protocol (MCP), Jellyfin, Radarr, Sonarr, qBittorrent, Komga, Calibre-Web Automated, AudioBookShelf, RomM, GameVault, RustDesk, Scrutiny, InfluxDB, Dockge, Homarr, PowerShell, Python.