HomeLab GitOps repository. Reconciled by flux.
Find a file
2026-05-19 22:43:07 +02:00
.docs del(configs): move redirect to gateway and bgp configuration to metallb 2026-05-19 08:47:33 +02:00
apps refactor: finish rebase 2026-05-18 21:18:09 +02:00
clusters/phonk del(configs): move redirect to gateway and bgp configuration to metallb 2026-05-19 08:47:33 +02:00
infrastructure del(configs): move redirect to gateway and bgp configuration to metallb 2026-05-19 08:47:33 +02:00
.gitignore add(ops/bao): deploy OpenBao with CNPG backend and HTTPRoute 2026-05-17 16:09:56 +02:00
README.md update todo 2026-05-19 22:43:07 +02:00
TODO.md update todo 2026-05-19 22:43:07 +02:00

Gigawave

GitOps repo for the phonk Talos Linux homelab cluster (3 nodes), managed by Flux v2.

Cluster Overview

  • OS: Talos Linux
  • Hardware
    • HP ProDesk 400 G5 (4c, 48GB, 500GB SATA SSD, 2TB NVME)
    • HP ProDesk 400 G5 (4c, 48GB, 500GB SATA SSD, 2TB NVME)
    • HP ProDesk 400 G5 (4c, 64GB, 500GB SATA SSD, 2TB NVME)
  • Network: Local 2.5GbE
  • CNI
    • Cilium
      • kube-proxy replacement
      • Hubble (tbh i dont see much value here... thinking of turning it off)
  • Storage
    • Local Path — workloads with PVCs are pinned to a node for rescheduling
  • Secrets
    • OpenBao
      • PostgreSQL backend
      • Unseal via static seal secret applied before flux bootstrap
    • External Secrets Operator
  • Gateway
    • Envoy
      • external
        • 1bleim.de
        • anuth.dev
        • fullbyte.de
      • internal
        • ops.phonk.jukebox.fullbyte.de
        • home.anuth.dev

GitOps

  • Bootstrap from github.com/boneskewer69/gigawave
  • Switch to Self-hosted Forgejo at forge.fullbyte.de/
  • Updates: Renovate bot only (no Flux image automation)

Docs

  • Bootstrap — Flux install, manual secrets, SSH deploy key, reconcile reference
  • OpenBao — init, zone KV + auth setup, OIDC, initial secrets
  • Talos / BGP — node operations, MikroTik BGP config
  • Each app has its own README detailing why it exists and what should be deployed here

Repository Structure

gigawave/
├── clusters/phonk/          # Flux Kustomization CRs
│   ├── flux-system/         # flux-operator FluxInstance
│   ├── infrastructure/      # one .yaml per infra layer
│   └── apps/                # one .yaml per zone
├── infrastructure/
│   ├── namespaces/          # zone + operator namespaces
│   ├── sources/             # HelmRepository + GitRepository CRs
│   ├── cni/cilium/          # Cilium HelmRelease (kube-system)
│   ├── csi/local-path/      # local-path-provisioner HelmRelease
│   ├── gateway/envoy/       # stub — Envoy Gateway migration (future)
│   └── operators/
│       ├── cert/            # cert-manager, cert-manager-webhook-hetzner
│       ├── kafka/strimzi/
│       ├── opensearch/opensearch-operator/
│       ├── postgresql/cnpg/
│       ├── redis/redis-operator/
│       ├── secrets/external-secrets/
│       └── storage/garage-operator/
└── apps/
    ├── ops/                 # namespace: ops — cluster services
    │   ├── bao/             # OpenBao HelmRelease + bao-db CNPG cluster
    │   ├── config/          # SecretStore, ClusterIssuer, wildcard certs
    │   ├── gitops/flux-operator/
    │   ├── monitoring/      # kube-prometheus-stack + Thanos
    │   ├── network/dns/zone/# CoreDNS for *.ops.phonk.jukebox.fullbyte.de
    │   └── pgadmin/
    ├── fullbyte/            # namespace: fullbyte — fullbyte.de services
    │   ├── config/          # SecretStore
    │   ├── ci/              # Woodpecker CI
    │   ├── forge/           # Forgejo + forgejo-db
    │   ├── httpbin/
    │   ├── id/              # PocketID + pocketid-db
    │   └── s3/              # GarageCluster
    ├── home/                # namespace: home — home.anuth.dev services
    │   ├── config/          # SecretStore
    │   └── network/dns/
    │       ├── zone/        # CoreDNS for *.home.anuth.dev
    │       └── resolver/    # Blocky (upstreams: ops zone + home zone)
    ├── 1bleim/              # stub (future: 1bleim.de)
    ├── anuth/               # stub (future: anuth.dev)
    └── vanknel/             # stub (future: vanknel.de)

