Drop the Traefik-level basic auth layer — keep only Hermes's own login
By request: one auth layer, not two. Note this isn't really removing a layer I added on top of nothing — Hermes's own gate is mandatory and can't be disabled while the dashboard is reachable through a separate Traefik container (it fails closed at startup on any non-loopback bind without a configured auth provider). The only thing actually optional was the Traefik-level middleware, so that's what comes out; Traefik now just does TLS termination + routing.
This commit is contained in:
+3
-6
@@ -39,16 +39,13 @@ HERMES_MATRIX_ACCESS_TOKEN=
|
|||||||
HERMES_API_SERVER_KEY=
|
HERMES_API_SERVER_KEY=
|
||||||
|
|
||||||
# --- hermes web dashboard (hermes.apps.williamturner.eu) ---
|
# --- hermes web dashboard (hermes.apps.williamturner.eu) ---
|
||||||
# Two independent auth layers: Hermes's own login (basic auth — its docs call this
|
# Hermes's own login gate — mandatory once its dashboard is bound non-loopback (needed
|
||||||
# "not suitable for direct public-internet exposure" alone) plus a Traefik-level basic
|
# for Traefik, a separate container, to reach it at all), so this can't be turned off
|
||||||
# auth gate in front of it. Both required, different credentials recommended.
|
# while the dashboard is reachable through Traefik.
|
||||||
HERMES_DASHBOARD_USERNAME=william
|
HERMES_DASHBOARD_USERNAME=william
|
||||||
HERMES_DASHBOARD_PASSWORD=
|
HERMES_DASHBOARD_PASSWORD=
|
||||||
# 32+ random bytes — `openssl rand -base64 32`
|
# 32+ random bytes — `openssl rand -base64 32`
|
||||||
HERMES_DASHBOARD_SECRET=
|
HERMES_DASHBOARD_SECRET=
|
||||||
# htpasswd-format "user:hash" for Traefik's basicauth middleware. Generate with:
|
|
||||||
# python3 -c "import crypt; print('someuser:' + crypt.crypt('somepassword', crypt.mksalt(crypt.METHOD_SHA512)))"
|
|
||||||
TRAEFIK_HERMES_AUTH_HASH=
|
|
||||||
|
|
||||||
# --- portainer (GitOps redeploy) ---
|
# --- portainer (GitOps redeploy) ---
|
||||||
PORTAINER_STACK_WEBHOOK_URL=
|
PORTAINER_STACK_WEBHOOK_URL=
|
||||||
|
|||||||
+5
-8
@@ -112,14 +112,11 @@ services:
|
|||||||
- "traefik.http.routers.hermes-dashboard.rule=Host(`${HERMES_DASHBOARD_HOSTNAME}`)"
|
- "traefik.http.routers.hermes-dashboard.rule=Host(`${HERMES_DASHBOARD_HOSTNAME}`)"
|
||||||
- "traefik.http.routers.hermes-dashboard.entrypoints=websecure"
|
- "traefik.http.routers.hermes-dashboard.entrypoints=websecure"
|
||||||
- "traefik.http.routers.hermes-dashboard.tls.certresolver=letsencrypt"
|
- "traefik.http.routers.hermes-dashboard.tls.certresolver=letsencrypt"
|
||||||
# Second, independent auth layer in front of Hermes's own login page — its docs
|
# Just TLS termination + routing — no Traefik-level auth middleware. Hermes's own
|
||||||
# explicitly call basic-auth-only "not suitable for direct public-internet
|
# login gate is not optional here anyway: it fails closed at startup once its bind
|
||||||
# exposure" and cite a real June 2026 incident where scanners reached exposed
|
# isn't loopback-only (required for Traefik, a separate container, to reach it at
|
||||||
# dashboards and drove agents into planting SSH-key backdoors. This means an
|
# all), so a second gate in front of it would only add friction, not remove Hermes's
|
||||||
# attacker has to clear Traefik's gate before ever reaching Hermes's own auth,
|
# own one. One password, at Hermes's own login page.
|
||||||
# not just guess one password.
|
|
||||||
- "traefik.http.routers.hermes-dashboard.middlewares=hermes-dashboard-auth"
|
|
||||||
- "traefik.http.middlewares.hermes-dashboard-auth.basicauth.users=${TRAEFIK_HERMES_AUTH_HASH}"
|
|
||||||
- "traefik.http.services.hermes-dashboard.loadbalancer.server.port=9119"
|
- "traefik.http.services.hermes-dashboard.loadbalancer.server.port=9119"
|
||||||
|
|
||||||
claude-agent:
|
claude-agent:
|
||||||
|
|||||||
Reference in New Issue
Block a user