Skip to content

feature: Traefik serves the panel through the Gateway API instead of the retired ingress-nginx - #697

Merged
lukepolo merged 18 commits into
mainfrom
feature/traefik-gateway-api
Oct 29, 2026
Merged

lukepolo merged 18 commits into
mainfrom
feature/traefik-gateway-api

Conversation

@lukepolo

@lukepolo lukepolo commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

ingress-nginx is retired upstream; the panel now runs Traefik v3.7.16 and routes through the Gateway API.

  • Traefik installs from two charts in charts/ (gateway-crds, then gateway, a thin wrapper over the official traefik chart 42.1.3) through k3s's helm-controller, so servers need no helm binary; a workflow publishes both to oci://ghcr.io/5stackgg/charts for CodePier's Quick Install
  • Every panel Ingress is now an HTTPRoute on a 5stack Gateway (stream auth as ForwardAuth, CORS as Headers, text compression on web and api); a shared traefik/traefik-gateway takes routes from any namespace on web (80) and websecure (443)
  • Reverse-proxy installs still answer on 443 as ingress-nginx did, with self-signed certificates that renew on update, so proxies forwarding there keep working and the api's Secure session cookie still sees HTTPS
  • Leftover nginx-class Ingresses (plugins, other apps) keep working through Traefik's NGINX-compat provider, and cert-manager issues and renews through Traefik
  • update.sh takes over Gateway API CRDs a disabled k3s Traefik left behind, installs Traefik, applies the routes, hands 80/443 (or ingress-nginx's own ports) over, then removes ingress-nginx
  • k3s-in-Docker tests cover a fresh install, an upgrade from ingress-nginx, and real certificate issuance and renewal against an in-cluster Pebble

…the retired ingress-nginx

Traefik v3.7.16 is installed from charts/gateway (a wrapper around the traefik
42.1.3 chart) and charts/gateway-crds (Gateway API v1.6.3 standard + Traefik
CRDs, kept on uninstall) through k3s's helm-controller. Every panel Ingress
becomes an HTTPRoute on a 5stack Gateway; nginx-class Ingresses from plugins
and other apps keep working through Traefik's ingress-nginx provider.
update.sh hands ports 80/443 from ingress-nginx to Traefik and removes it.
…resh install and from ingress-nginx, and a workflow publishing the gateway charts to ghcr.io
…gresses, and http mode waits out the removed redirect
…s ingress-nginx did, and the gateway tests pass shellcheck and detect nginx by its install
…nt only the preflight's own path at forward-auth
…vers a failed Traefik release, a stalled handover gives nginx its ports back, and the Media Server page's stats route survives
…efik left behind, and a failed chart shows helm's error after its pod is gone

k3s's traefik-crd release keeps its CRDs when k3s runs with --disable=traefik, still marked as its, so the gateway-crds install was refused. Objects whose release is gone are handed to gateway-crds; a live release's, or ones made outside Helm, stop the install with what to do. The helm-install Job deletes its pod when it gives up, so its error is read while the pod runs, and a re-run picks reinstall from the release's status rather than from logs that are gone.
…stalled, so a second update isn't stopped by the traefik.io CRDs Traefik's chart re-creates without Helm's marks
…-nginx did, so a proxy forwarding there keeps working and logins see HTTPS

Proxies that forward to the node over HTTPS got Traefik's 404 for every panel host, because a REVERSE_PROXY install's listeners were plain HTTP only. A second Gateway, 5stack-tls, serves the same hosts on websecure with a self-signed certificate write_overlays makes once and keeps, and every route attaches to both. Behind such a proxy the api now sees X-Forwarded-Proto: https, which its Secure session cookie needs. Port 80 is unchanged. An https install removes the Gateway and its certificate.
…g behind a reverse proxy that forwards there, and both self-signed upstream certificates renew before they expire

traefik-gateway gets a websecure listener: HTTPS on every hostname, open to every namespace, on a self-signed certificate the chart makes itself (CodePier installs it without the panel's scripts). A route attaches to web and websecure to answer either way. The panel's own listeners carry their hostnames and certificates, so they keep their hosts. The chart's certificate is kept across upgrades through lookup and rendered back unchanged until it's within 30 days of the expiry its annotation records; the panel's reverse-proxy certificate is likewise replaced only when it's within 30 days of expiring or unreadable.
…s it, server-side as helm, so the upgrade's own apply doesn't conflict over the annotation
…through Traefik, from an in-cluster Pebble, on the panel's own Issuer and Certificates

A new gateway job installs cert-manager as update.sh does and runs Pebble with pebble-challtestsrv resolving every test host to Traefik, so HTTP-01 is validated over port 80 the way Let's Encrypt does it. It starts from an ingress-nginx install's 5stack-ssl, due for renewal under the Issuer that install had, runs the update, and checks the renewal and the stream certificate are Pebble-issued for every host and served on 443, that a further renewal is validated and served again, and that without the solver's router priority the https-redirect route takes the challenge path.
…o it is due when cert-manager runs again, and the pin keeps the solver off port 80, since the router priority turns out not to be what lets it win

Without the priority the solver Ingress still outranks the https-redirect route on port 80; that is now measured rather than pinned.
… the panel's hosts, since moving the solver off port 80 still issues once the ACME server follows the redirect to 443

Without the priority the solver Ingress is ranked by its rule's length, so the https-redirect route takes the challenge for some hosts and not others; the test records each host's answer and needs the redirect to win at least one and no certificate to be issued.
…their text responses

Each panel HTTPRoute gets spec.hostnames equal to the hostname of the listener it attaches to, filled by the same replacements as the listeners in the https, reverse-proxy and dev overlays, so a route reads as its host rather than *. A route's hostnames intersect with its listener's, so routing is unchanged; a rendered-overlay check holds every route to its listener's host in all three. A compress Middleware, referenced by the web route and the api route's api rule only, compresses text/html, application/json, text/css, application/javascript and image/svg+xml responses of 1024 bytes or more. Demos, clips, uploads, playcast fragments, event streams, downloads and websockets pass through untouched, and so do responses that already carry a Content-Encoding and everything Hasura serves.
…one break that stops issuance through Traefik

Two runs without the router priority still issued: once the solver pod is up its Ingress outranks the https-redirect route, and a solver on websecure is reached through the redirect, so neither annotation alone decides it on Traefik v3.7.16. With the solver on neither port, the redirect answers the challenge, the ACME server follows it to 443 where there's no solver, and the Certificate never becomes Ready.
@lukepolo
lukepolo marked this pull request as ready for review October 29, 2026 14:36
@lukepolo
lukepolo merged commit bc315cd into main Oct 29, 2026
7 checks passed
@lukepolo
lukepolo deleted the feature/traefik-gateway-api branch October 29, 2026 14:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant