The Practical Homelab: Self-Hosting Your DevOps Stack

The Practical Homelab: Self-Hosting Your DevOps Stack

If you’re reading this, you’ve likely got a dashboard full of SaaS services you don’t truly own, and a growing pile of notes about how you’d move work back in-house if you had the time. The reality is you do have the time—you just need a sane plan, not a dream of a perfect, zero-friction cloud. A practical homelab is not about recreating every cloud service on your desk; it’s about building a focused, maintainable automation stack that you actually use, and that doesn’t require you to babysit it constantly. This article is my practical, opinionated blueprint for a lean self-hosted DevOps stack you can actually operate in real life.

Hook: the feeling you get when your pipeline deploys to production at 2 a.m. and your phone doesn’t ping you with a thousand errors because you built the system to fail gracefully, not spectacularly.

What you’re building, in plain terms

  • A small, reliable Kubernetes cluster (or a near-Kubernetes experience) running on a home hypervisor.
  • A Git hosting service you own (code, pipelines, and secrets included).
  • A lightweight CI/CD system that runs your pipelines without eating your weekend.
  • A private container registry, TLS everywhere, and a sane ingress path.
  • A VPN-first remote access story so you can work from anywhere without exposing everything to the internet.
  • Observability and backups so you catch breakages before your users do.

A note on scope and reality

This isn’t a “single click” setup; it’s a plan you implement iteratively. The goal is not to recreate every cloud feature but to deliver a reproducible workflow, from code commit to production, that you can own. Start simple, scale pragmatically, and invest in automation and backups early.

Hardware, virtualization, and the base stack

Choose a physical host that can handle the workload with some headroom. Two to four cores, 16–32 GB RAM, and 2–4 TB of respectable storage is a good starting point for a small homelab, letting you run a couple of VMs or lightweight containers with room to spare. If you’re on a tight budget, a single beefy NAS/mini-servers can work, but plan to migrate to virtualization to isolate workloads later.

Virtualization choice: Proxmox VE or similar

  • Proxmox VE is my default recommendation for homelabs. It’s solid, has built-in clustering features, and plays well with both containers (LXC) and full VMs.
  • Use LXC for lightweight services (Gitea, Drone, small registries) and VMs for heavier control-plane components or your Kubernetes nodes if you’re running a multi-node cluster.

Basic software stack (concrete starting point)

  • Hypervisor: Proxmox VE
  • OS inside VMs/containers: Ubuntu Server 22.04 LTS (or Debian if you prefer)
  • Kubernetes: k3s (lightweight, easy to manage; single-node is fine to start)
  • Ingress: Traefik or Caddy (Caddy is nice for its automatic TLS; Traefik is a good Kubernetes-native choice)
  • Git hosting: Gitea (self-hosted Git service)
  • CI/CD: Drone CI (lightweight, Docker-native) or GitLab Community Edition if you want a full suite (but heavier)
  • Container registry: Harbor (for features) or a simple Docker Registry v2
  • VPN: WireGuard
  • Monitoring: Prometheus + Grafana
  • Logging: Loki + Promtail + Grafana (optional but very useful)
  • Secrets (local dev): Mozilla SOPS with age or GPG, or Vault if you’re comfortable managing it

Why I like this mix

  • It’s modular and replaceable. If Drone becomes flaky, you can swap in another small CI runner without tearing down your cluster.
  • It keeps the control surface small. Kubernetes is a tool, not a goal; k3s lowers the barrier to entry and reduces operational risk.
  • TLS and security are baked in from day one with TLS termination at the ingress layer and VPN access for remote work.

Getting from zero to first pilot: a practical plan

Phase 1 — Foundations (hardware, virtualization, baseline services)

  • Install Proxmox VE on the hardware. Create two to three VMs or LXC containers:
  • A control-plane node (or a single-node k3s setup)
  • A worker node (optional if you’re starting with single-node)
  • A storage/backup node (optional but recommended)
  • Install Ubuntu Server 22.04 on the VMs or containers.
  • Set up SSH keys, disable password login, and harden the host (unattended upgrades, basic firewall).

Phase 2 — The cluster and ingress

  • Install k3s on the control plane; join worker nodes if you’ve got them.
  • Install an ingress controller (Traefik or Nginx) inside the cluster; enable TLS via Let’s Encrypt with cert-manager or a simple TLS cert for non-production.
  • Prepare a persistent storage strategy for Kubernetes (local path provisioner is fine for a start; consider NFS or Longhorn if you want more dynamic storage).

Phase 3 — Core services (Gitea, CI, registry)

  • Deploy Gitea as a Helm chart or a simple manifest; set up repositories for your code, and enable hooks to trigger pipelines.
  • Deploy Drone CI (Docker-based) or GitLab CE, depending on your appetite for maintenance and scale. If you’re starting small, go with Drone for its lean footprint.
  • Deploy a private Docker Registry or Harbor. Ensure persistent storage for images; set up access control and TLS.

Phase 4 — Observability, backups, and access

  • Install Prometheus and Grafana; add node exporters and kube-state-model exporters for visibility.
  • Install Loki + Promtail + Grafana if you want centralized logs; configure dashboards.
  • Set up a backup plan for every critical component: Gitea data, Drone data, registry data, and etcd data if applicable. Schedule automated backups to an external drive or offsite (or both).

