Skip to Content
New to cms0? Start with the hosted, self-hosted, or app integration path.
Self-hostingEnvironment variables

@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

VariableRequiredDescription
DATABASE_URLYesPostgreSQL connection string
PORTNoApp port
CMS0_PUBLIC_APP_URLYesPublic admin origin
BETTER_AUTH_URLYesAuth origin, usually the same as CMS0_PUBLIC_APP_URL
BETTER_AUTH_SECRETYesAuth secret
TRUSTED_ORIGINSYesComma-separated trusted origins

Bootstrap admin

VariableRequiredDescription
ADMIN_EMAILRecommendedFirst admin email
ADMIN_PASSWORDRecommendedFirst admin password
ORG_NAMEYesOrganization name created for the first admin

Set both ADMIN_EMAIL and ADMIN_PASSWORD together. The app rejects partial bootstrap credentials.

The bootstrap admin is created directly from ADMIN_EMAIL and ADMIN_PASSWORD. New operator accounts are invite-only after startup. Send a team invitation from the admin UI; email/password signup and Google signup both require a valid pending invitation whose email matches the account email.

Storage

VariableRequiredDescription
CMS0_STORAGE_DRIVERYesfilesystem or s3
CMS0_STORAGE_PATHWith filesystemFilesystem storage root
CMS0_ASSET_BASE_URLYesPublic base URL for uploaded runtime assets

S3-compatible storage

VariableRequiredDescription
CMS0_STORAGE_BUCKETWith CMS0_STORAGE_DRIVER=s3Bucket name
CMS0_STORAGE_REGIONWith CMS0_STORAGE_DRIVER=s3Bucket region
CMS0_STORAGE_ENDPOINTOptionalCustom endpoint for S3-compatible providers
CMS0_STORAGE_ACCESS_KEY_IDWith CMS0_STORAGE_DRIVER=s3Access key id
CMS0_STORAGE_SECRET_ACCESS_KEYWith CMS0_STORAGE_DRIVER=s3Secret access key
CMS0_STORAGE_FORCE_PATH_STYLEWith S3Path-style toggle for compatible providers
CMS0_STORAGE_PREFIXOptionalLogical prefix inside the bucket

Email

VariableRequiredDescription
CMS0_EMAIL_TRANSPORTYeslog, smtp, or plunk
CMS0_EMAIL_FROMRecommendedSender email
CMS0_EMAIL_FROM_NAMEOptionalSender display name
CMS0_EMAIL_REPLY_TOOptionalReply-to email
CMS0_EMAIL_REPLY_TO_NAMEOptionalReply-to display name

SMTP

VariableRequiredDescription
CMS0_EMAIL_SMTP_HOSTWith CMS0_EMAIL_TRANSPORT=smtpSMTP host
CMS0_EMAIL_SMTP_PORTWith SMTPSMTP port
CMS0_EMAIL_SMTP_SECUREWith SMTPSMTP TLS toggle
CMS0_EMAIL_SMTP_USERNAMEOptionalSMTP username
CMS0_EMAIL_SMTP_PASSWORDOptionalSMTP password

Plunk

VariableRequiredDescription
CMS0_EMAIL_PLUNK_SECRET_KEYWith CMS0_EMAIL_TRANSPORT=plunkPlunk server-side secret key
CMS0_EMAIL_PLUNK_BASE_URLOptionalCustom Plunk API base URL

OAuth

VariableRequiredDescription
GOOGLE_CLIENT_IDOptionalGoogle OAuth client ID
GOOGLE_CLIENT_SECRETOptionalGoogle OAuth client secret

When Google OAuth is configured, existing operators can continue with Google from the login page. New Google accounts are created only from a valid invitation link.

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/health.