Prerequisites
- Docker 20.10+ with Compose V2
- OpenRouter API key (get from openrouter.ai/keys)
- Admin key for user management (generate with
openssl rand -hex 32)
Quick Start
Clone the repository
git clone https://github.com/chocksy/cems.git
cd cems
Create environment file
Create a .env file in the project root:# Required
OPENROUTER_API_KEY=sk-or-v1-...
CEMS_ADMIN_KEY=$(openssl rand -hex 32)
# Optional (secure the database)
POSTGRES_PASSWORD=your_secure_password_here
Never commit .env to version control. Add it to .gitignore.
Start services
This will:
- Pull the
pgvector/pgvector:pg16 image
- Build
cems-server from Dockerfile
- Build
cems-mcp from mcp-wrapper/Dockerfile
- Initialize the PostgreSQL database with
deploy/init.sql
- Start all services with health checks
Verify services are running
All services should show healthy status:NAME STATUS
cems-postgres Up (healthy)
cems-server Up (healthy)
cems-mcp Up (healthy)
Check server health
curl http://localhost:8765/health
Expected response:
Service Details
PostgreSQL + pgvector
postgres:
image: pgvector/pgvector:pg16
container_name: cems-postgres
environment:
POSTGRES_USER: cems
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-cems_secure_password}
POSTGRES_DB: cems
volumes:
- postgres_data:/var/lib/postgresql/data
- ./deploy/init.sql:/docker-entrypoint-initdb.d/init.sql
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U cems"]
interval: 10s
timeout: 5s
retries: 5
Key Points:
- Uses
pgvector extension for 1536-dim vector embeddings
- Database initialized with
deploy/init.sql on first run
- Health check ensures database is ready before starting dependent services
- Data persisted in Docker volume
postgres_data
cems-server
cems-server:
build:
context: .
dockerfile: Dockerfile
container_name: cems-server
environment:
CEMS_DATABASE_URL: postgresql://cems:${POSTGRES_PASSWORD:-cems_secure_password}@postgres:5432/cems
OPENROUTER_API_KEY: ${OPENROUTER_API_KEY}
CEMS_MODE: server
CEMS_SERVER_HOST: 0.0.0.0
CEMS_SERVER_PORT: 8765
CEMS_ADMIN_KEY: ${CEMS_ADMIN_KEY}
CEMS_EMBEDDING_BACKEND: openrouter
CEMS_EMBEDDING_DIMENSION: 1536
CEMS_RERANKER_BACKEND: disabled
ports:
- "8765:8765"
depends_on:
postgres:
condition: service_healthy
Key Points:
- Python 3.12-slim base image
- Runs as non-root user
cems (UID 1000)
- Uses
uv for fast dependency installation
- Health check at
/health endpoint
- Waits for PostgreSQL to be healthy before starting
See the full Dockerfile at: ~/workspace/source/Dockerfile
cems-mcp
cems-mcp:
build:
context: ./mcp-wrapper
dockerfile: Dockerfile
container_name: cems-mcp
environment:
PYTHON_API_URL: http://cems-server:8765
PORT: 8766
ports:
- "8766:8766"
depends_on:
cems-server:
condition: service_healthy
Key Points:
- Express.js server exposing MCP-over-HTTP
- Proxies requests to
cems-server at port 8765
- Provides 6 MCP tools:
memory_add, memory_search, memory_get, memory_forget, memory_update, memory_maintenance
- Streamable HTTP transport for MCP clients
Volumes
The compose file defines two volumes:
volumes:
postgres_data: # PostgreSQL data persistence
llama_models: # (Optional) For local llama.cpp embeddings
The llama_models volume is only used if you switch to CEMS_EMBEDDING_BACKEND=llamacpp_server. By default, OpenRouter API is used.
Networking
All services run on the default Docker bridge network. Services communicate by container name:
cems-server → postgres:5432
cems-mcp → cems-server:8765
Port Mapping
| Service | Internal Port | External Port | Purpose |
|---|
| postgres | 5432 | 5432 | PostgreSQL + pgvector |
| cems-server | 8765 | 8765 | REST API + Admin API |
| cems-mcp | 8766 | 8766 | MCP-over-HTTP |
If you expose these ports to the internet, ensure you:
- Use a reverse proxy (nginx, Caddy, Traefik)
- Enable HTTPS with valid certificates
- Implement rate limiting
- Restrict access by IP if possible
Stopping Services
# Stop services (keeps data)
docker compose down
# Stop and remove volumes (DELETES ALL DATA)
docker compose down -v
Logs
# View all logs
docker compose logs -f
# View specific service
docker compose logs -f cems-server
# View last 100 lines
docker compose logs --tail=100 cems-server
Updating
Rebuild and restart
docker compose up -d --build
Troubleshooting
Services won’t start
# Check service status
docker compose ps
# Check logs for errors
docker compose logs cems-server
Common issues:
- Missing
OPENROUTER_API_KEY in .env
- Missing
CEMS_ADMIN_KEY in .env
- Port 5432/8765/8766 already in use
- Insufficient Docker resources (memory/CPU)
Database connection errors
# Check PostgreSQL logs
docker compose logs postgres
# Verify database is healthy
docker compose exec postgres pg_isready -U cems
# Connect to database manually
docker compose exec postgres psql -U cems -d cems
Health check failing
# Test health endpoint
curl http://localhost:8765/health
# Check if all environment variables are set
docker compose exec cems-server env | grep CEMS
Next Steps
Configuration
Customize environment variables
User Management
Create your first user