Skip to content

Environment variables

All env vars use the SM_ prefix. Settings are loaded at boot — anything that must be known before the DB is open lives here. Runtime-tunable settings (SMTP creds, feature flags, storage backends) live in the DB-backed settings store and are edited from /settings/modules.

This is the full reference. See Configuration for a narrative overview.

Framework

VariableDefaultNotes
SM_DATABASE_URLsqlite+aiosqlite:///./app.dbRequired in production. Async URL: postgresql+asyncpg://user:pw@host:5432/db or sqlite+aiosqlite:///./app.db.
SM_ENVIRONMENTdevelopmentdevelopment and testing are the only non-prod values (placeholder-secret check is skipped for both). Any value other than development triggers strict module discovery.
SM_SECRET_KEYchange-me-in-productionMust be overridden in production — session cookie signing key.
SM_DEBUGfalseEnables debug mode (tracebacks in HTTP responses).
SM_LOG_LEVELINFODEBUG/INFO/WARNING/ERROR.
SM_LOG_FORMATjsontext for readable dev logs, json for structured logs in prod.
SM_MODULES_ENABLEDunsetComma-separated allow-list to disable modules without uninstalling them.
SM_VITE_DEV_URLhttp://localhost:5050Dev only — where the Vite HMR client connects.
SM_VITE_PORT5050Dev only — port the Vite dev server binds to (read by vite.config.ts). If you change it, set SM_VITE_DEV_URL to match so the backend points the HMR client at the right origin.
SM_AUTH_PUBLIC_PATHS[]JSON array of host-level anonymous-access path prefixes. Escape hatch for exposing a route without a session when no module owns it; modules should prefer the method-aware register_public_routes hook.

DB connection pool

VariableDefaultNotes
SM_DB_POOL_SIZE10SQLAlchemy pool_size (per process).
SM_DB_MAX_OVERFLOW20SQLAlchemy max_overflow (per process).
SM_DB_POOL_PRE_PINGtrueTest connections before use.
SM_DB_POOL_RECYCLE1800Recycle connections after N seconds (helps with LB idle drops).

Pools are per process. With multiple uvicorn --workers, total connections = workers × (SM_DB_POOL_SIZE + SM_DB_MAX_OVERFLOW); keep it under the database's max_connections (Postgres default 100) or workers raise asyncpg.TooManyConnectionsError under load. See deployment for sizing examples.

Host settings (DB-backed, not env)

Multi-tenancy and i18n configuration live in the DB-backed host settings store (HostSettings, registered under package="host"), not in env vars. Edit them in the admin UI at /settings/modules under the host section. Their defaults:

SettingDefaultNotes
multi_tenantfalseEnables TenantMiddleware + MultiTenantMixin auto-filter.
tenant_header""HTTP header that identifies the current tenant (empty = tenant middleware disabled).
i18n_default_localeenMust be in i18n_supported_locales.
i18n_supported_locales["en"]e.g. ["en", "es", "de"].
i18n_cookie_namelocaleCookie that stores the user's selected locale.

Users module

Most users settings (signup, mailer, SMTP, OAuth/OIDC credentials, rate limits) are now DB-backed — edit them in the admin UI at /settings/modules under Users, not via env vars. The env vars below are the genuine bootstrap-time exceptions read at process start.

VariableDefaultNotes
SM_USERS_BOOTSTRAP_EMAILunsetAuto-creates an admin if set and the users table is empty.
SM_USERS_BOOTSTRAP_PASSWORDunsetPaired with the email above.
SM_USERS_BOOTSTRAP_USER_EMAILunsetOptional second non-admin seed user (handy in dev).
SM_USERS_BOOTSTRAP_USER_PASSWORDunsetPaired with the user email above.
SM_USERS_RESET_PASSWORD_TOKEN_SECRETdev placeholderHMAC key for password-reset tokens. Must be overridden in production (boot fails otherwise).
SM_USERS_VERIFICATION_TOKEN_SECRETdev placeholderHMAC key for email-verification tokens. Must be overridden in production (boot fails otherwise).

Background tasks (Celery)

Celery config (broker_url, result_backend, queue, retention, etc.) is now DB-backed — edit it in the admin UI at /settings/modules under BackgroundTasks. Defaults are redis://localhost:6379/0 (broker) and /1 (result backend). Because workers read the broker/backend once at process start, changing those values requires a worker restart.

The one field still read from the environment at import time:

VariableDefaultNotes
SM_BG_TASKS_TASK_ALWAYS_EAGERfalseRun tasks synchronously in the calling process (used by tests).

File storage module

File storage config is now DB-backed — edit it in the admin UI at /settings/modules under Files. The key fields and defaults:

SettingDefaultNotes
backendfilesystemfilesystem or s3 (S3-compatible: AWS S3, MinIO, R2).
fs_root_path./uploadsFilesystem backend root directory.
s3_bucket""S3 bucket name (required when backend is s3).
s3_region""S3 region (required when backend is s3).
s3_endpoint_url""Custom endpoint for MinIO / R2; blank uses AWS default.

Patterns

Per-module prefix

Every module-owned env var uses SM_<MODULE_UPPER>_*. Keeps settings self-describing and avoids collisions.

Comma-separated lists

Pydantic parses comma-separated strings into list[str]SM_MODULES_ENABLED=users,dashboard becomes ["users", "dashboard"]. (SM_AUTH_PUBLIC_PATHS is the exception — it takes a JSON array, e.g. ["/status", "/api/webhook"].)

Booleans

true, 1, yes, onTrue. Everything else → False. Pydantic is strict — SM_DEBUG=True works, SM_DEBUG=TRUE works, but watch for whitespace.

Placeholder-secret check

In production (SM_ENVIRONMENT not in {development, testing}), boot fails if SM_SECRET_KEY == "change-me-in-production". Override before deploying.

.env files

The app loads .env via pydantic's BaseSettings. Order of precedence:

  1. Actual environment variables.
  2. .env file in the current working directory.
  3. Defaults from the Settings class.

Keep secrets out of .env.example — check in only non-secret defaults.

Module-enabled allow-list

bash
SM_MODULES_ENABLED=users,orders,dashboard

Loads only the listed modules. Useful for:

  • TestsSM_MODULES_ENABLED=users,orders for a minimal app.
  • Worker processes — if you run a Celery worker as a separate container, it only needs background_tasks and whatever modules define tasks it processes.
  • Emergency disable — hide a broken module without rebuilding the image. Remove it from the list, restart.

Released under the MIT License.