Home Infrastructure & Kubernetes Cluster
May 5, 2026 ยท View on GitHub
This is a mono repository for my home infrastructure and Kubernetes cluster. I try to adhere to Infrastructure as Code (IaC) and GitOps practices using tools like Ansible, Terraform, Kubernetes, Flux, Renovate, and GitHub Actions.
Agent note: this README remains human-facing. Tooling and AI assistants should use the repository guidance files as the operational guide, starting at CLAUDE.md and then following any more specific CLAUDE.md files in subdirectories.
๐ Hardware Infrastructure
The infrastructure is built on a Debian 13 Proxmox server with the following specifications:
| Device | Quantity | CPU | OS Disk Size | RAM | OS | Function |
|---|---|---|---|---|---|---|
| Lenovo M93p tiny USFF | 1 | Intel i5-4570T @ 2.90GHz | 512GB SSD | 16GB | Debian 13 | Proxmox hypervisor |
Virtual Machines:
| Device | Quantity | OS Disk Size | Data Disk Size | RAM | OS | Function |
|---|---|---|---|---|---|---|
| NAS VM | 1 | 16 GB | USB3 DAS 16TB EXT4 (host) | 2GB | Debian 13 | SMB + NFS NAS, OpenMediaVault 8 |
| K3s VM | 1 | 200GB | - | 12GB | Debian 13 | K3s master node - single node cluster |
๐ GitOps Workflow
Flux
Flux watches the clusters in my kubernetes folder and makes changes to my clusters based on the state of this Git repository. The workflow operates as follows:
- Flux recursively searches the
kubernetes/appsfolder until it finds the most top levelkustomization.yamlper directory - Each
kustomization.yamlgenerally contains:- A namespace resource
- One or many Flux kustomizations (
ks.yaml)
- Under the control of those Flux kustomizations, there will be a
HelmReleaseor other resources related to the application
Renovate
Renovate watches the entire repository for dependency updates. When updates are found, a PR is automatically created. When PRs are merged, Flux applies the changes to the cluster.
๐ Repository Structure
๐ kubernetes
โโโ ๐ apps # applications
โโโ ๐ bootstrap # initial cluster setup and configuration
โโโ ๐ flux # flux system configuration
๐ง Application Deployment Strategy
I use official Helm charts whenever possible for applications. When official charts are not available, I use the bjw-s Helm Chart ecosystem to ensure consistent deployment patterns.
bjw-s Common Library: Helm 3 library chart providing reusable templates for common Kubernetes resources.
bjw-s App Template: Companion chart that enables deployment of any application using the Common Library.
๐ ๏ธ Core Components
Networking & Security
- cert-manager: SSL certificates for services
- Calico: Container networking and network security
- MetalLB: Load balancer for bare metal clusters
- cloudflared: Cloudflare secure tunnel access
- Envoy Gateway: Envoy-based ingress controller
- k8s-gateway: Split-DNS bridge from the LAN into Gateway API routes
Ingress Model
The cluster uses a dual-Gateway Envoy model:
envoy-external: public-facing Gateway API entrypoint behind Cloudflare Tunnelenvoy-internal: internal Gateway API entrypoint exposed on a LAN VIP through MetalLB
Public DNS and public traffic stay on the external path:
- Cloudflare Tunnel forwards
${PUBLIC_DOMAIN}and*.${PUBLIC_DOMAIN}toenvoy-external - ExternalDNS manages public DNS records for externally published routes
Internal clients use split DNS instead of the tunnel path:
k8s-gatewaylistens on its own LAN VIP and watches HTTPRoutes attached toenvoy-internal- the home router DNS conditionally forwards
${PUBLIC_DOMAIN}lookups tok8s-gateway - internal clients therefore resolve app hostnames to the
envoy-internalVIP and reach services directly on the LAN
Most user-facing HTTPRoutes attach to both envoy-external and envoy-internal.
See docs/networking-readme.md for the current routing and split-DNS model.
DNS & External Integration
- external-dns: Automatic DNS record synchronization
- external-secrets: Secrets management using 1Password Connect
Storage & Backup
- democratic-csi: CSI driver supporting local hostpath, NFS, iSCSI and ZFS storage backends
- volsync: PVC backup and recovery using Kopia to OVH object storage
Configuration Management
- sops: Git-committed secrets for Kubernetes and Terraform
โ๏ธ Cloud Provider: Cloudflare
All Cloudflare resources are managed using Terraform with the Cloudflare provider. Configuration files are located in the provision/cloudflare directory.
Cloudflare Resources
- DNS records: For both cluster resources and custom domain email settings
- Cloudflare Access: Zero-trust network access
- Cloudflare Firewall: Security rules and protection
- R2 Bucket: Storage for homepage downloadable files
- Cloudflare Tunnel: Publishes cluster resources securely
- Cloudflare Workers
- Email MTA-STS policy
- Zone Settings: Domain configuration and optimization
๐ Secrets Management
The cluster uses a hybrid approach for secrets management:
- Basic cluster secrets: Encrypted with SOPS and stored in the Git repository
- Application secrets: Stored in 1Password and accessed via External Secrets operator
This setup ensures sensitive data is properly secured while maintaining the GitOps workflow.
๐ Deployment Dependencies
Applications are deployed with proper dependency management:
HelmReleaseresources can depend on otherHelmReleaseresourcesKustomizationresources can depend on otherKustomizationresources- In rare cases, applications can depend on both
HelmReleaseandKustomizationresources
This ensures applications are deployed in the correct order with all dependencies satisfied.