This repository manages a personal homelab running on Kubernetes (K3s), using Helmfile to deploy services and Ansible to provision bare-metal nodes. Bootstrap secrets are encrypted with SOPS; runtime secrets are managed by OpenBao with the External Secrets Operator.
ArgoCD and OpenBao are provided as platform services for downstream application repositories built on top of this foundation β they do not manage this repository's own releases, which are deployed directly by Helmfile.
This project is the cornerstone of a homelab β it provides the base infrastructure (cluster, networking, monitoring, identity). If you want to deploy your own applications (a portfolio site, a blog, custom services, etc.), those should live in a separate repository and be deployed on top of this foundation. This keeps the infrastructure clean and your application deployments independent.
The homelab follows a layered architecture:
- Infrastructure Layer: K3s cluster provisioned with Ansible
- Platform Layer: Core services (MetalLB, Traefik, cert-manager) for networking and certificates
- Application Layer: Applications deployed via Helmfile (ArgoCD, Authentik, Grafana, etc.)
- Observability Layer: Monitoring (Prometheus), Logging (Loki), Tracing (Tempo), and Profiling (Pyroscope)
- Backup Layer: Cluster and PVC backups via Velero to Cloudflare R2
| Service | Purpose | Namespace | Grafana Dashboard |
|---|---|---|---|
| prometheus-operator-crds | Prometheus Operator CRDs | monitoring-system | β |
| cert-manager | SSL/TLS certificate management | cert-manager-system | β |
| cert-manager-config | Certificate configuration | cert-manager-system | β |
| external-dns | DNS management with Cloudflare | cert-manager-system | β External DNS |
| authentik-blueprints | Declarative provider/app/user provisioning | auth-system | β |
| longhorn | Distributed block storage | longhorn-system | β Longhorn |
| metallb | Load balancer for bare metal | lb-system | β MetalLB |
| metallb-config | MetalLB IP Address Pool and L2 Advertisement | lb-system | β |
| prometheus-stack | Monitoring and alerting | monitoring-system | β Kubernetes Cluster Β· Node Exporter Β· Kubernetes Pods |
| grafana | Metrics visualization | monitoring-system | β |
| loki | Log aggregation | monitoring-system | β Loki (chart-bundled) |
| alloy | OpenTelemetry collector (logs, traces, profiling) | monitoring-system | β |
| tempo | Distributed tracing | monitoring-system | β |
| pyroscope | Continuous profiling | monitoring-system | β |
| traefik | Reverse proxy and ingress | ingress-system | β Traefik |
| authentik | Identity provider | auth-system | β Authentik |
| argocd | GitOps continuous delivery | gitops-system | β ArgoCD Operations Β· Application Β· Notifications |
| authentik-ingress | Authentik ingress configuration | auth-system | β |
| openbao | Runtime secrets manager (Vault-compatible) | openbao-system | β Hashicorp Vault |
| external-secrets | Sync OpenBao secrets into Kubernetes Secrets | external-secrets-system | β |
| velero | Kubernetes backup and restore | velero-system | β |
Services with a web UI, reachable over Traefik + TLS. ROOT_URL is your
configured root_dns. Internal hosts resolve to the MetalLB load-balancer IP
and are only reachable on the LAN/VPN; External is the public-facing SSO
entry point.
| Access | URL | Service |
|---|---|---|
| External | https://auth.ROOT_URL |
Authentik (SSO / identity provider) |
| Internal | https://argocd.internal.ROOT_URL |
ArgoCD |
| Internal | https://grafana.internal.ROOT_URL |
Grafana |
| Internal | https://longhorn.internal.ROOT_URL |
Longhorn |
| Internal | https://openbao.internal.ROOT_URL |
OpenBao |
| Tool | Purpose |
|---|---|
| K3s | Lightweight Kubernetes distribution |
| Ansible | Cluster provisioning and configuration |
| Helmfile | Helm releases management |
| Helm | Kubernetes package manager |
| ArgoCD | GitOps continuous delivery |
| SOPS | Bootstrap secrets encryption |
| OpenBao | Runtime secrets manager (Vault-compatible) |
| External Secrets Operator | Sync OpenBao secrets into Kubernetes Secrets |
| Prometheus | Monitoring and alerting |
| Grafana | Metrics visualization |
| Loki | Log aggregation |
| Tempo | Distributed tracing |
| Pyroscope | Continuous profiling |
| Grafana Alloy | OpenTelemetry collector for logs, traces, and eBPF profiling |
| Longhorn | Cloud-native distributed block storage |
| MetalLB | Load balancer for bare metal Kubernetes |
| Traefik | Cloud-native reverse proxy |
| cert-manager | X.509 certificate management |
| external-dns | Synchronize exposed services with DNS providers |
| Authentik | Identity provider |
| Velero | Kubernetes backup and restore |
| Cloudflare R2 | S3-compatible object storage for backups |
| Terraform | Cloud infrastructure provisioning |
| Cloudflare | DNS and CDN provider |
| pre-commit | Git hooks for code quality |
| ansible-lint | Ansible playbook linting |
homelab/
βββ charts/ # Custom Helm charts
β βββ cert-manager-config/ # Certificate configuration
β βββ external-ingress/ # Ingress definitions
β βββ metallb-config/ # MetalLB configuration
βββ docs/ # Documentation
βββ helmfile/ # Helmfile configuration
β βββ common/ # Common values and templates
β β βββ values/ # Service values files
β βββ releases/ # Staged Helmfile release definitions
β β βββ 001-crds.helmfile.yaml.gotmpl
β β βββ 002-certs.helmfile.yaml.gotmpl
β β βββ 003-blueprints.helmfile.yaml.gotmpl
β β βββ 004-core-apps.helmfile.yaml.gotmpl
β β βββ 005-ingresses.helmfile.yaml.gotmpl
β βββ environments/ # Environment-specific configs
β β βββ dev/ # Development environment
β β β βββ secrets/ # Per-chart encrypted secrets
β β β βββ values/ # Per-chart value overrides
β β βββ prod/ # Production environment
β β βββ secrets/ # Per-chart encrypted secrets
β β βββ values/ # Per-chart value overrides
β βββ secret-templates/ # Secret templates with descriptions
β βββ locks/ # Helmfile lock files
βββ metal/ # Bare metal provisioning
β βββ k3s/ # K3s cluster setup with Ansible
βββ scripts/ # Automation scripts (lib, infra, helm, secrets, apps)
βββ tests/ # Shell BDD (shellspec) + Python integration tests
βββ terraform/ # Cloud infrastructure (Cloudflare R2, etc.)
βββ helmfile.yaml.gotmpl # Main Helmfile entry point
βββ ROADMAP.md # Project roadmap
βββ README.md # This file
Fork this repository to store your own configs and secrets. See docs/FORKING.md for setup.
See docs/INSTALL.md for the full setup guide, including prerequisites, helm plugins, credentials, and step-by-step deployment.
# Quick start
mise run setup # install tools, plugins, git hooks
mise run check # verify environment
cp helmfile/config.template.yaml helmfile/environments/<env>/config.yaml # configure
mise run secrets:init <env> # set up secrets
mise run provision # provision cluster
cp terraform/terraform.tfvars.example terraform/terraform.tfvars # configure Cloudflare
mise run install <env> # deploy services
mise run openbao:setup <env> # initialise OpenBao + ESOSee docs/CONFIG.md for all available settings and docs/SECRETS.md for secrets management.
The homelab includes a comprehensive monitoring stack:
- Prometheus: Metrics collection and alerting
- Grafana: Visualization and dashboards
- Loki: Log aggregation
- Tempo: Distributed tracing
- Pyroscope: Continuous profiling
- Grafana Alloy: OpenTelemetry collector for logs, traces, and eBPF profiling
Grafana is exposed via MetalLB LoadBalancer. Access it using the external IP assigned by MetalLB.
- Kubernetes Cluster
- Node Exporter
- Kubernetes Pods
- MetalLB
- Longhorn
- CoreDNS
- External DNS
- Authentik
- ArgoCD Operations
- ArgoCD Application
- ArgoCD Notifications
Velero runs in velero-system and takes daily scheduled backups of all namespaces and PVCs (via CSI snapshots), storing them in a Cloudflare R2 bucket.
The R2 bucket is provisioned via Terraform:
mise run tf:apply # creates the R2 bucketAfter applying, copy the outputs (velero_bucket_name, velero_s3_endpoint) into your environment config.yaml, then create the R2 API token manually in the Cloudflare dashboard and add it to the Velero SOPS secret.
- Roadmap β upcoming features and progress
- Testing β pre-commit hooks, shell BDD (shellspec), Gherkin acceptance tests (pytest-bdd), and Python integration tests
- Spec-Driven Development β the
/speckit-*flow, the project constitution, and when to write a spec - Configuration β config system reference and all available settings
- Installation β step-by-step setup guide
- Forking β how to fork and maintain your own configs and secrets
- Versioning β release scheme, what triggers a release, and Renovate automation
- Architecture Decisions β ADRs documenting significant infrastructure changes
- Scripts β automation script documentation and usage
- Secrets β full secrets reference with criticality levels
- OpenBao SSO β configure OIDC login to OpenBao via Authentik
See CONTRIBUTING.md. Meaningful work starts from a spec (see Spec-Driven Development), and every PR with a meaningful change must include an ADR.
This project is licensed under the MIT License - see the LICENSE file for details.
- K3s for the lightweight Kubernetes distribution
- Helmfile for Helm releases management
- ArgoCD for GitOps continuous delivery
- Grafana and the Grafana stack for observability
- Longhorn for cloud-native block storage
- MetalLB for bare metal load balancing
- Traefik for reverse proxy and ingress
- cert-manager for certificate management
- Authentik for identity management
- SOPS for secrets encryption
- Ansible for cluster provisioning
- Velero for Kubernetes backup and restore
- Terraform for cloud infrastructure provisioning
- Let's Encrypt for free TLS certificates
- Cloudflare for DNS, CDN, and R2 object storage
This project does not authorize the use of its code, documentation, or any associated materials for training artificial intelligence (AI) or machine learning (ML) models. Any use of this repository's content for AI/ML training purposes is strictly prohibited without explicit written permission from the project owner.