April 5, 2026

Building a Kubernetes Home Lab with GitOps

From bare metal to production-grade self-hosted infrastructure

Why Kubernetes at Home?

I wanted to run real workloads at home - not just Docker Compose. Prometheus, Grafana, Pi-hole, home automation - these need orchestration, not just containers running ad-hoc.

So I built a 5-node kubeadm cluster on AlmaLinux with full GitOps. Everything deploys from Git. When I push to main, ArgoCD makes it happen. No manually running kubectl apply.

The Hardware

Current Cluster:

  • 1 Master Node - 4 cores, 8GB RAM, 120GB SSD
  • 4 Worker Nodes - Mix of 2-4 cores, 4-8GB RAM each
  • Total - ~32GB RAM, 20+ vCPU across the cluster
  • Network - 10.0.0.0/24 flat network

Architecture Overview

The cluster follows the GitOps pattern using ArgoCD and Helm.

  • ArgoCD watches this Git repo and deploys automatically
  • Helm charts define all applications
  • cert-manager handles TLS with Cloudflare DNS-01
  • MetalLB provides load balancing
  • NGINX Ingress routes external traffic
  • Prometheus + Grafana monitor everything

When I add a new app, I push a Helm chart and enable it in config. ArgoCD syncs automatically.

Step 1: Initialize the Master

Start with one node that will become the master. All nodes run AlmaLinux 10.0.

# Disable swap (REQUIRED for k8s)
swapoff -a
sed -i '/ swap / s/^/#/' /etc/fstab

# Load kernel modules
modprobe overlay
modprobe br_netfilter

# Configure sysctl
cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF
sysctl --system

# Install containerd
dnf install -y containerd.io
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
systemctl enable --now containerd

# Install k8s repo and components
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.33/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.33/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
EOF

dnf install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
systemctl enable --now kubelet

Step 2: Initialize Kubernetes

Initialize the cluster with kubeadm. This creates the control plane.

# Initialize (use your node IP)
kubeadm init --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12

# Set up kubeconfig for your user
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# Install flannel (or calico, or weave)
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

Wait for everything to be Ready. Run kubectl get nodes to verify.

Step 3: Join Worker Nodes

Generate a join token on the master. Run this on each worker:

# On master, generate token (valid 24h)
kubeadm token create --print-join-command

# On worker, run the output (looks like):
kubeadm join 10.0.0.219:6443 --token xxxxxx --discovery-token-ca-cert-hash sha256:xxxxxx

After joining, approve the CSRs on master:

# Check and approve
kubectl get csr
kubectl approve <node-name>

Step 4: Install Infrastructure

Once nodes are ready, install the basics. I use a bootstrap script but here's the manual way:

  • ArgoCD - The GitOps controller
  • MetalLB - Load balancer for bare metal
  • NGINX Ingress - HTTP routing
  • cert-manager - TLS certificates
  • local-path-provisioner - Storage (PVCs)

My cluster uses kubeadm on AlmaLinux 10.0 with Kubernetes v1.33.

Step 5: Set Up GitOps

Install ArgoCD and point it at your Git repo. The repo contains all Helm charts and configs.

# Install ArgoCD
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v3.3.3/manifests/install.yaml

# Get the admin password
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

# Add your repo (in ArgoCD UI or CLI)
argocd repo add https://github.com/your-org/k8s-playground-cluster --username your-user

Then create an Application in ArgoCD that watches your repo. When you push, ArgoCD syncs automatically.

Applications Running

  • Prometheus + Grafana - Metrics and dashboards
  • Loki - Log aggregation
  • Pi-hole - Network-wide ad blocking
  • Istio - Service mesh
  • Gatekeeper - Policy enforcement
  • Sealed Secrets - Encrypted secrets in Git
  • SNMP Exporter - For router monitoring

How to Deploy a New App

With GitOps, adding a new app takes 3 steps:

  1. Create a Helm chart in charts/
  2. Enable it in cluster/dev/config.yaml
  3. Push to main - ArgoCD deploys automatically

No kubectl apply needed. No manual steps. The repo is the source of truth.

Questions? Reach out!