Add Authelia SSO to Frigate — disables its own login, not just a gate in front of it
Frigate has its own built-in login separate from Authelia's session, so just adding `import authelia` in front of it (the pattern used for no-built-in-auth services) would leave two independent logins stacked, defeating the point of Authelia's "remember me" on mobile. Frigate has a `proxy` auth mode built for exactly this — trust Remote-User/Remote-Groups from an upstream forward_auth proxy and disable its own login entirely. - Extend configure_caddy_for_service() with an optional 5th arg for sub-directives inside the reverse_proxy block itself (header_up), needed to pin an X-Proxy-Secret header so Frigate's proxy-auth trust can't be spoofed by a request reaching its published port directly, bypassing Caddy/Authelia. Backward compatible — every other caller is unaffected. - services/frigate.sh: prompt to protect with Authelia when installed; wires import authelia + the X-Proxy-Secret header_up into Caddy, and only writes config.yml's auth.enabled: False + proxy block once Caddy actually confirms it's fronting the domain (never disables the native login with nothing else gating access). Reuses the secret across reinstalls instead of rotating it. Calls _authelia_scope_access() so access can be restricted to specific users instead of every Authelia account. Fixed a latent bug in the standalone-mode Caddy stub where the auth block was placed after reverse_proxy instead of before it (dead code — the same "Authelia never prompts" bug class CLAUDE.md documents for the real helper). - CLAUDE.md: document the new configure_caddy_for_service parameter and Frigate's hybrid built-in-auth/forward_auth pattern. Verified end-to-end against a local test harness (fake Authelia/Caddy dirs): config.yml, .env, and the generated Caddyfile block all agree on the shared secret and header names, auth is skipped cleanly when Caddy isn't configured, and the secret is reused on a second run. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SpKTLpwAgZNooTacWeQLuc
This commit is contained in:
@@ -191,13 +191,25 @@ pip_user_install PACKAGE... # pip3 --user with --break-system-packages o
|
||||
### Caddy reverse proxy
|
||||
|
||||
```bash
|
||||
configure_caddy_for_service "Display Name" "PORT" "default-subdomain" ["extra-block"]
|
||||
configure_caddy_for_service "Display Name" "PORT" "default-subdomain" ["extra-block"] ["reverse_proxy-extra"]
|
||||
```
|
||||
|
||||
Prompts the user for a domain, appends a site block to the Caddyfile, and
|
||||
reloads Caddy. No-ops silently if Caddy isn't installed. The fourth argument
|
||||
is an optional string inserted verbatim inside the Caddy site block (use it
|
||||
for `import authelia` or custom matchers).
|
||||
is an optional string inserted verbatim inside the Caddy site block, before
|
||||
`reverse_proxy` (use it for `import authelia` or custom matchers). The fifth
|
||||
argument is a different thing — an optional string inserted **inside** the
|
||||
`reverse_proxy` block itself, as sub-directives (e.g.
|
||||
`" header_up X-Proxy-Secret abc123"`), for a backend that needs a
|
||||
header only `reverse_proxy`'s own `header_up` can set — the fourth
|
||||
argument's block runs *before* `reverse_proxy` and can't reach into it.
|
||||
`services/frigate.sh` is the reference caller: Frigate's `proxy` auth mode
|
||||
trusts `Remote-User`/`Remote-Groups` headers from Authelia's forward_auth,
|
||||
but only if a matching `X-Proxy-Secret` header is also present — otherwise
|
||||
those headers could be spoofed by a request that reaches Frigate's
|
||||
published host port directly, bypassing Caddy/Authelia entirely. Omit the
|
||||
fifth argument and the generated `reverse_proxy` line is the same bare form
|
||||
as before — every other caller is unaffected.
|
||||
|
||||
The function places that block **before** `reverse_proxy` in the generated
|
||||
site block — don't reorder this. `forward_auth` (what `import authelia`
|
||||
@@ -245,14 +257,19 @@ forward_auth https://auth.example.com {
|
||||
This only affects the remote-Authelia path — same-machine `authelia:9091`
|
||||
snippets (`services/authelia.sh`) are a single hop and don't need it.
|
||||
|
||||
Sets two out-params (not `local` — read them after the call returns) so the
|
||||
caller can tell whether Caddy actually ended up fronting the service:
|
||||
Sets three out-params (not `local` — read them after the call returns) so
|
||||
the caller can tell whether Caddy actually ended up fronting the service:
|
||||
|
||||
```bash
|
||||
CADDY_SERVICE_CONFIGURED # true/false
|
||||
CADDY_SERVICE_MODE # "local" or "remote" (only meaningful if configured)
|
||||
CADDY_SERVICE_DOMAIN # the domain actually configured (only meaningful if configured)
|
||||
```
|
||||
|
||||
`CADDY_SERVICE_DOMAIN` is what `_authelia_scope_access()` (see below) wants
|
||||
as its `DOMAIN` argument — read it right after the call instead of
|
||||
recomputing/guessing the domain a second time.
|
||||
|
||||
Use this to skip opening a host firewall port for a service Caddy already
|
||||
fronts *locally* (it reaches the service over `host.docker.internal`, not
|
||||
the network) — but still open it when `CADDY_SERVICE_MODE` is `"remote"`,
|
||||
@@ -461,6 +478,30 @@ for Authelia to protect. Removed from this list; if it grows a web UI in
|
||||
the future, add it back and wire up the same prompt other services here
|
||||
use.
|
||||
|
||||
**`frigate` — a third pattern, neither of the two above.** Frigate *does*
|
||||
have built-in auth (username/password, `admin`/`viewer` roles, on by
|
||||
default) so it isn't "no built-in auth" — but unlike the has-built-in-auth
|
||||
list, that auth is designed to be handed off to an upstream proxy instead
|
||||
of just living alongside it. Frigate has its own `proxy` auth mode built
|
||||
specifically for Authelia/Authentik/oauth2_proxy/traefik-forward-auth:
|
||||
given trusted `Remote-User`/`Remote-Groups` headers it can skip its own
|
||||
login screen entirely (`auth.enabled: False`), rather than showing a
|
||||
second, independently-expiring login *after* Authelia's. `services/frigate.sh`
|
||||
wires this up: `import authelia` (fourth arg) plus a
|
||||
`header_up X-Proxy-Secret <secret>` (fifth arg, see
|
||||
`configure_caddy_for_service` above) into the reverse_proxy block, with
|
||||
the matching `proxy.auth_secret`/`header_map`/`default_role: admin` block
|
||||
written into `config/config.yml` — and only written at all once
|
||||
`CADDY_SERVICE_CONFIGURED` confirms Caddy actually ended up fronting the
|
||||
domain, so Frigate's own login is never disabled with nothing else in
|
||||
front of it. `default_role: admin` (default in this repo's install) means
|
||||
anyone who passes Authelia gets full access, same as the login it
|
||||
replaces; use `proxy.role_map`/Authelia groups instead if some users
|
||||
should be view-only. Reuses the same `FRIGATE_PROXY_AUTH_SECRET` on
|
||||
reinstall (from `.env` via `ENV_MAP`, the same array `_frigate_parse_existing`
|
||||
already builds) rather than rotating it and breaking the existing Caddy
|
||||
pairing.
|
||||
|
||||
For services without built-in auth, prompt the user before calling
|
||||
`configure_caddy_for_service` and pass `import authelia` as the extra block
|
||||
if Authelia is installed and the user wants SSO protection:
|
||||
|
||||
Reference in New Issue
Block a user