Lab Infrastructure
Complete documentation of Emil's homelab: hardware, network, Kubernetes clusters, services, and operational patterns.
Overview
The homelab runs on a single Proxmox host (lab-node01) with two Kubernetes clusters:
| Cluster |
Nodes |
Purpose |
Status |
| Talos |
3 CP + 3 workers |
Legacy cluster — services migrating to k3s |
🟡 Migrating |
| K3s |
3 nodes |
Active cluster — servarr stack running |
🟢 Active |
Network
| Subnet |
VLAN |
Purpose |
Gateway |
192.168.20.0/24 |
20 |
Infrastructure (agent, DNS, NAS, runner, secrets) |
192.168.20.1 |
192.168.30.0/24 |
30 |
Kubernetes & virtualization |
192.168.30.1 |
Key Hosts
| IP |
Hostname |
Role |
192.168.20.20 |
dns.bear.casa |
Technitium DNS |
192.168.20.21 |
nas.bear.casa |
Synology NAS |
192.168.20.31 |
— |
GitLab CI runner |
192.168.20.100 |
agent.bear.casa |
Hermes AI agent (LXC) |
192.168.20.151 |
— |
Infisical secrets |
192.168.30.104 |
— |
k3s VIP (kube-vip ARP) |
192.168.30.105-107 |
k3s-node-1/2/3 |
K3s cluster nodes |
192.168.30.201 |
lab-node01 |
Proxmox VE |
Proxmox
- Host:
lab-node01 at 192.168.30.201:8006
- API Token:
hermes@pve!hermes-token (Infisical prod)
- Storage:
data-nfs (NFS), data-ssd (local SSD), isos-nfs
- Bridge:
vmbr0 on VLAN 30
- VM IDs: k3s nodes at 110-112, template at 101
K3s Cluster
- Version:
v1.30.2+k3s1
- HA: Embedded etcd (3-node)
- VIP:
192.168.30.104 via kube-vip (ARP mode)
- Ingress: nginx-ingress on hostNetwork (ports 80/443 on node IPs)
- Storage: NFS-backed
nfs-client (default) + OpenEBS Local PV for config
- LoadBalancer: MetalLB (pool
192.168.30.160-240)
Installed Charts
| Chart |
Namespace |
Notes |
| ingress-nginx |
ingress-nginx |
HostNetwork bare-metal |
| nfs-subdir-external-provisioner |
nfs-provisioner |
Default StorageClass |
| cert-manager |
cert-manager |
Let's Encrypt (prod + staging) |
| MetalLB |
metallb-system |
FRR mode, L2 advertisement |
Services
Infrastructure Services
Publishing & Docs
Secrets Management
All secrets are stored in Infisical at secrets.emilsturzenegger.ch:
- Workspace:
homelab (slug: homelab-a-rye)
- Environments: dev, staging, prod
- Key secrets: Proxmox API tokens, GitLab PAT, Cloudflare credentials, Discord tokens, SSH passwords, API keys
- Auth: Universal Auth (client ID + client secret)
Access pattern:
# Login
curl -s -X POST "https://secrets.emilsturzenegger.ch/api/v1/auth/universal-auth/login" \
-H "Content-Type: application/json" \
-d '{"clientId":"...","clientSecret":"..."}' | jq -r '.accessToken'
# Get secrets
curl -s "https://secrets.emilsturzenegger.ch/api/v3/secrets/raw?workspaceSlug=homelab-a-rye&environment=prod" \
-H "Authorization: Bearer $TOKEN"
Git Repositories
| Repo |
URL |
Purpose |
| k3s-helm-deployments |
GitLab |
Helm values and deployment manifests |
| k3s-proxmox |
GitLab |
IaC: Terraform + Ansible for k3s |
| Wiki |
GitLab |
This wiki source |
| Hermes Workflow |
GitHub |
Multi-agent pipeline framework |
DNS
Technitium DNS at 192.168.20.20 (dns.bear.casa):
- API: Port 80,
Authorization: Bearer <token>
- Read:
GET /api/zones/list, GET /api/zones/records/get?domain=<zone>&listZone=true
- Write: POST
/api/zones/records/add (form-encoded, not JSON)
- Zones:
bear.casa, emilsturzenegger.ch, reverse zones for VLANs
- Token: In Infisical prod as
TECHNITIUM_TOKEN