homelab/build/config/ansible/roles/k3s_traefik/templates/dashboard-ingressroute.yaml.j2
Russell Seymour 1250c9cef6
Some checks are pending
deploy / deploy (push) Waiting to run
Initial checkin of code for managing homelab
2026-08-24 20:52:36 +01:00

83 lines
3.4 KiB
Django/Jinja

{#
Managed by Ansible (roles/k3s_traefik) — do not edit on the node.
Plain manifests, not a HelmChart — same pattern as
roles/k3s_metallb/templates/metallb-config.yaml.j2 and
roles/k3s_cert_manager/templates/cluster-issuer.yaml.j2: CRs belonging to
charts installed elsewhere, dropped in the auto-deploying directory and
retried by k3s's deploy controller until the CRDs they need exist.
Rendered only when k3s_traefik_dashboard_host is set; tasks/main.yml
deletes this file when it isn't, and k3s's deploy controller
garbage-collects what the file created.
traefik.io/v1alpha1, not traefik.containo.us/v1alpha1 — the group changed
with Traefik v3, which is what current k3s bundles.
-#}
{# Explicit Certificate rather than the cert-manager.io/cluster-issuer
annotation every app's Ingress uses: cert-manager watches Ingress
resources, and this route can't be one (see below). DNS-01, so this
issues without the hostname resolving anywhere yet. -#}
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: traefik-dashboard
namespace: {{ k3s_traefik_namespace }}
spec:
secretName: {{ k3s_traefik_dashboard_tls_secret }}
issuerRef:
name: {{ k3s_traefik_dashboard_cert_issuer }}
kind: ClusterIssuer
dnsNames:
- {{ k3s_traefik_dashboard_host }}
---
{# Authentik, in forward-auth (domain level) mode — see defaults/main.yml for
why domain level and not single-application. Fails closed: if Authentik is
down this returns an error rather than passing the request through, which
is the correct direction and the reason the port-forward path stays. -#}
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: {{ k3s_traefik_dashboard_auth_middleware }}
namespace: {{ k3s_traefik_namespace }}
spec:
forwardAuth:
address: {{ k3s_traefik_dashboard_auth_address }}
# Traefik strips X-Forwarded-* from client requests by default; Authentik
# needs them to know which host and scheme the user actually asked for,
# and builds its redirect back out of them. Safe here because the only
# thing that can set them is Traefik itself — nothing reaches this
# middleware without passing through the entrypoint first.
trustForwardHeader: true
authResponseHeaders:
{% for header in k3s_traefik_dashboard_auth_response_headers %}
- {{ header }}
{% endfor %}
---
{# An IngressRoute rather than an Ingress, and not by preference: the
dashboard is served by api@internal, a Traefik-internal service with no
Kubernetes Service behind it, so there is nothing for an Ingress backend
to name. That single fact is why the Certificate above is explicit and why
the middleware is attached here rather than by annotation. -#}
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: traefik-dashboard
namespace: {{ k3s_traefik_namespace }}
spec:
entryPoints:
- websecure
routes:
# Both prefixes, because the dashboard is a static bundle under
# /dashboard/ that reads its data from /api — serving the first without
# the second gets you a page that loads and then stays empty.
- kind: Rule
match: Host(`{{ k3s_traefik_dashboard_host }}`) && (PathPrefix(`/dashboard`) || PathPrefix(`/api`))
middlewares:
- name: {{ k3s_traefik_dashboard_auth_middleware }}
namespace: {{ k3s_traefik_namespace }}
services:
- kind: TraefikService
name: api@internal
tls:
secretName: {{ k3s_traefik_dashboard_tls_secret }}