lerkolabs

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.

at a glance9

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

network8 isolated vlans · default deny inter-vlan
VLANNameSubnetPurpose
1000MGMT10.0.0.0/24Network equipment only
1010LAN10.1.0.0/24Trusted personal devices
1020Homelab10.2.0.0/24All self-hosted services
1030Guests10.3.0.0/24Internet only, RFC1918 blocked
1040IoT10.4.0.0/24Smart home, isolated
1050WFH10.5.0.0/24Work devices, no personal access
DMZDMZ10.99.0.0/24Public-facing, hard-blocked internally
VPNVPN10.200.0.0/24WireGuard clients = LAN access
services24

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

architecture decisionswhy things are configured the way they are7

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