... a GitOps-driven homelab managed with Flux, Renovate, and GitHub Actions
This mono repository serves as the single source of truth for my home(lab) infrastructure and Kubernetes cluster, following Infrastructure as Code (IaC) and GitOps best practices. The cluster is semi-automated with tools like Kubernetes, Flux, Renovate and GitHub Actions.
This ensures an immutable and reproducible environment, with changes applied automatically based on repository state.
The cluster operates on Talos Linux, an immutable and ephemeral Linux distribution tailored for Kubernetes, deployed on virtual machines running on Proxmox VE. Persistent storage is provided by TrueNAS SCALE, ensuring data integrity and availability.
- actions-runner-controller: Self-hosted GitHub runners.
- cert-manager: Automated SSL certificate management.
- cilium: eBPF-powered networking and security.
- cloudflared: Secure Cloudflare Tunnel integration.
- democratic-csi: CSI driver for persistent storage.
- external-dns: Automatic DNS management.
- external-secrets: Managed Kubernetes secrets using 1Password Connect.
- sops: Secure encryption for Talos configuration and Kubernetes secrets.
- spegel: Stateless cluster local OCI registry mirror.
- volsync: Backup and restore solution for persistent volume claims.
Flux continuously monitors the repository and ensures the cluster state aligns with the desired configuration defined in the kubernetes directory.
Flux operates by recursively scanning the kubernetes/apps
directory to identify the highest-level kustomization.yaml
files within each application directory. These kustomizations generally define namespaces and Flux-managed resources (ks.yaml
). Under these kustomizations, applications are deployed via HelmRelease
including other resources related to the application.
Renovate automates dependency management across the entire repository. It continuously scans for updates and creates pull requests when new versions are available. Once merged, Flux applies the changes to the cluster, ensuring an up-to-date and secure environment.
├─📁 bootstrap # Resources used during bootstrap process
├─📁 kubernetes # Kubernetes cluster directory
│ ├─ 📁 apps # Application manifests
│ ├─ 📁 components # Reusable kustomize components
│ └─ 📁 flux # Flux system configuration
├─📁 scripts # Scripts used during boots
8000
trap process
└─📁 talos # Talos cluster configuration
├─ 📁 clusterconfig # Talos node configuration files
└─ 📁 patches # Patches applied to Talos nodes
Flux ensures applications are deployed in the correct sequence by managing dependencies between them. Typically, a HelmRelease
depends on another HelmRelease
, while a Kustomization
may rely on another Kustomization
. Occasionally, an application may require both a HelmRelease
and a Kustomization
before deployment. The example below illustrates a dependency chain where cloudnative-pg
must be deployed and operational before cloudnative-pg-cluster
, which in turn must be healthy before immich
is deployed.
graph TD;
id1[Kustomization: flux-system] -->|Creates| id2[Kustomization: cluster-apps];
id2 -->|Creates| id3[Kustomization: cloudnative-pg];
id2 -->|Creates| id4[Kustomization: cloudnative-pg-cluster];
id2 -->|Creates| id5[Kustomization: immich];
id3 -->|Creates| id6(HelmRelease: cloudnative-pg);
id4 -->|Depends on| id3;
id4 -->|Creates| id7(Cluster: immich-pg17);
id5 -->|Depends on| id4;
id5 -->|Creates| id8(HelmRelease: immich);
While most services are self-hosted, certain critical components rely on cloud services to ensure availability, especially in bootstrapping scenarios.
Service | Purpose | Cost |
---|---|---|
1Password | Secret management via External Secrets | ~€40/yr |
Cloudflare | DNS and secure access via Cloudflare Tunnel | Free |
GitHub | Repository hosting and CI/CD | Free |
Mailgun | Automatic email delivery | Free (Flex Plan) |
Name.com | Domain registration | ~€55/yr |
Pushover | Infrastructure alerts and notifications | $5 (One Time Fee) |
Tailscale | Secure private remote access | Free |
~€8/mo |
graph LR;
id1((Internet)) <-->|600Mbps↓ 50Mbps↑| id2[UniFi Cloud Gateway Fiber];
id2 <-->|1Gbps↕| id3[UniFi Pro 24 PoE];
id3 <-->|10Gbps↕| id4[UniFi Aggregation];
id3 <-->|1Gbps↕| id5["UniFi 8 (Gen1)"];
id3 <-->|1Gbps↕| id6[2 x UniFi AC Pro];
id3 <-->|1Gbps↕| id7(Home devices);
id4 <-->|10Gbps↕| id8[Proxmox VE host];
id4 <-->|10Gbps↕| id9[5 x Talos VMs];
id4 <-->|10Gbps↕| id10[TrueNAS SCALE];
id5 <-->|1Gbps↕| id11(IoT devices);
id6 <--> id12(WiFi clients);
Name | ID | Description |
---|---|---|
Default | 1 |
Default VLAN (abandoned) |
Management | 10 |
Management network |
Server | 20 |
VLAN for servers and services |
Home | 30 |
VLAN for devices and computers |
Kids | 40 |
VLAN for kids |
Camera | 50 |
VLAN for security cameras |
IoT | 60 |
VLAN for IoT devices |
Storage | 100 |
VLAN for NFS and iSCSI |
Guest | 200 |
VLAN for guest devices |
To be documented...
To be documented...
Vendor | Model | Count | Function |
---|---|---|---|
Ubiquiti | UniFi Cloud Gateway Fiber | 1 | Firewall & Router |
Ubiquiti | UniFi Aggregation | 1 | 10G SFP+ Core Switch |
Ubiquiti | UniFi Pro 24 PoE | 1 | 1GbE RJ45 PoE Switch |
Ubiquiti | UniFi 8 (Gen1) | 1 | 1GbE RJ45 Utility Switch |
Ubiquiti | UniFi AC Pro | 2 | WiFi 5 Access Point |
A special thanks to the Home Operations Discord community for their insights and inspiration. Many ideas stem from shared clusters under the k8s-at-home GitHub topic and the excellent Kubesearch tool.
See LICENSE