@cms0/admin reads configuration from environment variables and fails early when required values are missing.
Put production secrets in your host or platform secret manager. Do not commit .env files.
Core app
| Variable | Required | Description |
|---|---|---|
DATABASE_URL | Yes | PostgreSQL connection string |
PORT | No | App port |
CMS0_PUBLIC_APP_URL | Yes | Public admin origin |
BETTER_AUTH_URL | Yes | Auth origin, usually the same as CMS0_PUBLIC_APP_URL |
BETTER_AUTH_SECRET | Yes | Auth secret |
TRUSTED_ORIGINS | Yes | Comma-separated trusted origins |
Bootstrap admin
| Variable | Required | Description |
|---|---|---|
ADMIN_EMAIL | Recommended | First admin email |
ADMIN_PASSWORD | Recommended | First admin password |
CMS0_SELFHOST_ALLOW_SIGNUP | Yes | Enables or disables email/password signup |
Set both ADMIN_EMAIL and ADMIN_PASSWORD together. The app rejects partial bootstrap credentials.
Storage
| Variable | Required | Description |
|---|---|---|
CMS0_STORAGE_DRIVER | Yes | filesystem or s3 |
CMS0_STORAGE_PATH | With filesystem | Filesystem storage root |
CMS0_ASSET_BASE_URL | Yes | Public base URL for control-plane assets |
S3-compatible storage
| Variable | Required | Description |
|---|---|---|
CMS0_STORAGE_BUCKET | With CMS0_STORAGE_DRIVER=s3 | Bucket name |
CMS0_STORAGE_REGION | With CMS0_STORAGE_DRIVER=s3 | Bucket region |
CMS0_STORAGE_ENDPOINT | Optional | Custom endpoint for S3-compatible providers |
CMS0_STORAGE_ACCESS_KEY_ID | With CMS0_STORAGE_DRIVER=s3 | Access key id |
CMS0_STORAGE_SECRET_ACCESS_KEY | With CMS0_STORAGE_DRIVER=s3 | Secret access key |
CMS0_STORAGE_FORCE_PATH_STYLE | With S3 | Path-style toggle for compatible providers |
CMS0_STORAGE_PREFIX | Optional | Logical prefix inside the bucket |
| Variable | Required | Description |
|---|---|---|
CMS0_EMAIL_TRANSPORT | Yes | log, smtp, or plunk |
CMS0_EMAIL_FROM | Recommended | Sender email |
CMS0_EMAIL_FROM_NAME | Optional | Sender display name |
CMS0_EMAIL_REPLY_TO | Optional | Reply-to email |
CMS0_EMAIL_REPLY_TO_NAME | Optional | Reply-to display name |
SMTP
| Variable | Required | Description |
|---|---|---|
CMS0_EMAIL_SMTP_HOST | With CMS0_EMAIL_TRANSPORT=smtp | SMTP host |
CMS0_EMAIL_SMTP_PORT | With SMTP | SMTP port |
CMS0_EMAIL_SMTP_SECURE | With SMTP | SMTP TLS toggle |
CMS0_EMAIL_SMTP_USERNAME | Optional | SMTP username |
CMS0_EMAIL_SMTP_PASSWORD | Optional | SMTP password |
Plunk
| Variable | Required | Description |
|---|---|---|
CMS0_EMAIL_PLUNK_API_KEY | With CMS0_EMAIL_TRANSPORT=plunk | Plunk API key |
CMS0_EMAIL_PLUNK_BASE_URL | Optional | Custom Plunk API base URL |
OAuth
| Variable | Required | Description |
|---|---|---|
GOOGLE_CLIENT_ID | Optional | Google OAuth client ID |
GOOGLE_CLIENT_SECRET | Optional | Google OAuth client secret |
App integration values
These values usually live in the app that consumes cms0, not in @cms0/admin:
.env
CMS0_API_BASE_URL="https://admin.example.com/api/content"
CMS0_API_KEY="cms0_..."Success check
The admin app should start without missing-variable errors, and the public origin should serve both the UI and /api/content/health.