Home Infrastructure Lab
Personal infrastructure environment for learning, self-hosting, and operational practice. Running 24/7 on production-grade hardware with real network segmentation, SSO, monitoring, and IaC-style documentation.
Hypervisor
Proxmox VE
Firewall
pfSense (Intel N100)
Switching
TP-Link Omada (managed)
ISP
AT&T Fiber 1 Gbps
VPN
WireGuard (pfSense)
Reverse Proxy
Caddy + Cloudflare DNS-01
Auth
Authentik SSO
DNS
Pi-hole → Unbound → Cloudflare
Containers
9 LXC + 2 VMs
| VLAN | Name | Subnet | Purpose |
|---|---|---|---|
| 1000 | MGMT | 10.0.0.0/24 | Network equipment only |
| 1010 | LAN | 10.1.0.0/24 | Trusted personal devices |
| 1020 | Homelab | 10.2.0.0/24 | All self-hosted services |
| 1030 | Guests | 10.3.0.0/24 | Internet only, RFC1918 blocked |
| 1040 | IoT | 10.4.0.0/24 | Smart home, isolated |
| 1050 | WFH | 10.5.0.0/24 | Work devices, no personal access |
| DMZ | DMZ | 10.99.0.0/24 | Public-facing, hard-blocked internally |
| VPN | VPN | 10.200.0.0/24 | WireGuard clients = LAN access |
Core Infrastructure
pfSense
Firewall, DHCP, routing, WireGuard VPN
Caddy
Reverse proxy with automatic wildcard TLS via Cloudflare DNS-01
Pi-hole
Network-wide DNS + ad blocking
WireGuard
VPN — 600–900 Mbps on N100, full LAN access for clients
Security & Auth
Authentik
SSO provider — OIDC + forward auth across all services
Vaultwarden
Self-hosted password manager, isolated in its own LXC
Monitoring
Victoria Metrics
Long-term metrics storage and querying
Grafana
Dashboards and alerting across all hosts and services
Beszel
Lightweight container and host monitoring
ntfy
Self-hosted push notifications
Productivity
Gitea
Personal Git server
Outline
Team wiki and knowledge base
Vikunja
Task management
Actual Budget
Personal budgeting
Ghostfolio
Investment portfolio tracking
Hoarder
Bookmark manager with tagging
FreshRSS
RSS reader
Memos
Quick notes and journal
Traggo
Time tracking
Baikal
CalDAV / CardDAV server
Grist
Spreadsheets and structured data
Media
Plex + Jellyfin
Media streaming
Sonarr / Radarr / Lidarr
Automated media management
Calibre-Web
Book library with auto-ingest
AT&T Gateway: IP Passthrough over EAP bypass
decision: BGW320 stays in-line with IP Passthrough mode. pfSense gets the public IP directly. Gateway WiFi disabled.
why: AT&T locks 802.1X auth to their gateway hardware. EAP proxy bypass is brittle — breaks on firmware updates and only saves 1–2ms. True bridge mode isn't supported.
Caddy over NGINX Proxy Manager
decision: Caddy with DNS-01 challenge via Cloudflare API. All subdomains resolve to Caddy internally via Pi-hole. Caddy terminates SSL and proxies to backends.
why: Single Caddyfile, auto-cert without exposing port 80/443 to the internet. NPM has more UI overhead for the same outcome. Traefik is more complex for no benefit here.
WireGuard over OpenVPN
decision: WireGuard on pfSense, UDP 51820, VPN subnet 10.200.0.0/24. Clients get LAN + MGMT access, blocked from Guest/IoT/WFH.
why: Faster, simpler config, better battery life on mobile. ~600–900 Mbps on an N100. OpenVPN has no advantage here. Tailscale adds an external relay dependency.
Pi-hole in Homelab VLAN, not MGMT
decision: Pi-hole at 10.2.0.11 (VLAN 1020). Firewall allows port 53 inbound from all VLANs. MGMT uses pfSense Unbound as its primary DNS.
why: Putting Pi-hole in MGMT would require opening MGMT to all VLANs — a larger attack surface. DNS traffic crossing into Homelab VLAN is the lesser risk.
N100 for pfSense
decision: Intel N100 mini PC: 4-core 3.4 GHz, ~6W idle. Handles 2–3 Gbps routing and 600–900 Mbps WireGuard.
why: Right-sized for 1 Gbps fiber with headroom. Raspberry Pi can't handle 1 Gbps + VPN. A full rack server wastes power for this role.
Shared Postgres + Redis in apps LXC
decision: One Postgres instance, multiple databases. One Redis instance. A single init script provisions all schemas on first run.
why: Avoids 15 separate DB containers. Reduces RAM overhead significantly. All productivity apps share the same LXC (10.2.0.60).
Gitea CI/CD: Self-hosted runner with container build + SSH rsync deploy
decision: act_runner v0.3.1 on Gitea LXC (10.99.0.22). Push to dev → node:22-alpine container builds Next.js → rsync out/ to Portfolio LXC → SSH docker rebuild.
why: Keeps the full pipeline internal — no GitHub Actions, no external runners. Build runs in an isolated Alpine container so the Gitea LXC isn't polluted. Portfolio LXC (10.99.0.23) just serves pre-built static files via nginx.
lerkolabs on GitHub
Full documentation: VLAN maps, runbooks, service registry, config exports, and setup guides.
↗ github.com/lerko96/homelab-wip