# cluster-config/cilium-values.yaml
# Cilium CNI — installed via talosctl (not helmfile) during cluster bootstrap.
# Applied once: `helm install cilium cilium/cilium -n kube-system -f cilium-values.yaml`
#
# Why Cilium: Talos Linux does not ship kube-proxy. Cilium's eBPF dataplane
# replaces it entirely (kubeProxyReplacement: true) and also handles LB-IPAM
# so LoadBalancer services get real IPs without MetalLB.

# ── cgroup ────────────────────────────────────────────────────────────────────
# Talos mounts cgroups at boot before any container runtime starts.
# autoMount: false tells Cilium to use the existing mount rather than trying
# to mount its own — double-mounting on Talos causes init failures.
cgroup:
  autoMount:
    enabled: false
  hostRoot: /sys/fs/cgroup   # where Talos exposes the cgroup v2 hierarchy

# ── IPAM ──────────────────────────────────────────────────────────────────────
# kubernetes mode: Cilium allocates pod IPs from the pod CIDR that Talos
# configured for each node (--pod-cidr in the kubelet). Alternative is
# Cilium's own cluster-pool IPAM, but that requires extra config and
# conflicts with the Talos node CIDR assignment.
ipam:
  mode: kubernetes

# ── Operator ──────────────────────────────────────────────────────────────────
# Single replica is fine for a 3-node homelab. The operator manages CiliumNode
# objects and LB-IPAM pools — it does not sit in the data path.
operator:
  replicas: 1

# ── kube-proxy replacement ────────────────────────────────────────────────────
# Talos is deliberately installed without kube-proxy (machineConfig
# install.extensions excludes it). Cilium must replace it completely —
# partial replacement would leave Service ClusterIPs unreachable.
kubeProxyReplacement: true

# ── L2 announcements ──────────────────────────────────────────────────────────
# Without this, LB-IPAM (k8s/cilium/lb-ipam-pool.yaml) assigns real IPs to
# LoadBalancer Services, but nothing ARPs for them on the LAN — the IP shows
# up in `kubectl get svc` but is 100% unreachable from outside the cluster
# (confirmed: forgejo's .165 and shadowsocks' .166 both had incomplete ARP
# entries and 100% ping loss before this). This flag is what actually makes
# k8s/cilium/l2-announcement-policy.yaml take effect instead of being inert.
l2announcements:
  enabled: true

# ── API server endpoint ───────────────────────────────────────────────────────
# Cilium needs to talk to the Kubernetes API to watch Nodes/Services/Endpoints.
# On Talos the API server listens on 127.0.0.1:7445 locally (the external
# port 6443 requires the node's external cert, which may not be available
# during early bootstrap). This is the standard Talos Cilium bootstrap config.
k8sServiceHost: 127.0.0.1
k8sServicePort: 7445

# ── Security context / capabilities ──────────────────────────────────────────
# Cilium's eBPF programs run in the kernel and require elevated capabilities.
# These are the minimum set needed — removing any of them breaks networking.
#
#   NET_ADMIN / NET_RAW  — manipulate iptables/nftables and raw sockets
#   IPC_LOCK             — lock eBPF maps in memory (prevents paging out BPF state)
#   SYS_ADMIN            — call bpf() syscall and mount BPF filesystem
#   SYS_RESOURCE         — raise RLIMIT_MEMLOCK for BPF map memory
#   DAC_OVERRIDE / FOWNER / SETGID / SETUID — file permission ops during init
#   CHOWN / KILL         — container lifecycle management
#
# cleanCiliumState runs as a one-shot init container to wipe stale eBPF state
# on upgrades — it needs NET_ADMIN, SYS_ADMIN, SYS_RESOURCE only.
securityContext:
  capabilities:
    ciliumAgent:
    - CHOWN
    - KILL
    - NET_ADMIN
    - NET_RAW
    - IPC_LOCK
    - SYS_ADMIN
    - SYS_RESOURCE
    - DAC_OVERRIDE
    - FOWNER
    - SETGID
    - SETUID
    cleanCiliumState:
    - NET_ADMIN
    - SYS_ADMIN
    - SYS_RESOURCE
