Skip to content

Homelab GitOps starter

A platform, not a distro and not an app store.

You get a Kubernetes cluster whose day-2 life is Git: Argo CD watches this repository, syncs Applications in waves, and you add workloads later. The cluster still depends on things outside Kubernetes — DNS, a CA, object storage, maybe NFS. Those are documented here so they are not a surprise.

GitHub: jslay88/homelab-gitops-starter

Who this is for

Someone standing up a homelab cluster (Talos VMs on Unraid or Proxmox) who wants the same kind of platform that a long-lived GitOps lab uses: MetalLB, ingress, cert-manager, Longhorn, sealed-secrets, optional Postgres operator and backups.

It is not a dump of someone else's live lab. There are no real IPs, no SealedSecrets, and no workload charts.

How to use it

  1. Fill in the inventory on paper or in a notes file.
  2. Use this template → new repo, private. Do not fork: a fork of a public repo stays public and stays linked. Replace YOUR_GITHUB, CHANGEME, and example.com in master-application.yaml and applications/. Private Git: create the Argo repo-creds Secret before the App of Apps (bootstrap). Wave 2 only seals that Secret into Git later.
  3. Read local DNS and Step-CA before you pick hostnames. The cluster cannot invent a LAN nameserver or a private CA.
  4. Pick addresses (reserved CP / worker / VIP blocks; cluster name homelab). Three control planes plus a Talos API VIP at .20 so kubectl has one IP that survives a CP reboot. Build Talos under ~/talos/homelab on Unraid or Proxmox, then bootstrap Argo CD.
  5. Walk waves 0–9, then observability (wave 10) or delete applications/kube-prometheus-stack.yaml. Delete Application files you do not want. Stop at each Validation block — the next wave will not paper over a failed check. Upstream docs for every pin: versions.
  6. First app: one whoami Ingress + Step-CA cert so you know DNS and TLS work.
  7. Talos day-2 when you upgrade or add a node. Backups when MinIO exists. Chart bumps when you change a pin.
  8. An AI assistant can use kubectl or a Kubernetes MCP server against this repo and the cluster. Git still owns apply.

What GitOps means here

helm install argocd   (once)
master-application.yaml  ──►  applications/*.yaml
                         Helm charts + values/ manifests

After the first apply, you do not helm upgrade platform charts by hand. You change Git; Argo syncs.

We use App of Apps (one YAML file per Application), not ApplicationSet. Homelab platform apps are few and different from each other — Helm-only, raw manifests, extra ignoreDifferences. A shared generator fights that.

Two Applications are chart + raw manifests in one object (MetalLB pools, StepClusterIssuer). The rest are chart-only or YAML-only. Breakdown: Application sources.

Two kinds of hostname

Kind Example DNS Certificate
LAN only grafana.k8s.home.example.com Your BIND / router (DNS) Step-CA
Public app.k8s.example.com Public DNS Let's Encrypt
Public, path only argocd.example.com/api/webhook Public DNS Let's Encrypt — UI stays on the LAN (wave 7)

If you skip both BIND and Step-CA, you can still reach apps by IP or by /etc/hosts, with browser warnings. That is a worse lab.

UIs that already run on the LAN (NAS, router, a Pi) use the same Ingress and the same two cert paths. The backend is a Service plus an EndpointSlice, not a Pod.

Out of scope

Workloads. Identity products. Ad-blocking DNS as a cluster component (Pi-hole can sit in front of BIND later). A descheduler. Multi-instance Postgres HA. Cilium. Those are left out on purpose.

Docs wrong or a step that cannot work as written: Get help (open a GitHub issue). Changes to the public starter: Contributing.