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.