Dependency Graph

graph TD
    namespaces[infrastructure-namespaces]
    sources[infrastructure-sources]
    csi[infrastructure-csi]
    crds_gw[infrastructure-crds-gateway-api]
    crds_prom[infrastructure-crds-prometheus]
    cni[infrastructure-cni]
    gateway[infrastructure-gateway]
    operators[infrastructure-operators]
    ops[apps-ops]
    fullbyte[apps-fullbyte]
    home[apps-home]
    stubs["apps-1bleim / apps-anuth / apps-vanknel"]

    namespaces --> sources
    namespaces --> csi
    sources --> crds_gw
    sources --> crds_prom
    crds_gw --> cni
    crds_gw --> gateway
    cni --> operators
    operators --> ops
    crds_prom --> ops
    ops --> fullbyte
    ops --> home
    ops --> stubs

Key Conventions

  • New namespace → add to infrastructure/namespaces/namespaces.yaml
  • New Helm repo → add to infrastructure/sources/helm-repos.yaml
  • Operator HelmRelease → goes in infrastructure/operators/<category>/<name>/helmrelease.yaml
  • Operator instances: one cluster per tenant (e.g. bao-db, grafana-db, <app>-db). Always use instances: 3 with enablePodAntiAffinity: required and topologyKey: kubernetes.io/hostname — one replica per node, survives two node failures. No nodeSelector needed.
  • pgAdmin: add server to pgAdmin manually after deploy
  • Secrets pattern: ExternalSecret (pulls from OpenBao) → Kubernetes Secret → consumed by HelmRelease valuesFrom
  • SecretStore: one namespace-scoped SecretStore named openbao per zone (apps/<zone>/config/secretstore.yaml), pointing to bao.ops.svc.cluster.local. Use ClusterSecretStore only for cross-namespace infra (e.g. cert-manager-webhook-hetzner).
  • Stages: most workloads prod-only. If dev is required, create namespace <name>-dev and deploy a separate instance.
  • Variable substitution: cluster-wide vars in cluster-config ConfigMap; Flux postBuild.substituteFrom injects them. Reference as ${VAR_NAME} in manifests.
  • Deployment mode: single instance where possible. Stateful workloads: pin to node, deploy ≥2 if HA is possible, otherwise add backup TODO.
  • Storage: prefer emptyDir for ephemeral state; PVCs only for data that must survive pod restarts.
  • Email: outbound via Brevo (SMTP relay). Verified senders: id@fullbyte.de (PocketID), git@fullbyte.de (Forgejo), noreply@fullbyte.de (all others). Ask before using any other address. OpenBao secret path: secret/mail/de-fullbyte-<app> with keys smtp-server, smtp-port, smtp-login, smtp-key.

Tooling Ideas

  • flux-template — render template from local HelmRelease file
  • flux dependson diagram generator
  • pgadmin operator

Learnings

  • routing
    • less is more
    • bridge is like a partition for network ports on a switch/router
    • add DNS and NTP server to your network early
    • wait for NTP to fully sync before relying on time-sensitive services