scribasedocs

Getting Started

Built-in admin login

A self-hosted control plane can verify operators in one of two ways, selected by SCRIBASE_AUTH_MODE:

Mode What signs you in Default on
builtin The control plane's own password login (argon2id, optional TOTP) The single-box layout
oidc An external identity provider with RFC 7662 token introspection (SCRIBASE_OIDC_*) Everything else

Personal access tokens, organization API keys and organization SSO sessions work in both modes. This page covers builtin.

Create the first administrator

Pick one of two options.

Option A: setup token (no secret in the env file). Leave SCRIBASE_ADMIN_EMAIL and SCRIBASE_ADMIN_PASSWORD_HASH blank. While no administrator exists, every boot prints a one-time setup token to the control-API log. Spend it from the CLI:

Terminal
docker compose -p scribase logs control-api | grep -A1 'setup token'
scribase admin setup --email you@example.com --setup-token scb_setup_...

or open the console: its sign-in page shows a Setup token form instead of the password form until an administrator exists. Setting only SCRIBASE_ADMIN_EMAIL binds the token to that address.

Option B: pre-seed the administrator. Generate a password hash and put it in the env file:

Terminal
scribase admin hash-password        # prompts twice, prints an argon2id PHC string
Terminal
SCRIBASE_ADMIN_EMAIL=you@example.com
SCRIBASE_ADMIN_PASSWORD_HASH='$argon2id$v=19$m=19456,t=2,p=1$...'

Wrap the hash in single quotes so Docker Compose keeps every $. On boot the account is created or promoted. Changing the hash later resets that administrator's password once, on the next boot. That is the break-glass path if you are locked out.

Sign in

  • Console: when the control plane can send email (see Sign in with an email link), the sign-in page leads with Email me a sign-in link; Use a password instead shows the password form. After either, an authentication code follows if the account has an authenticator app. Use a recovery code instead accepts one of the one-time recovery codes.
  • CLI: scribase login --email you@example.com prompts for the password (echo off, never from arguments) and then for a code if one is enrolled. See Login and tokens.

Security properties

  • Passwords: argon2id (19 MiB, t=2), at least 12 characters. An unknown account and a wrong password answer the same 401 after the same work.
  • Lockout and rate limits: 10 failed passwords within 15 minutes lock the account for 15 minutes (SCRIBASE_LOGIN_MAX_FAILURES, SCRIBASE_LOGIN_LOCKOUT_SECONDS). Each client address is also limited to 20 sign-in attempts per 5 minutes.
  • Two-factor: enroll an authenticator app under Account > Security. TOTP secrets are sealed with SCRIBASE_KMS_MASTER_KEY. Regenerate recovery codes on the same page.
  • Sessions: opaque scb_ses_ bearers, stored only as SHA-256 digests, with an idle timeout (default 2 hours), an absolute timeout (default 12 hours) and rotation every 15 minutes (SCRIBASE_SESSION_IDLE_SECONDS, SCRIBASE_SESSION_ABSOLUTE_SECONDS, SCRIBASE_SESSION_ROTATE_SECONDS). You can list and sign out sessions under Account > Security > Sessions.
  • Audit: every sign-in, failure, lockout, sign-out and password change is recorded (GET /v1/auth/builtin/events, administrators only).

When email is configured (webhook or box SMTP, as above), members can sign in without a password. They enter their email and get a message with a single-use link and a 6-digit code (for signing in on another device). Both expire in 15 minutes; asking again replaces the earlier ones, and a code allows at most 5 guesses.

  • The link opens SCRIBASE_CONSOLE_URL/auth/magic?token=scb_mgl_..., which only previews the link; the member clicks Continue to sign in, so mail scanners that open every URL cannot use it up.
  • The answer to a request is the same whether or not the address has an account. Requests are limited to 5 per 5 minutes per client address and per email, plus one email per address per minute.
  • A new address gets its account when the link is redeemed, if sign-up is open (SCRIBASE_PUBLIC_SIGNUP); the organization card check still applies before the first project.
  • The operator administrator never gets a link: a request for that address sends a notice to sign in with the password and second factor instead.
  • API: POST /v1/auth/builtin/magic-link/request {"email"}, .../magic-link/preview {"token"}, .../magic-link/verify {"token"} or {"email","code"}. Table: control-plane migration 0030_builtin_magic_links.sql.

Invite members

An organization owner or admin invites people by email from the console. The invitee opens the link, sets a password and joins with the invited role. The normal organization roles (owner, admin, developer, viewer) apply.

Reset a forgotten password

Reset links are single use and stored only as SHA-256 digests. Creating a new link replaces the account's earlier unused ones. Setting the new password clears any lockout and signs out every session of the account. It does not sign the member in: they sign in normally afterwards, so an authenticator app still applies.

  • Administrator-issued (always available): under Account > Security > Reset a member's password, the operator administrator enters the member's email and their own password, and gets a link valid for 24 hours to share. API: POST /v1/auth/builtin/password-resets with {"email", "admin_password"}.
  • Emailed (when a mail relay is configured): set SCRIBASE_MAIL_WEBHOOK_URL to an https:// relay that accepts {to, subject, text, html} JSON (bearer SCRIBASE_MAIL_WEBHOOK_TOKEN), the same relay that emails invitations. The sign-in page then offers Forgot your password?, which emails a link valid for 1 hour. The answer is the same whether or not the email has an account, and each address gets at most one email per minute. Without a relay, the page tells the member to ask the administrator. Instead of a webhook you can use the box SMTP relay: when SCRIBASE_MAIL_WEBHOOK_URL is unset and SCRIBASE_DEFAULT_SMTP_HOST plus SCRIBASE_DEFAULT_SMTP_ADMIN_EMAIL are set (the single-box compose passes them from SMTP_* in .env), account email goes out over SMTP (port 465 implicit TLS, any other port STARTTLS, required).

Links open SCRIBASE_CONSOLE_URL/reset-password/<token>, so set SCRIBASE_CONSOLE_URL on the control API. The reset table comes from control-plane migration 0023_builtin_password_resets.sql.

The administrator cannot create a link for their own account. If the administrator is locked out, set a new SCRIBASE_ADMIN_PASSWORD_HASH and restart (see above).

Console configuration

Build the console with SCRIBASE_AUTH_MODE=builtin and give its server SCRIBASE_API_INTERNAL_URL (for example http://127.0.0.1:8081). The console server keeps the session in a __Host- cookie (HttpOnly, Secure, SameSite=Lax) and proxies /v1 calls, checking origin and a CSRF token on every mutation. The bearer never reaches browser script. Set SCRIBASE_CONSOLE_URL to the console's public origin. For plain-HTTP local development only, set SCRIBASE_CONSOLE_INSECURE_COOKIES=1.

Automation

A CLI session ends with the timeouts above. For CI and scripts, create a personal access token with scribase token create or an organization API key (see Access tokens & API keys).