--- # Ansible-side knobs for roles/k3s_traefik — the ingress controller k3s # bundles. The odd one out among the k3s_* cluster services: every other one # installs a chart this repo chose (roles/k3s_metallb, k3s_monitoring, # k3s_postgres, k3s_cert_manager), whereas Traefik is already installed by # k3s itself before Ansible ever connects. So this role installs nothing — # it only adjusts what's there, via a HelmChartConfig (see # templates/traefik.helmchartconfig.yaml.j2 for why that, and not an edit to # k3s's own traefik.yaml). # # Scope today is the dashboard, which a stock k3s serves 404s for. That's # not a broken install: Traefik builds the dashboard regardless # (`api.dashboard` defaults on), but the Traefik chart stopped creating the # router that reaches it in v28, so there is nothing routing /dashboard/ on # any entrypoint until something puts that router back. # Where k3s installs Traefik, and so where the HelmChartConfig has to live — # a HelmChartConfig only applies to the HelmChart of the same name in the # same namespace. k3s_traefik_namespace: kube-system # --- The dashboard, reachable by port-forward -------------------------------- # # Re-enables the chart's own dashboard IngressRoute, which binds to Traefik's # internal `traefik` entrypoint (port 9000). That entrypoint is not published # on Traefik's Service, so this exposes nothing to the LAN; it makes exactly # one thing work: # # kubectl -n kube-system port-forward deploy/traefik 9000:9000 # # then http://127.0.0.1:9000/dashboard/ — the trailing slash is required # # Left on even when the dashboard is also exposed on a hostname below, and # that's deliberate rather than redundant. Once the exposed route is behind # Authentik, the dashboard depends on Authentik being up, which depends on # CNPG being up, which depends on the cluster being healthy — precisely the # things you would open the dashboard to diagnose. Port-forward talks to the # pod and traverses none of it, so it stays as the break-glass path. Don't # "tidy this up" once the hostname works. k3s_traefik_dashboard_enabled: true # --- The dashboard, exposed on a hostname ------------------------------------ # # Empty (the default) means the port-forward above is the only way in, and # tasks/main.yml renders no IngressRoute at all — it removes one it previously # rendered, so clearing this is a real teardown rather than a no-op. # # Set it to a hostname (e.g. traefik.turtlesystems.uk) to publish the # dashboard on the `websecure` entrypoint with a cert-manager certificate and # the forward-auth middleware below in front of it. Doing so requires # k3s_traefik_dashboard_auth_address to be set as well — the role refuses to # run otherwise, because the failure mode of getting this wrong is a # read-only view of every route, service and middleware in the cluster # published unauthenticated to the LAN. # # The hostname needs a DNS record pointing at Traefik's MetalLB address # (`kubectl -n kube-system get svc traefik`), same as any app's Ingress. k3s_traefik_dashboard_host: "" # The ClusterIssuer roles/k3s_cert_manager creates. Must match # k3s_cert_manager_issuer_name — stated rather than referenced because that # lives in the other role's defaults, which aren't in scope here. Same # convention as CERT_ISSUER in src/authentik/ansible/kubernetes/vars.yml. # # An explicit Certificate rather than an Ingress annotation, unlike every app # on this cluster: cert-manager watches Ingress resources, and the dashboard # can't be one. It's served by Traefik's internal `api@internal` service, # which has no Kubernetes Service for an Ingress to point at — hence an # IngressRoute, which cert-manager doesn't watch. k3s_traefik_dashboard_cert_issuer: letsencrypt k3s_traefik_dashboard_tls_secret: traefik-dashboard-tls # --- Authentication in front of the exposed dashboard ------------------------ # # A Traefik forwardAuth middleware pointing at Authentik, which now runs on # this cluster (roles/k3s_app, src/authentik). No default, and required as # soon as k3s_traefik_dashboard_host is set: a default here would be a guess # at another app's service name, and a wrong guess that happens to be # unreachable is a 500, not an open dashboard — but one that happens to # resolve to the wrong thing is worse. Set it explicitly, next to the host, # in inventory/group_vars/k3s_cluster.yml. # # For Authentik's embedded outpost, in-cluster: # # http://authentik-server.authentik.svc.cluster.local/outpost.goauthentik.io/auth/traefik # # The provider in Authentik must be a Proxy Provider in **forward auth # (domain level)** mode, not single-application. Single-application mode # additionally requires /outpost.goauthentik.io/ to be routed to Authentik on # *this* host, which from an IngressRoute in kube-system means referencing a # Service in the authentik namespace — a cross-namespace reference Traefik # rejects unless started with providers.kubernetescrd.allowCrossNamespace, # which it isn't. Domain-level mode handles the redirect on Authentik's own # hostname instead and needs no such route, so it's the mode that fits. k3s_traefik_dashboard_auth_address: "" k3s_traefik_dashboard_auth_middleware: dashboard-auth # What Authentik sets on the way back through, forwarded to the dashboard. # The dashboard itself reads none of them — it has no notion of a user — so # this is really about the headers existing for anything else that reuses # this middleware later, and about matching Authentik's documented list # rather than inventing a shorter one. k3s_traefik_dashboard_auth_response_headers: - X-authentik-username - X-authentik-groups - X-authentik-entitlements - X-authentik-email - X-authentik-name - X-authentik-uid - X-authentik-jwt - X-authentik-meta-jwks - X-authentik-meta-outpost - X-authentik-meta-provider - X-authentik-meta-app - X-authentik-meta-version