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:

DeviceQuantityCPUOS Disk SizeRAMOSFunction
Lenovo M93p tiny USFF1Intel i5-4570T @ 2.90GHz512GB SSD16GBDebian 13Proxmox hypervisor

Virtual Machines:

DeviceQuantityOS Disk SizeData Disk SizeRAMOSFunction
NAS VM116 GBUSB3 DAS 16TB EXT4 (host)2GBDebian 13SMB + NFS NAS, OpenMediaVault 8
K3s VM1200GB-12GBDebian 13K3s 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/apps folder until it finds the most top level kustomization.yaml per directory
  • Each kustomization.yaml generally contains:
    • A namespace resource
    • One or many Flux kustomizations (ks.yaml)
  • Under the control of those Flux kustomizations, there will be a HelmRelease or 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 Tunnel
  • envoy-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} to envoy-external
  • ExternalDNS manages public DNS records for externally published routes

Internal clients use split DNS instead of the tunnel path:

  • k8s-gateway listens on its own LAN VIP and watches HTTPRoutes attached to envoy-internal
  • the home router DNS conditionally forwards ${PUBLIC_DOMAIN} lookups to k8s-gateway
  • internal clients therefore resolve app hostnames to the envoy-internal VIP 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

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:

  • HelmRelease resources can depend on other HelmRelease resources
  • Kustomization resources can depend on other Kustomization resources
  • In rare cases, applications can depend on both HelmRelease and Kustomization resources

This ensures applications are deployed in the correct order with all dependencies satisfied.