Skip to main content
Run MDCMS on your own infrastructure. This guide walks you through setting up a self-hosted instance from scratch using Docker Compose.
Already have a server running? Skip to the Quick Start to install the CLI and start managing content.

Prerequisites

You need Docker and Docker Compose installed. No other runtime (Bun, Node.js) is required for running the server.
ToolVersionInstall
Docker24+docs.docker.com/get-docker
Docker Composev2+ (included with Docker Desktop)Bundled with Docker Desktop on macOS/Windows
bash brew install --cask docker

Setup

1

Get the MDCMS source

git clone https://github.com/Blazity/mdcms.git
cd mdcms
2

Configure environment variables

Copy the example environment file and review it:
cp .env.example .env
The defaults work for local evaluation. For production, you should change database credentials, S3 keys, and configure auth providers. See the environment variables section below.
3

Start all services

docker compose up -d --build
This starts:
  • MDCMS Server on port 4000 — the API backend
  • PostgreSQL 16 on port 5432 — primary database
  • Redis 7 on port 6379 — sessions and caching
  • MinIO on ports 9000/9001 — S3-compatible object storage
  • Mailhog on ports 1025/8025 — email capture (dev/staging)
Database migrations run automatically before the server starts.
4

Verify the server is healthy

curl http://localhost:4000/healthz
You should get a 200 OK response. If the server is still starting, wait a few seconds and try again.

Service Endpoints

ServiceURLPurpose
MDCMS Server APIhttp://localhost:4000Backend API — all clients connect here
MinIO Consolehttp://localhost:9001Object storage admin (default: minioadmin/minioadmin)
Mailhog UIhttp://localhost:8025Captured email viewer (auth flows, invites)
PostgreSQLlocalhost:5432Direct database access
Redislocalhost:6379Direct cache access

First Boot

After the server starts, you need to create your first user and connect the CLI.

Create an admin user

Open the Studio UI from your host app (see Embed the Studio UI below), or use the CLI to authenticate:
npx mdcms login --server-url http://localhost:4000
This opens your browser for authentication. The first user to authenticate becomes the instance owner.

Connect the CLI

Initialize a project against your server:
npx mdcms init --server-url http://localhost:4000
The init wizard walks you through project creation, environment selection, content directory scanning, and initial schema sync. See the CLI Installation guide for details.

Embed the Studio UI

Add the visual content editor to your application. Install @mdcms/studio and mount it on a catch-all route in your app. See the Integration Guide for full step-by-step instructions covering Studio embedding, MDX components, authentication, and CORS setup.

Environment Variables

Required

These must be set for the server to start. The Docker Compose defaults handle these automatically for local use.
VariableDescriptionDefault
DATABASE_URLPostgreSQL connection stringpostgresql://mdcms:mdcms@postgres:5432/mdcms
REDIS_URLRedis connection stringredis://redis:6379
S3_ENDPOINTS3-compatible storage endpointhttp://minio:9000
S3_ACCESS_KEYS3 access keyminioadmin
S3_SECRET_KEYS3 secret keyminioadmin
S3_BUCKETS3 bucket namemdcms-media

Server

VariableDescriptionDefault
PORTServer listen port4000
NODE_ENVRuntime environmentdevelopment
LOG_LEVELLog verbosity (debug, info, warn, error)info

Email

VariableDescriptionDefault
SMTP_HOSTSMTP server hostnamemailhog
SMTP_PORTSMTP server port1025
The default email configuration uses Mailhog, which captures all outgoing email without delivering it. For production, configure a real SMTP provider.

Studio

VariableDescriptionDefault
MDCMS_STUDIO_ALLOWED_ORIGINSComma-separated CORS origins for Studio embedding
MDCMS_AUTH_INSECURE_COOKIESAllow HTTP cookies (set true for local dev without HTTPS)false

Auth Providers (optional)

Configure SSO providers for your organization. Providers are enabled by presence — no feature flag is needed.
VariableDescription
MDCMS_AUTH_OIDC_PROVIDERSJSON array of OIDC provider configurations
MDCMS_AUTH_SAML_PROVIDERSJSON array of SAML provider configurations
MDCMS_AUTH_ADMIN_EMAILSComma-separated emails that get admin role on first login
[
  {
    "providerId": "okta",
    "issuer": "https://example.okta.com/oauth2/default",
    "domain": "example.com",
    "clientId": "your-client-id",
    "clientSecret": "your-client-secret"
  }
]
[
  {
    "providerId": "okta-saml",
    "issuer": "https://www.okta.com/exk123456789",
    "domain": "example.com",
    "entryPoint": "https://example.okta.com/app/example/sso/saml",
    "cert": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
    "audience": "https://cms.example.com/saml/okta-saml/sp",
    "spEntityId": "https://cms.example.com/saml/okta-saml/sp"
  }
]

Production Considerations

Security

  • Set strong, unique values for S3_ACCESS_KEY, S3_SECRET_KEY, and database credentials
  • Configure MDCMS_STUDIO_ALLOWED_ORIGINS to restrict CORS to your actual Studio host domain
  • Set NODE_ENV=production to enable secure cookie defaults and disable development features
  • Remove MDCMS_AUTH_INSECURE_COOKIES (or set to false) when running behind HTTPS
  • Replace Mailhog with a production SMTP provider

Persistence

The Docker Compose configuration uses named volumes (pgdata, miniodata) for PostgreSQL and MinIO. These persist across container restarts. To back up your data:
# Dump the database
docker compose exec postgres pg_dump -U mdcms mdcms > backup.sql

# Restore from a dump
docker compose exec -T postgres psql -U mdcms mdcms < backup.sql

Upgrading

To upgrade to a newer version of MDCMS:
git pull origin main
docker compose up -d --build
Migrations run automatically on server startup. The migration runner completes before the server accepts traffic, so there is no window where the server runs against an outdated schema.

Using an External Database

To use an existing PostgreSQL instance instead of the bundled container, set DATABASE_URL to your external connection string and remove the postgres service from docker-compose.yml. The same applies to Redis (REDIS_URL) and S3-compatible storage (S3_ENDPOINT, S3_ACCESS_KEY, S3_SECRET_KEY).

Stopping and Resetting

# Stop all services (preserves data)
docker compose down

# Stop and remove all data volumes (fresh start)
docker compose down -v

Next Steps

Quick Start

Install the CLI, define your schema, and start managing content

CLI Commands

Push, pull, login, schema sync, and all CLI flags

Studio Guide

Embed the visual content editor in your application

API Reference

REST API endpoints, authentication, and the TypeScript SDK