feat!: drop the built-in auth in favour of Authelia
check / check (push) Successful in 2m14s

BREAKING CHANGE: PASSWORD is gone and AUTH and CERTRESOLVER are required.
The server's compose.yaml and .env must be updated in the same deploy — the
new image ignores PASSWORD, and the old one refuses to start without it.

Authelia now sits in front of Traefik, so the app was asking for a second
password at the same door. Two prompts, and the weaker of the two was the one
holding a single shared secret with no sessions, no MFA and no revocation.
Deleting it is the whole change: Authelia already does this properly, once,
for every service on the host.

Gone: auth(), challenge(), the whole of throttle.go and its tests, and
golang.org/x/time with them. routes() returns the bare mux, /healthz is an
ordinary route on it, and the smoke script drops sixty -u flags. Roughly 230
lines removed and nothing written to replace them.

What holds the app up now, both asserted in compose.yaml:

- The router names the Authelia middleware through AUTH. Traefik takes a
  router out of service when its middleware does not resolve, so a typo or an
  unset variable fails shut rather than serving the app open.
- The container still publishes no ports, so the proxy is the only thing that
  can reach it. Publishing 8080 would now bypass authentication outright, not
  merely TLS — the comment there says so.

certresolver replaces the bare tls=true, parameterised as CERTRESOLVER: the
server had been carrying that label by hand since the first deploy. Naming a
resolver implies tls=true, so it stays one label.

TestAuth and TestHealthzSkipsAuth are replaced by one test asserting every
route answers without credentials — a 401 from here would now mean auth had
crept back in.
This commit is contained in:
Esa Kataja
2026-09-06 13:31:17 +03:00
parent 6d5f3e3de3
commit 2974ffc621
13 changed files with 159 additions and 446 deletions
+9 -3
View File
@@ -15,19 +15,25 @@ services:
- ./data:/data
environment:
PASSWORD: ${PASSWORD:?set PASSWORD in .env}
DB: /data/foodster.db
ENV: ${ENV:-prod}
TZ: ${TZ:-Europe/Helsinki}
# No published ports: Traefik reaches the container over the shared
# network. Publishing 8080 as well would put an unencrypted copy of the
# app on the host, bypassing TLS.
# app on the host, bypassing TLS — and, now that the app has no login of
# its own, bypassing authentication entirely.
#
# The middleware is the only thing standing in front of the app. If AUTH
# is unset or names a middleware Traefik does not know, Traefik takes the
# router out of service rather than serving it open, so a typo fails shut.
labels:
- traefik.enable=true
- traefik.http.routers.foodster.entrypoints=websecure
- traefik.http.routers.foodster.rule=Host(`${HOST:?set HOST in .env}`)
- traefik.http.routers.foodster.tls=true
# Naming a resolver implies tls=true, so this is one label, not two.
- traefik.http.routers.foodster.tls.certresolver=${CERTRESOLVER:?set CERTRESOLVER in .env}
- traefik.http.routers.foodster.middlewares=${AUTH:?set AUTH in .env, e.g. authelia@docker}
- traefik.http.services.foodster.loadbalancer.server.port=8080
- traefik.docker.network=traefik
networks: