Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

buroa/k8s-gitops

Open more actions menu

Repository files navigation

A slightly overengineered homelab 🏠

... managed with Flux, Renovate, and GitHub Actions πŸ€–

Home-InternetΒ Β  Status-PageΒ Β  Alertmanager

DiscordΒ Β  TalosΒ Β  KubernetesΒ Β  FluxΒ Β  Renovate

AgeΒ Β  UptimeΒ Β  NodesΒ Β  PodsΒ Β  CPUΒ Β  MemoryΒ Β  PowerΒ Β  Alerts


πŸ’‘ Overview

This repository is the single source of truth for my home Kubernetes cluster and the workloads that run on it. Every cluster resource β€” from the operating system layer down to individual application Helm releases β€” is declared as code and reconciled automatically.

The stack is intentionally boring and reproducible:

  • Talos Linux β€” Immutable, API-driven OS that runs nothing but Kubernetes.
  • Flux β€” Continuous reconciliation of cluster state against this repository.
  • Renovate β€” Automated dependency updates across the entire cluster.
  • GitHub Actions β€” Validation and automation on every commit.

Disaster recovery is built in. Wipe every disk in the rack. Minutes later, the cluster is back β€” applications running, persistent data intact, zero manual steps. It picks up exactly where it left off.

Want to build something similar? Start with onedr0p/cluster-template.


πŸ“¦ Repository Layout

πŸ“ bootstrap     # One-time cluster bootstrap (helmfile + kustomize)
πŸ“ kubernetes    # Everything Flux reconciles
β”œβ”€πŸ“ apps        # Workloads, grouped by namespace
β”œβ”€πŸ“ components  # Reusable Kustomize components (alerts, kopiur, etc.)
β””β”€πŸ“ flux        # Flux system configuration and source repositories
πŸ“ talos         # Talos machine configs and per-node overrides

🎑 Cluster

A semi hyper-converged, three-node Kubernetes cluster running on bare-metal MS-A2 workstations. Persistent storage lives inside the cluster via Rook Ceph, with bulk media offloaded to a dedicated TrueNAS box over NFS.

Core components

  • actions-runner-controller β€” Self-hosted GitHub runners for CI/CD workflows.
  • cert-manager β€” Automated SSL certificate management and provisioning.
  • cilium β€” High-performance container networking powered by eBPF.
  • cloudflared β€” Secure tunnel providing Cloudflare-protected access to cluster services.
  • envoy-gateway β€” Modern ingress controller for cluster traffic management.
  • external-dns β€” Automated DNS record synchronization for ingress resources.
  • external-secrets β€” Kubernetes secrets management integrated with 1Password.
  • kopiur β€” Advanced backup and recovery solution for persistent volume claims.
  • multus β€” Multi-homed pod networking for advanced network configurations.
  • rook β€” Cloud-native distributed storage orchestrator for persistent storage.
  • spegel β€” Stateless cluster-local OCI registry mirror for improved performance.

GitOps workflow

Flux watches the kubernetes directory and reconciles the cluster on every commit. The flow is:

  1. Flux recursively scans kubernetes/apps and reads each top-level kustomization.yaml.
  2. Those entrypoints typically declare a Namespace and one or more Flux Kustomization resources (ks.yaml).
  3. Each Flux Kustomization materializes a HelmRelease (or raw manifests) for an application.
  4. Flux applies them in dependency order β€” e.g. nothing in rook-ceph deploys until its prerequisites are healthy.
graph LR
    classDef kustom fill:#43A047,stroke:#2E7D32,stroke-width:3px,color:#fff,font-weight:bold,rx:10,ry:10
    classDef helm fill:#1976D2,stroke:#0D47A1,stroke-width:3px,color:#fff,font-weight:bold,rx:10,ry:10

    A["πŸ“¦ Kustomization<br/>rook-ceph"]:::kustom
    B["πŸ“¦ Kustomization<br/>rook-ceph-cluster"]:::kustom
    C["🎯 HelmRelease<br/>rook-ceph"]:::helm
    D["🎯 HelmRelease<br/>rook-ceph-cluster"]:::helm
    E["πŸ“¦ Kustomization<br/>atuin"]:::kustom
    F["🎯 HelmRelease<br/>atuin"]:::helm

    A -->|Creates| C
    B -->|Creates| D
    B -.->|Depends on| A
    E -->|Creates| F
    E -.->|Depends on| B
Loading

🌎 Networking

A multi-tier home network built on UniFi hardware. The UDM Beast handles routing and firewalling between RCN's 5Gbps WAN and the LAN. A 25G aggregation switch forms the backbone β€” bonded to the NAS at 25G LACP and to each Kubernetes node at 10G LACP β€” while a 24-port PoE+ switch fans out to wired clients and access points.

graph LR
    %% Class Definitions
    classDef wan fill:#f87171,stroke:#fff,stroke-width:2px,color:#fff,font-weight:bold;
    classDef core fill:#60a5fa,stroke:#fff,stroke-width:2px,color:#fff,font-weight:bold;
    classDef agg fill:#34d399,stroke:#fff,stroke-width:2px,color:#fff,font-weight:bold;
    classDef switch fill:#a78bfa,stroke:#fff,stroke-width:2px,color:#fff,font-weight:bold;
    classDef device fill:#facc15,stroke:#fff,stroke-width:2px,color:#000,font-weight:bold;
    classDef vlan fill:#1f2937,stroke:#fff,stroke-width:1px,color:#fff,font-size:12px;

    %% Nodes
    RCN[πŸ›œ RCN<br/>5Gbps WAN]:::wan
    UDM[πŸ“¦ UDM Beast]:::core
    AGG[πŸ”— Pro Aggregation XG]:::agg
    NAS[πŸ’Ύ NAS]:::device
    K8s[☸️ Kubernetes<br/>3 Nodes]:::device
    SW[πŸ”Œ Pro XG 24 PoE]:::switch
    DEV[πŸ’» Devices]:::device
    WIFI[πŸ“Ά WiFi Clients]:::device

    %% Subgraph for VLANs
    subgraph VLANs [LAN +vlan]
        direction TB
        LOCAL[LOCAL<br/>192.168.0.0/24]:::vlan
        TRUSTED[TRUSTED*<br/>192.168.1.0/24]:::vlan
        SERVERS[SERVERS*<br/>192.168.10.0/24]:::vlan
        SERVICES[SERVICES*<br/>192.168.20.0/24]:::vlan
        IOT[IOT*<br/>192.168.30.0/24]:::vlan
        GUEST[GUEST*<br/>192.168.40.0/24]:::vlan
    end

    style VLANs fill:#111,stroke:#fff,stroke-width:2px,rx:0,ry:0,padding:20px;

    %% Links
    SERVERS -.-> RCN
    RCN -.->|WAN| UDM
    UDM -- 25G --- AGG
    UDM -- 25G --- SW
    AGG -- 10G LACP --> K8s
    AGG -- 25G LACP --> NAS
    SW --> DEV
    SW --> WIFI

    %% Keep SERVERS->RCN as a hidden layout constraint and style bonded links thicker
    linkStyle 0 stroke:transparent,stroke-width:0px,color:transparent;
    linkStyle 2 stroke-width:4px;
    linkStyle 3 stroke-width:4px;
    linkStyle 4 stroke-width:2px;
    linkStyle 5 stroke-width:4px;
Loading

DNS

Two ExternalDNS instances handle DNS automation:

  • Private β€” Syncs every route to the UDM Beast via the ExternalDNS UniFi webhook.
  • Public β€” Syncs routes on the external Gateway to Cloudflare.

The result is split-horizon DNS: at home, public hostnames resolve to LAN IPs, so traffic to my own services never leaves the network.


βš™ Hardware

Click to see my rack rack
Device Count OS Disk Data Disk RAM OS Purpose
Minisforum MS-A2 3 1.92TB M.2 3.84TB U.2 + 1.92TB M.2 96GB Talos Kubernetes
45HomeLab HL15 2.0 1 1.92TB M.2 12Γ—22TB HDD + 2Γ—7.68TB U.2 512GB TrueNAS SCALE NFS + Backup Storage
JetKVM 3 - - - - KVM for Kubernetes
UniFi Dream Machine Beast 1 - 2Γ—960GB SSD - UniFi OS Router & NVR
UniFi Pro XG Aggregation 1 - - - UniFi OS 25G SFP28 Switch
UniFi Pro XG 24 PoE 1 - - - UniFi OS 10G PoE+ Switch
UniFi Power Distribution Pro 1 - - - UniFi OS PDU
APC SMT1500RM2UNC UPS 1 - - - - UPS

MS-A2 build

Each MS-A2 (AMD Ryzenβ„’ 9 9955HX) workstation is equipped with:


πŸ™ Thanks

A huge thank you to @onedr0p and the Home Operations Discord community for the knowledge, patterns, and support that made this cluster possible. For more inspiration on running apps in a homelab, browse kubesearch.dev.


🌟 Stargazers


βš– License

See LICENSE.


Ask DeepWiki

About

Husband-approved homelab deployed with Talos Linux; managed with Flux, Renovate, and GitHub Actions πŸ€–

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

Used by

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.