No description
  • Python 64.6%
  • Shell 28.9%
  • Jinja 6.5%
Find a file
2026-08-26 16:50:52 +02:00
ansible added dns firewall aconfig to ansible 2026-08-06 17:31:50 +02:00
apps increase sure memory limit 2026-08-26 16:50:52 +02:00
argocd deploy media 2026-06-23 11:25:16 +02:00
runbooks node exporter config 2026-08-04 14:07:11 +02:00
scripts update Readme 2026-08-13 17:53:28 +02:00
.gitignore ansible stuff and repalce adguard with technitium 2026-08-04 09:37:00 +02:00
README.md update Readme 2026-08-13 17:53:28 +02:00

Homelab

GitOps-managed Kubernetes homelab powered by ArgoCD, provisioned with Ansible.

Quick Start

From bare metal

# One-command bootstrap: prepare nodes, install k3s, deploy ArgoCD
ansible-playbook ansible/install-all.yml

See ansible/README.md for full details on playbooks, roles, and ordering.

From an existing cluster

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

# 2. Wait for ArgoCD to be ready
kubectl wait -n argocd --for=condition=Ready pods --all --timeout=5m

# 3. Apply the root app
kubectl apply -f argocd/root-app.yaml

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

That's it. The root app watches the argocd/ directory, which deploys three category-level apps (infra, media, productivity), which in turn deploy all individual services. Everything syncs automatically — push to main and ArgoCD applies it.

Access Services

All services are exposed at {name}.example.lab (internal) or {name}.example.cloud (external via Cloudflare) via Traefik. Add *.example.lab to your DNS (Pi-hole, router, or /etc/hosts pointing to your cluster's ingress IP).

Repository Layout

argocd/                          # Root app watches here
  root-app.yaml                  # Bootstrap: applied once via kubectl
  infra.yaml                     # Deploys apps/infra/
  media.yaml                     # Deploys apps/media/
  productivity.yaml              # Deploys apps/productivity/
apps/
  infra/                         # Infrastructure: Traefik, cert-manager, Technitium, etc.
  media/                         # Media: Jellyfin, Immich, *arr stack, etc.
  productivity/                  # Productivity: Nextcloud, Forgejo, n8n, Synapse, etc.
scripts/                         # Utility scripts (config backups, etc.)

Active Services

Category Service Hostname Status
Infra Traefik (ingress) — ✅
cert-manager — ✅
sealed-secrets — ✅
MetalLB — ✅
Technitium DNS technitium.example.lab ✅
Authentik authentik.example.cloud ✅
Prometheus — ✅
Loki — ✅
Grafana grafana.example.internal ✅
Longhorn storage.example.internal ✅
RustFS (S3) — ✅
Home Assistant ha.example.cloud ✅
ArgoCD argocd.example.internal ✅
Media Jellyfin jellyfin.example.cloud ✅
Immich photos.example.cloud ✅
Audiobookshelf audiobooks.example.cloud ✅
Navidrome music.example.cloud ✅
Komga books.example.cloud ✅
Seerr seerr.example.cloud ✅
Sonarr sonarr.example.lab ✅
Radarr radarr.example.lab ✅
Lidarr lidarr.example.lab ✅
Readarr readarr.example.lab ✅
Bazarr bazarr.example.lab ✅
Prowlarr prowlarr.example.lab ✅
Gluetun (VPN) — ✅
BookBounty bookbounty.example.lab ✅
Productivity Nextcloud nextcloud.example.cloud ✅
Ollama ollama.example.cloud ✅
Open WebUI ai.example.cloud ✅
Outline wiki wiki.example.cloud ✅
Homarr dashboard homarr.example.cloud ✅
Sure (finance) finance.example.cloud ✅
Forgejo (Git) git.example.cloud ✅
n8n automation n8n.example.lab ✅
Synapse (Matrix) element.example.cloud ✅
SearXNG search search.example.cloud ✅

Storage

  • NFS Media (nfs-media StorageClass): Static NFS PVs backed by a Synology NAS. Each app gets its own PV/PVC pair for the media mount at /data.
  • Synology CSI (synology-*-* StorageClasses): ISCSI and SMB volumes provisioned on demand from the Synology NAS, with Retain reclaim policy.
  • Longhorn (longhorn — default for config PVCs): Replicated block storage across both nodes (2 replicas). All app config/data PVCs use this class — survives pod reschedules and ArgoCD redeploys.

Secrets

Secrets use sealed-secrets. Encrypted SealedSecret manifests live alongside each app. They're decrypted automatically by the sealed-secrets controller at sync time.

Notes

  • The control node may need taints removed to run workloads: kubectl taint nodes --all node-role.kubernetes.io/control-plane-
  • Config PVCs use Longhorn with 2 replicas, so data persists across redeploys. For migration-level backups, see scripts/backup-*-configs.sh or scripts/authentik-migrate.py.
  • NFS-backed media mounts are stateless from the cluster's perspective — the Synology owns the data.