import {
DocsTitle,
DocsLead,
DocsH2,
DocsP,
DocsList,
DocsLi,
DocsCode,
Mono,
} from '@/components/docs-page';
export const metadata = { title: 'Self-hosting — BuildMyMCPServer docs' };
export default function SelfHosting() {
return (
<>
Self-hosting
The control plane and generator are open. Bring your own Postgres, Redis, Docker host and
Anthropic API key. Production uses Hetzner + Coolify + Traefik; the seams are the same.
Requirements
Node.js 20+
pnpm 9+
Docker engine reachable from the generator process
Postgres 16+ and Redis 7+ (docker-compose for dev)
Anthropic API key (optional — mock fallback for offline dev)
Local dev
cd buildmymcpserver
pnpm install
cp .env.example .env
pnpm dev`}
/>
pnpm dev loads .env, brings up Postgres and Redis via
docker-compose, pushes the Drizzle schema, and starts web (:3001), api
(:4000) and generator concurrently.
Environment variables
DATABASE_URL — Postgres connection string
REDIS_URL — Redis (BullMQ + pubsub + preview cache)
ANTHROPIC_API_KEY — unset = mock generator
SECRETS_ENCRYPTION_KEY — 32-byte hex, AES-256-GCM key
CONTROL_PLANE_PUBLIC_URL — issuer for OAuth tokens
OAUTH_KEY_DIR — where RS256 keypair lives (auto-generated on boot)
RUNNER_PORT_RANGE_START/END — host port window for generated containers
Production deployment
The intended production setup is a Hetzner AX52 running Coolify, Traefik for wildcard SSL
on *.mcp.yourdomain.com, and Cloudflare for DNS+DDoS. The runner-deploy
adapter is the only environment-specific seam — swap the Docker-CLI implementation in
apps/generator/src/lib/deploy.ts for the Coolify HTTP API.
Container sandboxing
Production flags (commented in deploy.ts):
--read-only
--cap-drop=ALL
--security-opt=no-new-privileges
--cpus=0.5 --memory=512m
Dev relaxes these for Docker Desktop on Windows compat. Don't ship dev defaults to
prod.
>
);
}