Phase 5 — Security and remote access

  • Deploy WireGuard for remote access; optionally expose only a reverse proxy rather than individual services to the public internet.
  • Harden CI/CD and registries with role-based access, simple secrets management, and least privilege practices.

Phase 6 — Automation and IaC

  • Start with Ansible to codify configuration management for your hosts and services.
  • Add Terraform to describe your cluster or infra if you’re running on a VM-based homelab or migrating to a more cloud-like setup.
  • Use Packer to create repeatable VM images if you’re spinning new nodes often.

A concrete, minimal deployment path you can copy

1) Proxmox VE setup on your hardware; create 2 VMs:

  • vm-k3s-control: 2 cores, 4-8 GB RAM (expand later)
  • vm-k3s-worker: 2 cores, 4-8 GB RAM

2) OS install: Ubuntu Server 22.04 LTS

3) Kubernetes layer: k3s on vm-k3s-control, with token to join vm-k3s-worker

4) Ingress: Traefik installed via Helm

5) Git hosting: Gitea deployed via Helm with a persistent volume

6) CI/CD: Drone CI installed with a docker runner; link to Gitea webhooks

7) Registry: Harbor or simple docker-registry with TLS

8) Monitoring: Prometheus + Grafana; dashboards for pipelines, deployments, and node health

9) VPN: WireGuard server on its own small VM or integrated into the Proxmox host

10) Backups: nightly rsync snapshots of volumes and a separate backup recipe for your Git repos and pipelines

A realistic example pipeline

  • Goal: push code to Gitea, run unit tests, build a container image, push to Harbor, and deploy to the cluster.
  • Tooling: Gitea webhooks trigger Drone CI; Drone runs tests, builds an image, signs it, pushes to Harbor; Traefik routes a new deployment to Kubernetes, which updates the Deployment resource and triggers a rolling restart.

Drone pipeline sketch (conceptual)

  • Steps: checkout, test, build-image, push-image, deploy
  • YAML (rough sketch):
  • name: default
  • kind: pipeline
  • steps:
  • name: test

image: golang:1.20

commands:

  • go test ./...
  • name: build

image: docker:24

commands:

  • docker build -t harbor.yourdomain.local/project/service:${DRONE_COMMIT} .
  • docker login harbor.yourdomain.local -u user -p pass
  • docker push harbor.yourdomain.local/project/service:${DRONE_COMMIT}
  • name: deploy

image: bitnami/kubectl:1.26

commands:

  • kubectl set image deployment/service service=harbor...:${DRONE_COMMIT} -n app

This is a starting point, not a gold standard. The exact details depend on your chosen tools, but the pattern holds: code and tests, image build, registry push, deployment update.

Operational realities and pitfalls to anticipate

  • Don’t over-engineer the cluster to start. A single node k3s is enough to prove the pattern; scale gradually as you validate retention, backup, and recovery.
  • Backups are non-negotiable. A backup is only as good as your ability to restore. Practice restores on a quarterly cadence.
  • Secrets management is often overlooked. If you can’t automate secret rotation or enforce least privilege, you’ll regret it later.
  • Network segmentation matters. Expose the minimum surface to the internet; prefer a single entry point with TLS and clean routing rules rather than a sprawling set of public endpoints.
  • Documentation beats memory. Maintain a simple runbook: what to do when services fail, how to scale, how to roll back, and how to restore from backup.
  • Updates will break things. Schedule maintenance windows and test upgrades in a staging environment before pushing to production.

Maintenance rituals you’ll actually keep

  • Weekly, spend 30 minutes reviewing backups, disk health, and node health. If something looks off, address it sooner rather than later.
  • Monthly, review pipeline performance. If pipelines start taking longer or fail more often, it’s likely a sign to scale or optimize the runner resources.
  • Quarterly, run a disaster-recovery drill. Spin up a fresh VM cluster, restore from backup, and verify that you can push a new release.

Security posture basics (non-negotiable)

  • SSH keys only, with a strict policy for rotation.
  • Firewall rules that allow inbound access only to the ingress host and VPN endpoint.
  • TLS everywhere with cert renewal automation.
  • Secrets stored in a dedicated secret store or encrypted with SOPS; never commit credentials to your repos.
  • Keep your base OS and cluster components patched; automate updates where feasible.

Examples from real life: what worked for me

  • The first homelab I built used a single Proxmox host with three VMs: management, k3s control, and a general workload node. It was enough to prove the concept: I could deploy code, run a pipeline, and host private services without punching through NAT for every service.
  • The second improvement was swapping manual backups for a dedicated backup plan: rsync nightly to an external drive, with a separate weekly offline backup on a USB drive stored offsite. It saved me when the main disk failed during a re-provision.
  • A third improvement was moving from a monolithic “one-click” cloud to a more modular CI/CD: switching from a heavy GitLab CE install to Gitea + Drone cut maintenance time in half and made upgrades less scary.

Actionable, short conclusion

  • Start small: set up Proxmox, spin up a single-node k3s, and deploy Gitea, Drone, and a minimal registry.
  • Automate the basics: automate backups and TLS provisioning from day one.
  • Harden progressively: add WireGuard VPN, tighten RBAC, and implement secret management as you grow.
  • Treat your homelab as a craft, not a hobby: document everything, practice restores, and keep a weekly maintenance ritual.

If you take one thing away, let it be this: build a repeatable pipeline that you actually use, not a project you abandon after one demonstration. Your future self will thank you when a release goes out smoothly, you can revert quickly, and you own the entire stack end-to-end.