Skip to content

fix(monitoring): drop basic auth in front of beszel - #92

Merged
florianjs merged 1 commit into
mainfrom
fix/beszel-auth
Oct 20, 2026
Merged

florianjs merged 1 commit into
mainfrom
fix/beszel-auth

Conversation

@florianjs

Copy link
Copy Markdown
Owner

Problem

In production, the monitoring page kept showing the browser's login prompt, even after logging in to Beszel.

The Beszel UI sends its own session token in the Authorization header on every API call. That replaces the basic auth credentials, so Caddy answers 401 with WWW-Authenticate: Basic, and the browser asks again. Reproduced locally with Caddy + Beszel 0.21.0: log in through basic auth, then any API call with the Beszel token → 401 Www-Authenticate: Basic realm="restricted". Basic auth in front of Beszel cannot work.

Fix

  • Caddy: basic auth removed for the monitoring domain. /api/beszel/create-user is refused (403): when Beszel has no account yet, nobody can create the first one from the browser.
  • The Beszel account is created from .env on Beszel's first start (BESZEL_ADMIN_EMAIL / BESZEL_ADMIN_PASSWORD → Beszel's USER_EMAIL / USER_PASSWORD). Checked: Beszel reads them only when its data is empty and ignores them afterwards.
  • Installer:
    • asks for a monitoring login password (8+ characters, or generated), with the Let's Encrypt email as the login;
    • shows both at the end; re-runs keep them;
    • existing basic-auth installs are detected (MONITORING_PASSWORD_HASH without a Beszel login): they keep their Beszel account, and nothing is generated or asked;
    • no more Caddy hash step.
  • setup.sh: generates the same login.
  • Docs:
    • monitoring guide: how to log in, why there is no browser prompt any more, and how to recover a forgotten password or a missing account (beszel superuser upsert, then /_/);
    • getting started: the Grafana upgrade box adds the login to .env before the first start;
    • troubleshooting: a "keeps asking for a login" entry and a new forgotten-password entry;
    • env reference, configuration guide and README updated.

MONITORING_USER / MONITORING_PASSWORD_HASH are no longer used; leftover values are ignored.

Upgrading an existing install

git pull, then docker compose -f docker-compose.prod.yml up -d to recreate Caddy. Log in with the Beszel account you already created.

Test plan

  • Real Caddyfile in front of a fresh Beszel 0.21.0 seeded from the env: UI 200, login with the .env account 200, API call with the Beszel token 200 and no WWW-Authenticate, create-user from outside 403
  • Beszel behaviour: env account created on empty data only; ignored on restart with a different password; create-user 404 once an account exists
  • Recovery: superuser upsert → superuser login → user password reset → user login with the new password; /_/ reachable through Caddy
  • Installer harness in Debian 12 (non-root): 32/32. New cases: legacy basic-auth re-run (nothing asked or generated), Beszel login kept on re-run, short password asked again, --yes refuses a short MONITORING_PASSWORD, .env written with the login or commented for legacy installs
  • caddy validate, docker compose config (env passed through), shellcheck (warning level) on install.sh / setup.sh, docs build
  • Full install on a fresh VPS

🤖 Generated with Claude Code

The Beszel UI sends its own token in the Authorization header on every
API call. Caddy's basic auth rejected it with WWW-Authenticate: Basic, so
the browser asked for the monitoring password again and again.

Beszel's own login now protects it. Its account is created on the first
start from BESZEL_ADMIN_EMAIL / BESZEL_ADMIN_PASSWORD, which the installer
and setup.sh generate, and Caddy refuses /api/beszel/create-user so
nobody can claim the UI from the browser. Installs from before keep their
Beszel account; the docs explain how to recover a lost password.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 20, 2026

Copy link
Copy Markdown

Review in Change Stack →

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: cfb21dc0-243f-49d2-bddf-e395fbbea205
📥 Commits

Reviewing files that changed from the base of the PR and between 27ed11b and 73b8cd1.

📒 Files selected for processing: 11
  • .env.example
  • README.md
  • doc/guide/configuration.md
  • doc/guide/getting-started.md
  • doc/guide/monitoring.md
  • doc/guide/troubleshooting.md
  • doc/reference/env.md
  • docker-compose.prod.yml
  • docker/caddy/Caddyfile
  • scripts/install.sh
  • scripts/setup.sh
+---------------------------------------------------------------------------------------------------------------------------------------+
| Use tracer bullets to find the target. Tracer bullets let you home in on your target by trying things and seeing how close they land. |
+---------------------------------------------------------------------------------------------------------------------------------------+
  \
   \   (\__/)
       (•ㅅ•)
       /   づ
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@florianjs
florianjs merged commit c0cf3c0 into main Oct 20, 2026
1 check was pending
@florianjs florianjs mentioned this pull request Oct 29, 2026
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