one house, one git repo, too many daemons
kubeadm on a mini PC · Argo CD · OpenTofu · Traefik · Authentik · a NAS that holds everything
stack · hardware · edge · apps · layout · operating it · roadmap · changelog
Public on purpose. Hostnames and the LAN map are not secrets. Credentials, *.env, *.tfvars, and Cloudflare state are.
Most of the lab runs on a single kubeadm node and is reconciled by Argo CD. OpenTofu owns the things Kubernetes should not: DNS rewrites, the router, Wi-Fi, identity apps, and Grafana Cloud.
internet
|
+--------------+--------------+
| | |
WAN WireGuard Cloudflare
| | |
+--------------+--------------+
|
+-------+------+------+-------+
| | | |
NAS Lake Vibe CloudVM
| |
+------+------+
|
Traefik
| layer | what | where |
|---|---|---|
| remote | WireGuard on the router, Tailscale if that path dies | terraform/routeros/wireguard.tf |
| compute | Proxmox VE, LXC | lake-1 (always), edge-1 (mostly off) |
| kubernetes | kubeadm, Flannel host-gw, Argo CD | kubernetes/ |
| edge | Traefik-k8s, CrowdSec, Authentik | kubernetes/traefik/ |
| identity | Authentik OAuth / SAML / LDAP | kubernetes/authentik/ + terraform/authentik/ |
| dns | AdGuard Home → RouterOS → 1.1.1.1 | kubernetes/adguard/ + terraform/adguard/ |
| wifi | UniFi U7 Lite, WLANs as code | kubernetes/unifi/ + terraform/unifi/ |
| router | MikroTik hAP ac3 | terraform/routeros/ |
| data | CloudNativePG + NAS | kubernetes/cloudnative-pg/ |
| secrets | 1Password → External Secrets | kubernetes/*/resources/externalsecret-*.yaml |
| monitoring | VictoriaMetrics, Grafana Cloud | kubernetes/monitoring/ + terraform/grafana/ |
| box | role | notes |
|---|---|---|
| lake-1 | always on | 🏠 Mini PC. Proxmox. The Kubernetes node. |
| vibe | Mac | 🤖 AI node. |
| edge-1 | experimental | 🧪 Dell PowerEdge R610. Usually off. |
| nas | storage | 💾 Synology DS220+. |
ISP is INEA, 1 Gbps synthetic FTTH. Router is a MikroTik. AP is a UniFi U7 Lite.
Remote access is WireGuard on the router. Tailscale if that path dies.
Three doors. Do not collapse them.
| path | what it is |
|---|---|
| WAN | 🔥 Public web, firewalled. Allowlist, then Traefik. |
| WireGuard | 🔒 VPN onto the LAN. |
| Cloudflare Tunnel | ☁️ WAF for some hosts. Separate path. |
Auth class per host is scripts/auth_classification.yaml: forward-auth, native-oidc, public, lan-only.
Argo CD parents everything under kubernetes/. A directory with values.yaml (repoURL / chart / version) becomes a Helm Application. No values.yaml means a hand-written Application in kubernetes/argocd/resources/.
| app | job |
|---|---|
| AdGuard Home | DNS. |
| Authentik | Identity. |
| Argo CD | This repo, applied to itself. |
| Calibre | Books. |
| CloudNativePG | Shared Postgres. |
| Gitea | Git. |
| Headlamp | Kubernetes UI. Admins only. |
| Home Assistant | Home, MQTT, Zigbee. |
| Homepage | The dashboard. |
| Mediabox | Jellyfin and the *arr stack. Downloads stay on a VPN. |
| n8n | Workflows. |
| NetBox | IPAM / DCIM. |
| Traefik | The edge. |
| UniFi | Wi-Fi controller. |
| WatchYourLAN | Who is on the LAN. |
| Wealthfolio | Personal finance. |
Portainer is gone. Apps run on Kubernetes. Databases live on CloudNativePG.
.
├── kubernetes/ Argo CD apps. This is the workload tree.
│ ├── argocd/ self-managed Argo CD + ApplicationSet
│ ├── traefik/ edge
│ ├── flannel/ CNI
│ └── <app>/ one directory per app
├── terraform/ OpenTofu. State in GCS, prefix gitops-<module>.
│ ├── authentik/ adguard/ routeros/ unifi/ cloudflare/
│ ├── grafana/ netbox/ gcp/ gitea/ backblaze/
│ └── base.Makefile
├── scripts/ auth_classification.yaml
└── .github/workflows/ manual tofu plan/apply over WireGuard
OpenTofu 1.12.5. From a module directory:
cd terraform/<module>
make check # validate + fmt
make plan
make apply # -auto-approveArgo CD is the deploy path for kubernetes/. Bootstrap (only if Argo itself is down):
make -C kubernetes/argocd bootstrapContext k8s@lake, chart argo-cd 10.4.0. After that, push to main.
Secrets:
- Kubernetes: 1Password items, External Secrets. Tag Argo CD items
ArgoCD External Secrets Operator. - OpenTofu: gitignored
defaults.auto.tfvars. Never commit it.
New app data is a static NFS volume on the NAS, pointed at the export that already exists. Do not pin it to one node with a host bind.
- Cloud drives onto the NAS
- Proxmox backups onto the NAS
- Authentik LDAP for the Synology
- NUT / UPS
- kubeadm + self-managed Argo CD
- Argo CD via Authentik OIDC, secrets from 1Password
- Vault, Phase, and Vaultwarden out of the public repo
- UniFi controller + U7 Lite / WLANs as code
-
terraform/cloudflareinto a private sibling repo - Self-hosted LLM
- Real IoT isolation
- RouterOS fully driven from this repo (or from NetBox)
- Home Assistant on the lake node
- Helm-only apps drop empty
kustomization.yaml