GitOps-driven homelab. Self-hosted. Automated. Encrypted.
This repository is the single source of truth for my homelab — a fully GitOps-driven setup where every change is version-controlled and automatically applied:
- Kubernetes workloads — managed by ArgoCD via GitOps
- Node provisioning — handled by Ansible
- External infrastructure — Cloudflare DNS, tunnels, and more via Terraform
- Secrets — encrypted with SOPS, never committed in plaintext
Ansible handles node provisioning and cluster lifecycle management — k3s installation and upgrades, OS configuration, Tailscale enrollment, and ongoing maintenance across all nodes. Uses uv for dependency management.
uv sync --all-groups
uv run ansible-playbook ansible/playbooks/k3s-cluster.ymlTerraform manages external infrastructure-as-code (IaC). The cloudflare module covers DNS records, Cloudflare Tunnel, WAF rules, and zone settings across two domains.
cd terraform/cloudflare
terraform init -backend-config=../.decrypted~backend.sops.tfbackend
terraform plan
terraform apply -auto-aproveAll apps are declared as ArgoCD Application manifests under kubernetes/apps/addons/argocd-apps/templates/. Pushing to master is enough — ArgoCD detects drift and syncs automatically. To add a new app, drop a values file and an Application manifest, then push.
Ad-hoc Kubernetes resources that don't belong to a specific app (CRDs, cluster-wide config) live as Helm charts under kubernetes/charts/.
A fresh cluster is bootstrapped with Helmfile via the bootstrap Ansible tag. Helmfile installs the SOPS GPG key secret, the GitHub deploy key, ArgoCD, and the root argocd-apps Application — in dependency order. After that, ArgoCD self-manages via the App of Apps pattern.
uv run ansible-playbook ansible/playbooks/k3s-cluster.yml --tags bootstrapSee the bootstrap runbook for the full procedure.
All secrets are SOPS-encrypted (.sops.yaml) and never committed in plaintext. Ansible, Terraform, and ArgoCD each decrypt on the fly at runtime — no manual steps required.
| Tool | Secrets location |
|---|---|
| Ansible | ansible/inventory/hosts_secrets.sops.yaml |
| Terraform | secrets.sops.yaml per module |
| Kubernetes | values.sops.yaml alongside plain values.yaml |
Copyright © 2026 Afonso Costa
Licensed under the MIT License. See the LICENSE file for details.