Skip to content

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

Media Stack (servarr namespace)

Service URL Status
Sonarr sonarr.emilsturzenegger.ch 🟢
Radarr radarr.emilsturzenegger.ch 🟢
Prowlarr prowlarr.emilsturzenegger.ch 🟢
SABnzbd sabnzbd.emilsturzenegger.ch 🟢
Jellyfin jellyfin.emilsturzenegger.ch 🟢
Bazarr bazarr.emilsturzenegger.ch 🟢
Seerr seerr.emilsturzenegger.ch 🟢

Infrastructure Services

Service URL Status
Infisical secrets.emilsturzenegger.ch 🟢
Vikunja board.emilsturzenegger.ch 🟢
Home Assistant home-assistant.emilsturzenegger.ch 🟡 (on Talos)
UniFi unifi.emilsturzenegger.ch 🟡 (on Talos)
Vaultwarden bitwarden.emilsturzenegger.ch 🟡 (on Talos)
Node-RED node-red.emilsturzenegger.ch 🟡 (on Talos)
Zigbee2MQTT zigbee2mqtt.emilsturzenegger.ch 🟡 (on Talos)

Publishing & Docs

Service URL Status
Pipeline Outputs outputs.emilsturzenegger.ch 🟢
Wiki wiki.emilsturzenegger.ch 🟢

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