This is a monorepo for my home infrastructure and Kubernetes cluster, built on the cluster-template by onedr0p. I try to adhere to Infrastructure as Code (IaC) and GitOps practices using tools like Kubernetes, Flux, Renovate, and GitHub Actions.
With Nix installed and flakes enabled, run these commands from the repository root:
nix develop
task --listThe shell includes the CLI tools used by this repository. flake.lock pins their
versions through nixpkgs. It sets credential paths to local files without reading
or copying their contents into the Nix store. Credentials are not required to
enter the shell or list tasks.
Run nix fmt flake.nix to format it and nix flake check --no-build to evaluate the
flake. The existing mise configuration remains available as a fallback. Nix and
mise versions may differ; check compatibility before running cluster operations.
My Kubernetes cluster is deployed with Talos on a single node. Workloads and storage share the same available resources on the node.
- Networking: cilium provides eBPF-based networking with L2 announcements. envoy-gateway handles external and internal ingress. cloudflared secures ingress traffic via Cloudflare, and external-dns keeps DNS records in sync automatically.
- Security & Secrets: cert-manager automates SSL/TLS certificate management. Secrets are encrypted with SOPS and age.
- Storage: local-path-provisioner provides persistent volumes backed by the node's local NVMe storage.
- Monitoring: kube-prometheus-stack for metrics and alerting, Grafana for dashboards, Victoria Logs and Fluent Bit for log aggregation, and Gatus for uptime monitoring.
Flux watches the kubernetes folder and makes changes to the cluster based on the state of my Git repository. It recursively searches for top level kustomization.yaml files in each directory. Each of these files contain a namespace resource as well as one or more Flux kustomization (ks.yaml). The Flux kustomizations control HelmRelease or other app resources.
Renovate scans my whole repo for out of date depedencies, automatically creating PRs when found. Merging these PRs triggers Flux to apply the changes to the cluster.
This Git repository contains the following directories under Kubernetes.
📁 kubernetes
├── 📁 apps # applications
└── 📁 flux # flux system configurationThere are two instances of ExternalDNS running in my cluster. The first one for syncing internal DNS records to my Unifi Cloud Gateway Fiber using the ExternalDNS webhook provider for UniFi, while the other one syncs public DNS to my Cloudflare domain. Which one handles a record depends on the ingress class being other internal for internal resolution only and external for public access.
| Device | Num | OS Disk Size | Ram | OS | Function |
|---|---|---|---|---|---|
| Minisforum MS-02 Ultra | 1 | 2TB NVMe | 192GB DDR5 ECC | Talos | Kubernetes |
| UniFi Cloud Gateway Fiber | 1 | - | - | - | Router / Firewall |
| UniFi Pro XG 8 PoE | 1 | - | - | - | Core Switch |
| UniFi U7 Pro XG | 1 | - | - | - | Wi-Fi AP |
Thanks to onedr0p for the onedr0p/cluster-template.

