A Practical Homelab: Self-Hosting and DevOps on a Small Cluster

A Practical Homelab: Self-Hosting and DevOps on a Small Cluster

If you’re reading this, you probably have a closet full of old servers, a fondness for automation, and a stubborn belief that the best tooling is the stuff you run yourself rather than the cloud. The flashy “one-click” stacks are seductive, but in a homelab they’re often brittle, expensive to scale, and hard to audit offline. The real superpower is boring reliability: predictable backups, sane security, gradual upgrades, and a workflow that doesn’t crash when your internet goes out for a weekend.

In this article I’ll lay out a practical, opinionated plan to build a self-hosted DevOps and automation stack in a modest homelab. It’s deliberately lean, easy to operate, and designed to grow as you prove the value of automation. You’ll come away with a workable Kubernetes-based stack, GitOps to keep everything in check, a lightweight CI/CD that runs offline if needed, and concrete steps you can copy-paste into your environment.

Hook: why you should care about boring, boring-strong automation

The bottleneck in most homelabs isn’t the feature set; it’s the day-to-day operations that eat your time. You want a stack that you can maintain without constant firefighting: gradual upgrades, predictable outages, clear rollback paths, and a single source of truth for your deployments. A boring, well-laid-out stack does that by design. It’s not sexy, but it’s the kind of thing you can rely on for years.

1) The core philosophy: boring, scalable, and observable

  • Start with a small, reliable Kubernetes cluster (k3s) that you can run on 2–3 nodes. If you’re just starting, a single RM or a couple of beefy VMs will do; the goal is to prove out the pattern, not to pretend you’re replacing cloud providers.
  • Use GitOps as your deployment engine. The cluster is managed by code in Git, and all changes flow through Argo CD (or Flux). This gives you a clear, auditable history and a sane rollback story.
  • Add a lightweight CI/CD that runs pipelines inside the cluster and uses your own runners for sensitive operations.
  • Use local storage or lightly managed storage (Longhorn) for persistent workloads, with backups to a safe external location (restic + Velero).
  • Harden the stack layer-by-layer: TLS with cert-manager, secrets via sealed secrets, and defensive networking (firewalls, VPNs, least privilege).

2) The practical stack (what to install and why)

  • Kubernetes layer: K3s (a slim, easy-to-operate Kubernetes distribution)
  • Pros: small footprint, simple install, good for homelabs.
  • Cons: a bit opinionated; keep your node count modest to avoid operational debt.
  • Storage and networking
  • Longhorn for dynamic volumes (easy to manage in K3s)
  • MetalLB for load balancing on bare metal or private networks
  • Ingress and TLS
  • Traefik as the Ingress controller (or stick with the built-in Traefik that ships with K3s)
  • cert-manager to automate TLS certificates (Let’s Encrypt in normal operation)
  • GitOps and cluster management
  • Argo CD (in-cluster) for GitOps
  • Sealed Secrets (Bitnami) to protect Kubernetes secrets in Git
  • CI/CD and automation
  • Drone CI (self-hosted) or a lightweight alternative like a GitHub Runner if you prefer GitHub Actions flavor
  • Optional: a small, self-hosted CI runner for sensitive steps
  • Observability and backups
  • Prometheus + Grafana for metrics
  • Loki for logs (optional but nice)
  • Velero for backups; Restic for file-level backups
  • Identity and access (optional, but nice)
  • Lightweight OAuth/OIDC proxy if you want SSO for Argo CD and dashboards
  • Pi-hole for local DNS/ad-blocking (helps with privacy and home network hygiene)

3) High-level topology

  • The cluster runs on 2–3 nodes (one as control plane, others as workers). If you’re starting small, a single server cluster that you intend to scale is fine.
  • Ingress sits in front of services; Traefik handles TLS via cert-manager.
  • Argo CD talks to Git repositories to apply manifests to the cluster.
  • A separate backup path (Velero to an NFS share or object store) keeps data safe.
  • CI/CD runs inside the cluster with an agent that executes pipelines against your own registry and environment.

4) Getting started: a concrete blueprint you can actually implement

Prerequisites

  • A couple of nodes (bare metal or VMs) with Debian/Ubuntu LTS
  • Static IPs or a predictable DHCP reservation
  • A domain you control (for TLS, subdomains)
  • Basic familiarity with kubectl and Manifests

Step 1: Prepare the cluster

  • Install k3s on the first node (server)
  • curl -sfL https://get.k3s.io | sh -
  • Note the token: cat /var/lib/rancher/k3s/server/node-token
  • Ensure you can reach the API: export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
  • Install k3s agent on additional nodes
  • On each worker: curl -sfL https://get.k3s.io | K3S_URL="https://<server-ip>:6443" K3S_TOKEN="<token>" sh -
  • Confirm cluster is healthy
  • kubectl get nodes
  • kubectl get pods --all-namespaces

Step 2: Storage and networking

  • Install Longhorn for dynamic storage
  • kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/v1.3.0/deploy/longhorn.yaml
  • Wait for the UI to come up; ensure that default StorageClass is Longhorn
  • Install MetalLB (layer-2) for service exposure if you’re on private networks
  • apply manifests from the MetalLB project; configure a pool of IPs that you own
  • Confirm you can create a PersistentVolumeClaim and get a PV

Step 3: Ingress and TLS

  • If you’re using the built-in Traefik with K3s, verify it’s running
  • kubectl -n kube-system get pods | grep traefik
  • Install cert-manager
  • kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.yaml
  • Wait for cert-manager to be ready
  • Create an Issuer or ClusterIssuer for Let’s Encrypt
  • Example manifest (ClusterIssuer) for Let’s Encrypt staging first, then production
  • Apply and validate
  • Enable a sample ingress with TLS (you’ll switch to your real domain)
  • Use a simple app (e.g., whoami) to test
  • Ensure TLS certificates are issued and renew automatically

Step 4: GitOps with Argo CD

  • Install Argo CD
  • kubectl create namespace argocd
  • kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
  • Expose the Argo CD API with a safe method (port-forward is fine for initial setup)
  • kubectl port-forward svc/argocd-server -n argocd 8080:443
  • Connect Argo CD to a Git repository
  • Create a project, repository, and applications that point to your manifests
  • Define a small sample application