Skip to main content

Edge cluster

The edge cluster is the homelab's public-facing Kubernetes cluster. Single-node, single-purpose: terminate inbound traffic from the internet, then forward it to the production cluster over the NetBird mesh using PROXY-protocol-v2 to preserve the real client IP.

Stack​

Versions​

ComponentVersionDeclared in
Talos Linuxv1.14.3talos/edge/topf.yaml
Kubernetesv1.37.1talos/edge/topf.yaml
Fluxv2.9.6k8s/clusters/edge/flux-system/gotk-components.yaml

These are the versions declared in Git. Flux updates itself as soon as its manifests merge; a Talos or Kubernetes bump only reaches the nodes with the next topf upgrade.

Layers at a glance​

LayerWhatDoc
Compute1× cx33 Hetzner instance (control-plane-1), nbg1foundation/hetzner
Cluster OSTalos Linux, single-node configfoundation/talos
GitOpsFlux pulling from the same Gitea repo, separate clusters/edge/ pathfoundation/flux
NetworkCilium (CNI + kube-proxy replacement)platform/cilium
IngressEnvoy Gateway terminating TLS; forwards to production via PROXY-protocol-v2platform/envoy-gateway · topics/envoy-gateway-proxy-protocol-v2
Certscert-manager + ACME via cert-manager-webhook-all-inklplatform/cert-manager
DatabaseCNPG (small, only for sidecar app state)platform/cloudnative-pg
Inter-siteNetBird edge peer routes back to production over WireGuardfabric/netbird

Cluster machine​

RoleNameSpecNetwork
Control + workercontrol-plane-1cx33, Talos imagePublic IP + floating IP (edge-1); private 172.30.0.11/24

A single node is intentional — the edge cluster's blast radius is its own. If it dies, the production cluster carries on; only public traffic is interrupted.

Networking summary​

PlaneWhat
VPCedge (172.30.0.0/16), subnet k8s (172.30.0.0/24 in eu-central)
Public IPFloating IP edge-1 — survives instance replacement
Inter-siteNetBird edge network — the netbird-client pod joins as a plain mesh peer
Cross-networkedge_sidecar_envoy ↔ production public subnet for upstream

Cloud firewalls are label-selected: talos-control, talos-internal, allow-http, allow-ssh (port 22 carries Git over SSH to Gitea, not a shell). See Hetzner for ports.

What runs here​

  • Public ingress — the Envoy Gateway that the world hits.
  • TLS termination + ACME — cert-manager + the all-inkl webhook (DNS-01).
  • The mesh peer — netbird-client, which keeps the node on the NetBird network so the gateway can reach production.
  • Three public apps with their own domains — Aushang, Openbeehive and Seitenraum.

Two of those hold state on the node: Openbeehive and Seitenraum each run a single-instance CNPG database and keep uploads on local-path volumes. There is no Longhorn, no second node and no backup on this cluster, so that data lives exactly once. Everything else with persistent state belongs on production.

Reconciliation order​

Flux applies the cluster as a set of Kustomizations from k8s/clusters/edge/. Most of the platform has no ordering at all; what is ordered funnels through infra-configs, the gate every app waits for.

9 platform Kustomizations and 4 apps. An arrow means "has to be ready before"; the 7 entries without an incoming arrow start as soon as Flux is running.

Lifecycle commands​

# Render for review, diff against the node, apply (from talos/edge)
topf render
topf apply --dry-run
topf apply

# Talos upgrade: one reboot, so a public outage; a single node cannot drain
topf upgrade --drain=false

# Reconcile Flux
flux reconcile kustomization flux-system --kubeconfig ~/.kube/edge

# Provision / drift-check the underlying Hetzner resources
cd tofu/environment/edge && ./tofu.sh plan

Recovery​

If the cx33 instance is lost:

  1. tofu apply re-creates the instance with the same name + label set; cloud firewalls reattach automatically.
  2. topf apply --auto-bootstrap pushes the Talos config and bootstraps etcd; topf upgrade --drain=false afterwards installs the factory image.
  3. Re-attach the floating IP if it didn't follow.
  4. Flux reconciles everything else from Git.

The cluster itself is back in the order of minutes, and so is public ingress. The data of Openbeehive and Seitenraum is not: with no backup target on edge, a lost server takes their databases and uploads with it. See Disaster recovery.

See also​