# Traefik reconfiguration for this deployment. # # K3s defaults: Traefik as single-replica Deployment, LoadBalancer service. # We disabled servicelb (--disable=servicelb on k3s install), so LoadBalancer # doesn't get an external IP. This config makes Traefik a DaemonSet binding # directly on each node's public :80/:443 via hostNetwork, matching our # Cloudflare DNS round-robin across 3 node IPs. # # Apply: kubectl apply -f traefik-helmchartconfig.yaml # Then bump Helm reconcile: kubectl delete job -n kube-system helm-install-traefik apiVersion: helm.cattle.io/v1 kind: HelmChartConfig metadata: name: traefik namespace: kube-system spec: valuesContent: |- deployment: kind: DaemonSet hostNetwork: true service: enabled: false ports: web: port: 80 hostPort: 80 websecure: port: 443 hostPort: 443 # hostNetwork with port 80/443 requires RollingUpdate maxUnavailable > 0 # (each node's port is held by one pod; can't surge). updateStrategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 maxSurge: 0 securityContext: capabilities: drop: [ALL] add: [NET_BIND_SERVICE] readOnlyRootFilesystem: true runAsGroup: 65532 runAsNonRoot: true runAsUser: 65532 # NOTE: The host-level sysctl `net.ipv4.ip_unprivileged_port_start=0` # must be set on each node. Without it, hostNetwork pods can't actually # use NET_BIND_SERVICE to bind :80/:443. Persisted at # /etc/sysctl.d/99-unprivileged-ports.conf on each node. additionalArguments: # Trust Cloudflare's forwarded proto header so the Go app sees the # original https scheme even though CF→origin is plain HTTP. # IP ranges from https://www.cloudflare.com/ips-v4/ (as of 2026-04). - "--entrypoints.web.forwardedHeaders.trustedIPs=173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/13,104.24.0.0/14,172.64.0.0/13,131.0.72.0/22"