Self-hosting means you run @cms0/admin yourself.
The admin app gives you the editor UI, runtime API, schema snapshots, API keys, backups, triggers, and usage views.
What you run
@cms0/admin- PostgreSQL
- filesystem or S3-compatible storage
- email delivery for account and invitation flows
- a reverse proxy with HTTPS
Local first run
From this repository:
pnpm install
cp apps/admin/.env.example apps/admin/.env.localEdit apps/admin/.env.local and set at least:
DATABASE_URL="postgres://postgres:password@localhost:5432/cms0"
BETTER_AUTH_SECRET="replace-with-a-long-random-secret"
BETTER_AUTH_URL="http://localhost:3000"
CMS0_PUBLIC_APP_URL="http://localhost:3000"
TRUSTED_ORIGINS="http://localhost:3000,http://127.0.0.1:3000"
ADMIN_EMAIL="[email protected]"
ADMIN_PASSWORD="replace-with-a-local-password"
ORG_NAME="Acme Inc."
CMS0_STORAGE_DRIVER=filesystem
CMS0_STORAGE_PATH=./storage
CMS0_ASSET_BASE_URL="http://localhost:3000"
CMS0_EMAIL_TRANSPORT=logThen start the admin:
pnpm dev:adminThe local admin opens at http://localhost:3000.
Docker first run
To run the admin and Postgres through Docker Compose instead:
cp deploy/docker/admin.env.example deploy/docker/admin.env
pnpm docker:admin:build
pnpm docker:admin:upEdit deploy/docker/admin.env before using the stack outside local development.
The Compose stack stores database and admin storage data in named Docker volumes.
ADMIN_EMAIL and ADMIN_PASSWORD create the first admin account during
startup. After that, new self-hosted operator accounts are invite-only:
send a team invitation from the Team settings page, then let the invitee
create their account from that invitation link.
Setup order
Create a Postgres database
Set DATABASE_URL to the database used by @cms0/admin.
Choose storage
Use filesystem storage for local or single-host deployments, or S3-compatible storage for movable containers.
Configure auth and origins
Set CMS0_PUBLIC_APP_URL, BETTER_AUTH_URL, BETTER_AUTH_SECRET, and TRUSTED_ORIGINS.
Bootstrap the first admin
Set ADMIN_EMAIL and ADMIN_PASSWORD, start the app, then sign in.
Create an API key
Point your app and cms0.config.ts at the runtime URL ending in /api/content.
Runtime URL
For a local admin running on port 3000, the runtime API base URL is:
http://localhost:3000/api/contentIn production, use your admin origin:
https://cms.example.com/api/contentSelf-hosted app integrations still use @cms0/cms0; only the runtime base URL changes.
License note
The app integration workspaces use the Apache License 2.0. apps/admin, @cms0/admin-server, and @cms0/db-schema-ops use the GNU Affero General Public License v3.0 or later. See License for the workspace map.
Success check
Your self-hosted instance is ready when:
- you can sign in as the bootstrap admin
/api/healthresponds through the deployed origin- you can create an API key
/api/content/healthresponds when called with a valid API keypnpm exec cms0 buildpublishes a schema into the admin UI