[ CORRUPTED_GLITCH // TRANSMISSION_devops-home-lab ]

DATE ......

READ_TIME . 3 MIN

WORDS ..... 594

CHANNEL ... DEVOPS / TECHNOLOGY

REVISED ...

The DevOps Home Lab: A Production Mindset on a Power Strip

How to build a home lab that actually teaches DevOps: hardware tiers, a Kubernetes-on-Proxmox stack, GitOps from day one, and the mistakes that waste your first six months.

A home lab is only useful if it teaches you habits that transfer to production. A pile of Raspberry Pis running hand-configured containers teaches you how to hand-configure containers. This guide builds the opposite: a small estate you operate like an SRE, because the operating model — not the hardware — is the thing you’re practicing.

#Pick Your Hardware Tier

TierKit~CostPower drawGood for
Scrappy3× used mini-PC (i5, 16GB)$450~45WK8s cluster, CI, DNS
Committed1× used server (64GB, 8c) + mini-PC$700~110WProxmox, VMs + K8s nested
UnhingedRack, UPS, 10GbE switch, 3 nodes$2,500+300W+Ceph, VLANs, envy

Buy used business mini-PCs (ThinkCentre Tiny, EliteDesk Mini). They’re quiet, sip power, and three of them beat one big box because failure domains are the curriculum — you can’t practice node failure with one node.

#The Stack

Proxmox VE (hypervisor)
 ├── VM: opnsense          # routing, VLANs, DNS
 ├── VM: k8s-cp-{1..3}     # control plane (Talos Linux)
 ├── VM: k8s-worker-{1..3} # workers
 └── VM: nas               # TrueNAS or plain ZFS + NFS
Layered on Kubernetes:
 ├── Flux CD               # GitOps engine — everything below is a git commit
 ├── cert-manager + traefik
 ├── monitoring: Prometheus + Grafana + Loki
 └── workloads: Gitea, Renovate, whatever you self-host

Talos Linux for the Kubernetes nodes is the sleeper pick: no SSH, no package manager, API-only configuration. It forces you to treat nodes as cattle because you literally cannot pet them.

#GitOps From Day One

The single most important rule: nothing gets kubectl apply’d by hand. Bootstrap Flux against a Git repo and let it own the cluster:

flux bootstrap gitea \
  --owner=lab --repository=cluster \
  --branch=main --path=clusters/home
# clusters/home/apps/gitea/release.yml
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata: { name: gitea, namespace: gitea }
spec:
  interval: 30m
  chart:
    spec: { chart: gitea, version: "10.x", sourceRef: { kind: HelmRepository, name: gitea-charts } }
  values:
    persistence: { storageClass: nfs-ssd, size: 20Gi }

Now every change has a diff, a history, and a revert. When you break DNS at 11pm (you will), git revert is your incident response.

#Practice Like It’s Production

The lab earns its power bill when you run it with production ceremony:

  • Monitoring before workloads. Install Prometheus first, then apps. Alert on disk fill, cert expiry, node down — to your actual phone.
  • Break things on a schedule. Monthly chaos night: pull a node’s power mid-deploy, kill the NFS server, expire a cert. Write a postmortem each time, even though the only stakeholder is your dog.
  • Backups you’ve actually restored. Velero to an S3 bucket (or MinIO on the NAS), and a quarterly restore drill to a scratch namespace. A backup you’ve never restored is a hope, not a backup.
  • Renovate for upgrades. Let it PR chart/image bumps; you review and merge. This is the exact loop you’ll run at work.

#The Mistakes That Waste Six Months

  1. Buying hardware before defining workloads. The rack is not the hobby. (It becomes the hobby. Fight it.)
  2. One giant Docker host. Comfortable, and teaches you nothing after week two.
  3. Skipping the network layer. VLANs, DNS, and a real firewall are 40% of the transferable skill.
  4. Hosting the family’s stuff on the chaos cluster. The moment your partner’s photo backup runs on it, you can’t break it anymore — and breaking it was the point. Run “prod-home” separately, or accept your lab is now production with an SLA enforced at dinner.

Total damage for the committed tier: about $700 and a weekend to bootstrap. What you’re really buying is a place where the blast radius is zero and the lessons are real.

[ RELATED_SIGNALS ]