Skip to content

Multi-user roles

Mezzanine ships with full multi-user auth out of the box. No public-mode escape hatch — every install requires creating a first admin.

The four roles

RoleCan do
viewerRead-only. See servers, deploys, runs, metrics. Cannot trigger anything.
moderatorEverything viewer does plus trigger workflows, approve approval-gate steps.
adminEverything moderator does plus add/edit/delete servers, workflows, pools, integrations.
ownerEverything admin does plus manage other users (create, change role, delete), rotate panel-wide secrets.

The very first user created via the setup wizard becomes owner.

How enforcement works

Two layers — both apply on every request:

  1. Backend route-levelroleGate middleware in backend/src/middleware/auth.ts matches the request method + path against a per-resource allowlist. Returns 403 INSUFFICIENT_ROLE if the user’s role doesn’t meet the minimum.
  2. Frontend UI gating<Gated min="admin"> wraps buttons/forms so users without the role don’t see the affordance at all. (Defense in depth — the backend gate is the real protection; the UI gate is a UX nicety.)

Both layers stay in sync because they read from the same shared ROLE_RANK table.

Sessions

  • HTTP-only cp_session cookie, 30-day default lifetime, sliding renewal
  • Token = 256-bit random, stored in admin_sessions table
  • Logout deletes the row (server-side revocation works immediately)
  • Optional TOTP — enable in your user profile, use any TOTP app (1Password, Authy, Google Authenticator)

Password storage

  • bcrypt hashed with a per-install cost factor (default 12)
  • Never logged, never sent over the wire after the initial create / change
  • Password change requires the current password (no admin-can-set-anyone’s-password backdoor by default)

Adding users

owner only: Settings → Users → New user → username, email (optional), role, initial password. The user changes their password on first login.

Adding a moderator for self-deploy

Common pattern: create a moderator named ci or webhooks. Webhook deliveries use the workflow’s HMAC secret (no role check) but manual triggers + approvals in the UI need a logged-in user with at least moderator. So a dedicated low-privilege account for “things that should run but not configure” keeps your audit log clean.

What’s NOT included (yet)

  • SSO / SAML / OIDC — local accounts only. SAML is on the roadmap when there’s enterprise demand.
  • Per-server permissions — roles are global. A moderator can deploy any workflow, not “deploys for servers tagged staging only.” Worth doing if you have a team but the global role is usually enough.
  • Audit log UI — the activities table records everything but the UI to browse it is minimal. Improvement: add a richer audit view.