Self-Hosting

Self-Hosting

Run ApexMCP on your own infrastructure. Full Docker Compose stack — all services included.

Prerequisites

  • Docker Engine 24+
  • Docker Compose v2 (docker compose not docker-compose)
  • openssl (for generating secrets)
  • 4 GB RAM minimum (8 GB recommended for production)
  • Linux (amd64 or arm64) or macOS

Request Access

ApexMCP community images are hosted on GitHub Container Registry (GHCR) and require access approval.

To request access:

Email sales@apexmcp.ai with subject Self-Hosting Access Request and include:

  • Your GitHub username
  • Your intended use (personal / startup / enterprise)

We’ll grant read access to ghcr.io/andrcami/apexmcp-community/* within 1 business day and send you the .env.example template.

Quick Install

Once access is granted, authenticate with GHCR using your GitHub token:

echo YOUR_GITHUB_TOKEN | docker login ghcr.io -u YOUR_GITHUB_USERNAME --password-stdin

Then download and start the stack:

curl -o docker-compose.yml https://apexmcp.ai/install/docker-compose.yml
curl -o .env.example https://apexmcp.ai/install/.env.example
cp .env.example .env
# Edit .env with your values (see Required Environment Variables below)
docker compose up -d

Default dashboard: http://localhost:3000

Community docker-compose.yml

version: "3.9"
services:
  web:
    image: ghcr.io/andrcami/apexmcp-community/web:latest
    ports: ["3000:3000"]
    env_file: .env
    depends_on: [gateway, postgres, redis]
 
  gateway:
    image: ghcr.io/andrcami/apexmcp-community/gateway:latest
    ports: ["4000:4000"]
    env_file: .env
    depends_on: [postgres, redis]
 
  connector-service:
    image: ghcr.io/andrcami/apexmcp-community/connector-service:latest
    env_file: .env
    depends_on: [postgres, redis, credential-vault]
 
  mcp-manager:
    image: ghcr.io/andrcami/apexmcp-community/mcp-manager:latest
    env_file: .env
    depends_on: [postgres, redis]
 
  credential-vault:
    image: ghcr.io/andrcami/apexmcp-community/credential-vault:latest
    env_file: .env
    depends_on: [postgres]
 
  identity-broker:
    image: ghcr.io/andrcami/apexmcp-community/identity-broker:latest
    env_file: .env
    depends_on: [postgres]
 
  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: apexmcp
      POSTGRES_USER: apexmcp
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
 
  redis:
    image: redis:7-alpine
    volumes:
      - redis_data:/data
 
volumes:
  postgres_data:
  redis_data:

Required Environment Variables

Copy .env.example and fill in:

cp .env.example .env

Core

VariableDescription
NEXTAUTH_SECRETRandom 32-byte secret for session signing
NEXTAUTH_URLPublic URL of the web dashboard (e.g. https://app.example.com)
DATABASE_URLPostgreSQL connection string for main app database

Gateway

VariableDescription
GATEWAY_JWT_SECRETSecret for signing internal JWTs
GATEWAY_PORTGateway listen port (default 4000)

Zitadel (Identity)

VariableDescription
ZITADEL_DOMAINFQDN for Zitadel (e.g. auth.example.com)
ZITADEL_ADMIN_PASSWORDInitial admin password
ZITADEL_MASTERKEY32-character Zitadel master key

Credential Vault

VariableDescription
VAULT_ENCRYPTION_KEYAES-256 key for credential encryption (base64, 32 bytes)
VAULT_DATABASE_URLSeparate PostgreSQL database for encrypted credentials

Stripe (optional — disable billing for self-hosted)

VariableDescription
STRIPE_SECRET_KEYStripe secret key — omit or leave blank to disable billing
STRIPE_WEBHOOK_SECRETStripe webhook signing secret

License (Enterprise only)

VariableDescription
LICENSE_KEYEnterprise license key from ApexMCP sales
LICENSE_SERVER_URLLicense validation endpoint (default: https://license.apexmcp.ai)

Community edition runs without a license key but is limited to 3 connectors and 10,000 tool calls/month. Contact sales@apexmcp.ai for enterprise licensing.

Post-Install: Zitadel OAuth Setup

After starting the stack, configure the OAuth application in Zitadel:

  1. Open http://localhost:8080 (Zitadel admin)
  2. Log in with credentials printed by install.sh
  3. Go to Projects → ApexMCP → Applications
  4. Note the Client ID and Client Secret
  5. Add to .env:
ZITADEL_CLIENT_ID=<from step 4>
ZITADEL_CLIENT_SECRET=<from step 4>
ZITADEL_ISSUER=http://localhost:8080
  1. Restart the web service:
docker compose restart web

Services and Ports

ServiceContainerDefault Port
Web Dashboardweb3000
Docsdocs3001
Gatewaygateway4000
Connector Serviceconnector-service4001
MCP Managermcp-manager4002
Credential Vaultcredential-vault4003
Identity Brokeridentity-broker4004
License Serverlicense-server4005
Zitadelzitadel8080
PostgreSQLpostgres5432
Redisredis6379

Upgrading

docker compose pull
docker compose up -d

Zero-downtime for stateless services. Database migrations run automatically on container start.

To check for available updates:

docker compose images

Backup

Back up these volumes:

  • postgres_data — main application database
  • vault_postgres_data — encrypted credentials
  • zitadel_data — identity and user data
docker compose exec postgres pg_dumpall -U postgres > backup-$(date +%Y%m%d).sql

Getting a License Key

The community edition is open-source and free for self-hosting with limits.

For enterprise features (unlimited connectors, SSO, audit export, SLA, priority support):

Contact sales@apexmcp.ai or see pricing for plan details.

Enterprise license keys are tied to your domain and validated against the ApexMCP license server at startup (with a 7-day grace cache for air-gapped environments).