Configuration
BunBase is configured through environment variables (set at startup) and runtime settings (stored in the database, editable from Studio → Settings without restarting).
Runtime settings override env-var defaults and take effect within 60 seconds. They persist across restarts. Env vars are still used for security-sensitive values (SECRET_KEY, ADMIN_SECRET) and low-level infrastructure config (ports, worker count, storage provider).
Runtime Settings (Studio → Settings)
Section titled “Runtime Settings (Studio → Settings)”These are stored in the _settings database table and configurable from Studio:
| Setting | Default | Description |
|---|---|---|
maintenance_mode | false | Return 503 for all non-admin requests |
log_level | info | Minimum log level (debug, info, warn, error, off) |
registration_open | true | Allow new user registrations |
single_session_mode | false | Revoke all other sessions on new login |
require_email_verification | false | Flag exposed on user object for use in collection rules |
lockout_max_attempts | 10 | Failed login attempts before lockout |
lockout_duration_ms | 900000 | Lockout duration in ms (default 15 min) |
access_token_ttl_seconds | 900 | Access token lifetime in seconds (15 min default) |
refresh_token_ttl_days | 30 | Refresh token lifetime in days |
auth_password_enabled | true | Allow email + password login and registration |
auth_magic_link_enabled | true | Allow passwordless magic-link login |
auth_totp_enabled | true | Allow users to set up and use TOTP 2FA |
auth_oauth_enabled | true | Allow OAuth provider login (GitHub, Google, OIDC) |
auth_api_keys_enabled | true | Allow users to create API keys |
auto_create_collections | true | Create collections on first write |
auto_create_buckets | false | Create storage buckets on first upload |
storage_cdn_url | — | Custom CDN base URL for storage downloads (e.g. https://cdn.example.com). When set, signed URLs use this domain as the base. The CDN must proxy requests to BunBase. |
app_name | — | App name used in email subjects |
app_url | — | Frontend URL used in email callback links |
email_provider | console | console, resend, or smtp |
email_from | — | Sender address override |
resend_api_key | — | Resend API key |
smtp_host, smtp_port, smtp_user, smtp_pass, smtp_secure | — | SMTP configuration |
rate_limit_public_reads | 200 | Per-IP, per-worker limit for unauthenticated reads |
rate_limit_auth | 10 | Per-IP, per-worker limit for login/register/refresh |
rate_limit_authenticated | 500 | Per-user, per-worker limit for authenticated CRUD |
rate_limit_admin | 50 | Per-IP, per-worker limit for admin API |
rate_limit_file_upload | 20 | Per-user, per-worker limit for file uploads |
backup_auto_enabled | false | Enable scheduled automatic backups |
backup_interval_minutes | 60 | How often to run an auto-backup (minutes) |
backup_keep_recent_hours | 24 | Keep every backup from the last N hours |
backup_keep_daily_days | 30 | Keep one backup per day for the last N days |
backup_compression_format | zstd | Compression format: zstd (faster, better ratio, .db.zst) or gzip (wider compat, .db.gz) |
backup_compression_level | 6 | gzip level only: 1 = fastest, 9 = smallest (ignored when format is zstd) |
backup_remote_type | none | Remote push destination: none, s3, or rsync |
backup_remote_s3_endpoint | — | S3-compatible endpoint URL (blank → AWS S3) |
backup_remote_s3_bucket | — | Destination S3 bucket name |
backup_remote_s3_region | us-east-1 | S3 region |
backup_remote_s3_prefix | — | Optional key prefix inside the bucket (e.g. backups/) |
backup_remote_s3_access_key_id | — | S3 access key ID |
backup_remote_s3_secret_access_key | — | S3 secret access key |
backup_remote_rsync_dest | — | rsync destination (e.g. user@host:/var/backups/) |
access_log_max_rows | 10000 | Max rows to keep in the access log database (oldest deleted first) |
app_log_max_rows | 10000 | Max rows to keep in the app log database (oldest deleted first) |
access_log_max_age_days | 0 | Delete access logs older than N days (0 = disabled) |
app_log_max_age_days | 0 | Delete app logs older than N days (0 = disabled) |
oauth_github_client_id | — | GitHub OAuth App client ID |
oauth_github_client_secret | — | GitHub OAuth App client secret |
oauth_google_client_id | — | Google OAuth client ID |
oauth_google_client_secret | — | Google OAuth client secret |
oauth_oidc_issuer | — | OIDC issuer URL (e.g. https://accounts.example.com) |
oauth_oidc_client_id | — | OIDC client ID |
oauth_oidc_client_secret | — | OIDC client secret |
oauth_oidc_scopes | openid email profile | Space-separated OIDC scopes |
Server
Section titled “Server”| Variable | Default | Description |
|---|---|---|
PORT | 8080 | HTTP port |
NODE_ENV | development | development, production, or test |
PUBLIC_URL | http://localhost:8080 | Backend origin — used for signed storage URLs and CORS |
APP_URL | same as PUBLIC_URL | Frontend app origin — used in email callback links (magic link, password reset, email verification). Set when your frontend runs on a different domain or port than the backend. Example: APP_URL=https://app.example.com |
DATA_DIR | ./data | Directory for SQLite database, local storage, and backups |
Security
Section titled “Security”| Variable | Default | Description |
|---|---|---|
SECRET_KEY | (dev default) | Signs JWTs and local storage tokens. Required in production. Min 32 chars. |
ADMIN_SECRET | (dev default) | Bearer token for admin API access. Required in production. |
ALLOWED_ORIGINS | * | Comma-separated CORS origins. Use * for all, or list specific origins. |
HSTS | false | Set to true to add Strict-Transport-Security header (use behind TLS). |
Workers
Section titled “Workers”| Variable | Default | Description |
|---|---|---|
WORKER_COUNT | cpu_count - 1 | Number of HTTP app workers |
HTTP_WORKERS | true | Set to false to serve HTTP from the main thread (single-process mode) |
DB_MODE | main | main = DB in orchestrator; worker = dedicated DB Worker process |
Storage
Section titled “Storage”| Variable | Default | Description |
|---|---|---|
STORAGE_PROVIDER | local | local or s3 |
S3_ENDPOINT | — | S3-compatible endpoint URL (required if STORAGE_PROVIDER=s3) |
S3_BUCKET | — | S3 bucket name |
S3_REGION | — | S3 region |
S3_ACCESS_KEY_ID | — | Also accepts AWS_ACCESS_KEY_ID |
S3_SECRET_ACCESS_KEY | — | Also accepts AWS_SECRET_ACCESS_KEY |
Redis / Valkey (optional)
Section titled “Redis / Valkey (optional)”BunBase optionally integrates with Redis or Valkey for distributed rate limiting, cross-machine realtime fanout, and session caching. All features degrade gracefully when not configured.
| Variable | Default | Description |
|---|---|---|
REDIS_URL | — | Redis connection URL (e.g. redis://localhost:6379). If unset, Bun also checks VALKEY_URL. |
VALKEY_URL | — | Valkey connection URL — identical protocol to Redis. |
When configured, enables:
- Distributed rate limiting — counters shared across all workers and machines (single true limit, no per-worker multiplication)
- Cross-machine realtime fanout — WebSocket events published via Redis Pub/Sub reach clients on any machine
- Session read cache — session existence cached in Redis, reducing DB worker RPC load on every authenticated request
See the Docker Compose file in docker/ for a ready-to-use Valkey setup.
Rate Limiting
Section titled “Rate Limiting”Limits are per-IP (or per-user for authenticated/fileUpload routes) per minute.
Without Redis: tracked independently in each worker. Effective cluster budget = limit × WORKER_COUNT.
With Redis: single shared counter across all workers and machines — limit is the true cluster-wide limit.
| Variable | Default | Key | Description |
|---|---|---|---|
RATE_LIMIT_PUBLIC_READS | 200 | per-IP | Unauthenticated GET endpoints |
RATE_LIMIT_AUTH | 10 | per-IP | Login, register, token refresh |
RATE_LIMIT_AUTHENTICATED | 500 | per-user | Authenticated CRUD and realtime |
RATE_LIMIT_ADMIN | 50 | per-IP | Admin API endpoints |
RATE_LIMIT_FILE_UPLOAD | 20 | per-user | File upload endpoints |
All five limits are also configurable at runtime from Studio → Settings → Rate Limits without restarting.
| Variable | Default | Description |
|---|---|---|
EMAIL_PROVIDER | console | console (logs to stdout) or resend |
EMAIL_FROM | BunBase <noreply@localhost> | Sender address |
RESEND_API_KEY | — | Resend API key (required if EMAIL_PROVIDER=resend) |
Account Lockout
Section titled “Account Lockout”| Variable | Default | Description |
|---|---|---|
LOCKOUT_MAX_ATTEMPTS | 10 | Failed login attempts before lockout |
LOCKOUT_DURATION_MS | 900000 | Lockout duration in ms (default 15 minutes) |
Observability
Section titled “Observability”| Variable | Default | Description |
|---|---|---|
LOG_LEVEL | info | Minimum log level: debug, info, warn, error, or off |
LOG_ACCESS | stdout | Access log destination: stdout or off |