A hybrid homelab managed entirely through GitOps β Docker Compose stacks on a NAS for media workloads, and a 3-node RKE2 Kubernetes cluster for platform services. A separate lab tier (Nutanix on an R620, Proxmox on an XPS) hosts AAP, a TFE agent, and other enterprise tooling for skills prep β kept outside the GitOps loop because it's expected to be temporary.
| Device | Role | CPU | RAM | Storage | OS |
|---|---|---|---|---|---|
| UGREEN DXP6800 Pro | NAS + Docker host | Intel i5-1235U | 40GB | 53TB | TrueNAS SCALE |
| Intel NUC #1 | RKE2 worker | Intel Core i5-8259U | 32GB | 500GB | Elemental OS |
| Intel NUC #2 | RKE2 worker | Intel Core i7-8559U | 32GB | 250GB | Elemental OS |
| Intel NUC #3 | RKE2 worker | Intel Core i7-8559U | 32GB | 250GB | Elemental OS |
| Device | Role | CPU | RAM | Storage | OS |
|---|---|---|---|---|---|
| Dell PowerEdge R620 | Nutanix CE host (AHV + CVM) | 2x Xeon | 128GB | Mixed SSD/HDD | Nutanix CE (AHV) |
| Dell XPS 15 9510 | Proxmox host (AAP + TFE agent VMs) | Intel Core (11th gen) | 32GB | 1TB SSD | Proxmox VE |
homelab/
βββ .github/workflows/ # CI/CD β linting, Flux diff, NAS deploy
βββ docs/ # Architecture decisions, runbooks
β βββ adr.md # Architecture Decision Records
β βββ bootstrap.md # Cluster bootstrap procedure
β βββ naming-and-ips.md # Hostnames, VLANs, IP allocations
β βββ disaster-recovery.md # Backup strategy, restore procedures
β
βββ docker/ # NAS Docker Compose stacks (deployed via nas-deploy workflow)
β βββ ansible/ # Ansible playbook and inventory for stack bring-up
β βββ openbao/ # Example stack
β β βββ docker-compose.yaml
β β βββ .env.sops # SOPS-encrypted env vars (decrypted at deploy time)
β β βββ config/ # Optional: stack config files
β β βββ openbao.hcl # synced to /volume3/docker_config/<stack>/
β βββ <stack>/ # Compose + env sync to /volume3/docker_compose/<stack>/
β
βββ clusters/
βββ hlcl1/ # RKE2 cluster (Flux CD managed)
βββ flux-system/ # Flux bootstrap
βββ kustomization.yaml # Cluster entrypoint
βββ vars/ # Cluster-specific values (IPs, domains)
β βββ cluster-config.yaml
βββ infra/ # Foundational platform components
β βββ network/
β β βββ metallb/
β β βββ ks-chart.yaml # Flux Kustomization: Helm chart
β β βββ ks-config.yaml # Flux Kustomization: IP pool config (dependsOn chart)
β β βββ chart/ # Namespace, HelmRepository, HelmRelease
β β βββ config/ # IPAddressPool, L2Advertisement
β βββ storage/
β β βββ longhorn/
β β βββ nfs/
β βββ traefik/
β βββ cert-manager/
β βββ external-dns/
βββ apps/ # Cluster applications
βββ pihole/
βββ monitoring/
Media workloads (Plex, Sonarr, Radarr, DL) stay on the NAS as Docker Compose stacks because they need local filesystem access for hardlinks (no storage duplication), QuickSync hardware transcoding, and direct disk I/O. Kubernetes adds complexity without benefit here.
Platform services (DNS, monitoring, ingress, secrets management) run on the RKE2 cluster where they benefit from orchestration, self-healing, and LoadBalancer IPs.
See ADR-005 for the full rationale.
See setup-guide.md, for the full bootstrap procedure. (TODO: Add setup-guide.md)
- Architecture β service map, data flows, storage topology
- TODO: Write setupguide.md
- Networking β VLANs, DNS, IP allocations
- Disaster Recovery β backup strategy, restore procedures