This repository ships with a production Dockerfile for self-hosted or operator-managed deployments.
- built Nuxt/Nitro server output
- generated
.contentrainassets required by the UI string/content client gitin the runtime container for repository operations- non-root
studiouser
The container listens on port 3000.
Official container images are published to GHCR on every v* tag by the release workflow.
docker pull ghcr.io/contentrain/studio:v0.1.0-beta.7Available image tags for each release:
:vX.Y.Zand:vX.Y.Z-prerelease.N— exact release pin (recommended for production):sha-<shortsha>— immutable commit pin:X.Y,:X,:latest— floating tags, stable releases only
Prereleases do not publish :latest. See RELEASING.md for the full image-tag policy.
Self-hosters should pin to an exact vX.Y.Z tag rather than :latest so upgrades are explicit.
docker build -t contentrain-studio .Use this path for local iteration, forks, and patched builds. Production self-hosts should prefer the pre-built GHCR image above.
docker run \
--name contentrain-studio \
--env-file .env \
-p 3000:3000 \
contentrain-studioHealth endpoint:
GET /api/health
At minimum, production requires NUXT_SESSION_SECRET plus one provider pair:
Supabase pair (default):
NUXT_SUPABASE_URLNUXT_SUPABASE_SERVICE_ROLE_KEYNUXT_SUPABASE_ANON_KEY
Managed + postgres pair (plain PostgreSQL — set NUXT_AUTH_PROVIDER=managed, NUXT_DATABASE_PROVIDER=postgres):
NUXT_POSTGRES_URLNUXT_AUTH_JWT_SECRETNUXT_SESSION_PASSWORDNUXT_OAUTH_GITHUB_CLIENT_ID/NUXT_OAUTH_GITHUB_CLIENT_SECRETNUXT_RESEND_API_KEY
Depending on enabled surfaces, you may also need:
- GitHub App credentials
- Anthropic API key
- Resend sender configuration
- Stripe keys
- R2 credentials
- Redis URL
See ../.env.example and SELF_HOSTING.md.
- Persist your environment outside the image
- Use
rediss://for Redis when crossing untrusted networks - Terminate TLS at a reverse proxy or platform load balancer
- Keep the container stateless; database, object storage, Redis, and SMTP stay external
- If you rotate
NUXT_SESSION_SECRET, also setNUXT_SESSION_SECRET_PREVIOUSduring the migration window
Your reverse proxy should:
- forward HTTPS traffic to port
3000 - preserve
Hostand standard forwarding headers - set a sane request body limit for uploads
- avoid caching authenticated application routes
Before shipping a Docker deployment:
pnpm release:checkThe full release flow, image-tag policy, and GitHub Actions automation are documented in RELEASING.md.