Skip to content

Settings reference

Runtime configuration lives in the vaultbase_settings table — keyed by string, valued by string. Edited from the admin Settings page; values are cache-invalidated on save.

KeyTypeDefaultNotes
rate_limit.enabled"1"/"0""1"Master switch
rate_limit.rulesJSON array(defaults below)See shape below

rate_limit.rules shape:

[
{ "label": "*:auth", "max": 10, "windowMs": 3000, "audience": "all" },
{ "label": "*:create", "max": 60, "windowMs": 5000, "audience": "all" },
{ "label": "/api/*", "max": 300, "windowMs": 10000, "audience": "all" }
]

label syntax: <path>[:<action>]

  • path — exact (/api/v1/posts), prefix (/api/*), or wildcard (*)
  • actionauth, create, list, view, update, delete
  • audienceall, guest (no token), auth (any user/admin token)
KeyTypeDefault
smtp.enabled"1"/"0""0"
smtp.hoststring
smtp.portstring (int)"587"
smtp.secure"1"/"0""0"
smtp.userstring
smtp.passstring
smtp.fromstring— — e.g. "Acme" <noreply@acme.com>

Test via Settings → SMTP → Send test. The cache TTL is 30 seconds.

KeyTypeDefault
app.urlstring— — base URL of your frontend; used in {{link}}
email.verify.subjectstring"Verify your email"
email.verify.bodystring(multi-line default)
email.reset.subjectstring"Reset your password"
email.reset.bodystring(multi-line default)
email.otp.subjectstring"Your sign-in code"
email.otp.bodystring(multi-line default)

Variables in templates: {{email}}, {{token}}, {{code}} (otp only), {{link}}, {{appUrl}}, {{collection}}. Empty values fall back to the defaults.

KeyDefaultNotes
auth.otp.enabled"0" (off)Magic link / OTP flow. Requires SMTP.
auth.mfa.enabled"1" (on)TOTP enrollment. Disabling blocks new enrollment only — existing users keep working.
auth.anonymous.enabled"0" (off)POST .../anonymous
auth.impersonation.enabled"1" (on)Admin can impersonate users

Disabled features return 422 with a clear message.

HTTP API cross-origin allow-list. Edited from Settings → CORS. Empty origin list blocks all cross-origin requests (defensive default).

KeyTypeDefaultNotes
cors.originscomma-separated""* permits any origin (incompatible with credentials → silently downgraded to echoing matched origin).
cors.methodscomma-separatedGET,POST,PUT,PATCH,DELETE,OPTIONS
cors.headerscomma-separatedAuthorization,Content-Type,If-Match,X-VB-Idempotency-Key
cors.credentials"1"/"0""0"Sends Access-Control-Allow-Credentials: true.
cors.max_ageseconds"600"Preflight cache lifetime.

Cache TTL 5s; preflight is short-circuited at onRequest.

Applies to admin login + auth-collection registers. Defaults are off — only length is enforced (12 characters minimum, floor 8).

KeyTypeDefaultNotes
password.min_lengthint"12"Floor 8 (NIST 800-63B).
password.require_upper"1"/"0""0"Reject if no uppercase letter.
password.require_lower"1"/"0""0"Reject if no lowercase letter.
password.require_digit"1"/"0""0"Reject if no digit.
password.require_symbol"1"/"0""0"Reject if no non-alphanumeric character.
password.hibp_check"1"/"0""0"k-anonymity check against api.pwnedpasswords.com. Fails open on network error.

Per-email + per-IP failed-login throttle. Off by default. Per-IP keying requires security.trusted_proxies (or env) for accurate client IPs.

KeyTypeDefaultNotes
auth.lockout.max_attemptsint"0""0" = off. Lockout fires when failures within window reach this.
auth.lockout.duration_secondsint"900"Window seconds. Min 60 (15 min default).

Setting overrides VAULTBASE_TRUSTED_PROXIES env. Without either, vaultbase ignores X-Forwarded-For entirely (defensive default — prevents spoofing on direct-exposed deployments).

KeyTypeDefaultNotes
security.trusted_proxiescomma-separated CIDRs""Affects ratelimit + audit log + brute-force IP keying.

Prometheus exposition at /api/v1/metrics. Off by default. Optional bearer auth via metrics.token.

KeyTypeDefaultNotes
metrics.enabled"1"/"0""0"Master switch. 404 when off.
metrics.tokenstring""Required as Authorization: Bearer <token>. Empty = public.

Always available to admins as JSON at /_/metrics.

Admin UI accent + surface colors. Edited at Settings → Theme. Empty value falls back to the built-in default. Hex format only (#RGB, #RRGGBB, #RRGGBBAA). The login page picks up the operator’s overrides too.

KeyCSS variableDefault
theme.accent--accent#3b82f6
theme.accent_hover--accent-hover#4a8ef7
theme.accent_light--accent-light#60a5fa
theme.bg_app--bg-app#0e0f12
theme.bg_sidebar--bg-sidebar#131418
theme.bg_panel--bg-panel#181a1f
theme.text_primary--text-primary#e6e8ed
theme.text_secondary--text-secondary#9aa0ac
theme.success--success#22c55e
theme.warning--warning#f59e0b
theme.danger--danger#ef4444

Public read endpoint: GET /api/v1/admin/theme — admin SPA fetches it before mounting React.

Polls GitHub for the latest release tag. Boot delay 30 s, then every 6 h. Vaultbase never auto-updates — this is purely a notification.

KeyTypeDefaultNotes
update_check.enabled"1"/"0""1"Master switch.
update_check.latest_versionstring(cached)Last tag fetched from GitHub.
update_check.checked_atunix-seconds(cached)Last successful check.
update_check.errorstring(cached)Last fetch error, cleared on success.

Outbound helpers.http.* calls from hooks/routes/cron pass through a CIDR filter. See Hooks → Egress filter for the default deny list and DNS-rebind caveat.

KeyTypeDefaultNotes
hooks.http.denycomma-separated CIDRs(default-deny RFC1918 + link-local + loopback)Replaces defaults. off disables filtering.
hooks.http.allowcomma-separated CIDRs""Allow exceptions evaluated after deny.

Cache TTL 5s; PATCH /api/v1/admin/settings invalidates immediately.

For each of google, github, gitlab, facebook, microsoft, discord, twitch, spotify, linkedin, slack, bitbucket, notion, patreon:

KeyType
oauth2.<name>.enabled"1"/"0"
oauth2.<name>.client_idstring
oauth2.<name>.client_secretstring

A provider counts as “enabled” only when all three are set + enabled is "1".

See Push notifications for end-to-end setup.

KeyType
notifications.providers.onesignal.enabled"1"/"0"
notifications.providers.onesignal.app_idstring (UUID)
notifications.providers.onesignal.api_keystring (REST API key — encrypted at rest)
notifications.providers.fcm.enabled"1"/"0"
notifications.providers.fcm.project_idstring (optional — defaults to project_id from the service account JSON)
notifications.providers.fcm.service_accountstring (full service-account.json contents — encrypted at rest)

When VAULTBASE_ENCRYPTION_KEY is set, settings whose key matches a secret-shaped suffix are AES-GCM-encrypted before being written to vaultbase_settings and decrypted on read. The wrapper is the same vbenc:1:<iv>:<ciphertext> envelope used by encrypted record fields (core/encryption.ts), so backups + snapshots stay symmetric.

Suffixes that trigger encryption (case-insensitive): .password, .pass, .api_key, .apikey, .secret, .client_secret, .private_key, .privatekey, .access_key, .accesskey, .service_account, .token.

Without VAULTBASE_ENCRYPTION_KEY set, secret-shaped settings are stored plaintext (back-compat) and a one-time stderr warning is emitted per key. If the env var is later removed or rotated to a wrong value, reads return "" and a warning is logged.

GET /api/v1/admin/settings ← admin auth
PATCH /api/v1/admin/settings { "<key>": "<value>", ... }

PATCH is partial — keys not in the body are left untouched. Settings caches (rate-limit, SMTP) are invalidated on save.

import { getAllSettings, getSetting, setSetting } from "vaultbase/api/v1/settings";
const all = getAllSettings();
const port = parseInt(getSetting("smtp.port", "587"));
setSetting("auth.otp.enabled", "1");

Useful inside hooks/routes via ctx.helpers (which proxies a subset).