Documentation Index
Fetch the complete documentation index at: https://docs.ctrlplane.dev/llms.txt
Use this file to discover all available pages before exploring further.
Ctrlplane is self-hosted and can be deployed on your infrastructure. This guide
covers production-ready deployment options for platform teams.
Deployment Options
| Option | Best For | Maintenance |
|---|
| Kubernetes | Production self-hosted deployments | Self-managed |
| Docker Compose | Development and evaluation | Self-managed |
Self-Hosted Options
Choose the deployment method that best fits your infrastructure:
Docker Compose (Development & Testing)
Best for: Local development, testing, small teams
Prerequisites:
- Docker Engine 20.10+
- Docker Compose v2.0+
- 2GB RAM minimum
Quick Start:
- Clone the repository:
git clone https://github.com/ctrlplanedev/ctrlplane.git
cd ctrlplane
- Copy environment files:
cp .env.example .env
# Edit .env with your configuration
- Start services:
- Run database migrations:
docker compose exec api pnpm --filter @ctrlplane/db migrate
- Access Ctrlplane:
Services Started:
- Web UI (port 3000)
- API Server (port 4000)
- Workspace Engine (port 50051)
- PostgreSQL (port 5432)
- Redis (optional, for job queue)
Configuration:
Key environment variables in .env:
# Database
DATABASE_URL=postgresql://user:password@postgres:5432/ctrlplane
# Authentication
AUTH_SECRET=your-secret-key-change-this
NEXTAUTH_URL=http://localhost:3000
# API Keys
API_KEY_SALT=your-api-key-salt
# GitHub OAuth (optional)
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
Updating:
git pull
docker compose pull
docker compose up -d
Kubernetes (Production)
Best for: Production deployments, high availability
Prerequisites:
- Kubernetes cluster 1.24+
- kubectl configured
- Helm 3.8+
- PostgreSQL database (managed or in-cluster)
Installation with Helm:
- Add the Ctrlplane Helm repository:
helm repo add ctrlplane https://charts.ctrlplane.dev
helm repo update
- Create a namespace:
kubectl create namespace ctrlplane
- Create a values file
values.yaml:
# Basic configuration
ingress:
enabled: true
hostname: ctrlplane.example.com
tls:
enabled: true
secretName: ctrlplane-tls
# Database configuration (use managed DB in production)
postgresql:
enabled: false # Set to true for embedded PostgreSQL
external:
host: your-postgres-host
port: 5432
database: ctrlplane
username: ctrlplane
existingSecret: ctrlplane-db-secret # Contains password
# API Server
api:
replicaCount: 2
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
# Workspace Engine
workspaceEngine:
replicaCount: 2
resources:
requests:
memory: "1Gi"
cpu: "1000m"
limits:
memory: "2Gi"
cpu: "2000m"
# Web UI
web:
replicaCount: 2
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
# Authentication
auth:
secret: your-auth-secret
providers:
github:
enabled: true
clientId: your-github-client-id
existingSecret: github-oauth-secret
# Redis (for job queue)
redis:
enabled: true
auth:
enabled: true
existingSecret: redis-secret
- Create secrets:
# Database password
kubectl create secret generic ctrlplane-db-secret \
--from-literal=password=your-db-password \
-n ctrlplane
# GitHub OAuth (if enabled)
kubectl create secret generic github-oauth-secret \
--from-literal=client-secret=your-github-client-secret \
-n ctrlplane
# Redis password
kubectl create secret generic redis-secret \
--from-literal=password=your-redis-password \
-n ctrlplane
- Install the chart:
helm install ctrlplane ctrlplane/ctrlplane \
--namespace ctrlplane \
--values values.yaml
- Run database migrations:
kubectl run migrate --rm -it --restart=Never \
--image=ctrlplane/api:latest \
--namespace ctrlplane \
--env="DATABASE_URL=$DATABASE_URL" \
-- pnpm --filter @ctrlplane/db migrate
- Verify installation:
kubectl get pods -n ctrlplane
kubectl get svc -n ctrlplane
Accessing Ctrlplane:
If you configured ingress:
# Should be accessible at your configured hostname
https://ctrlplane.example.com
If using port-forward for testing:
kubectl port-forward -n ctrlplane svc/ctrlplane-web 3000:80
# Access at http://localhost:3000
Updating:
helm repo update
helm upgrade ctrlplane ctrlplane/ctrlplane \
--namespace ctrlplane \
--values values.yaml
Manual Installation
For custom deployments, you can run each component separately.
Components:
-
PostgreSQL Database (required)
- Version: 14+
- Extensions: uuid-ossp, pgcrypto
-
API Server
docker run -d \
--name ctrlplane-api \
-p 4000:4000 \
-e DATABASE_URL=postgresql://... \
-e AUTH_SECRET=your-secret \
ctrlplane/api:latest
-
Workspace Engine
docker run -d \
--name ctrlplane-workspace-engine \
-p 50051:50051 \
-e DATABASE_URL=postgresql://... \
ctrlplane/workspace-engine:latest
-
Web UI
docker run -d \
--name ctrlplane-web \
-p 3000:3000 \
-e API_URL=http://localhost:4000 \
ctrlplane/web:latest
-
Run Migrations
docker run --rm \
-e DATABASE_URL=postgresql://... \
ctrlplane/api:latest \
pnpm --filter @ctrlplane/db migrate
Configuration
Environment Variables
API Server
# Database
DATABASE_URL=postgresql://user:pass@host:5432/ctrlplane
# Authentication
AUTH_SECRET=random-secret-key
API_KEY_SALT=random-salt-for-api-keys
# GitHub OAuth (optional)
GITHUB_CLIENT_ID=your-client-id
GITHUB_CLIENT_SECRET=your-client-secret
# Logging
LOG_LEVEL=info
# OpenTelemetry (optional) - To fully disable OTEL, set OTEL_SDK_DISABLED=true
OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4318
Workspace Engine
# Database
DATABASE_URL=postgresql://user:pass@host:5432/ctrlplane
# gRPC Server
WORKSPACE_ENGINE_HOST=0.0.0.0
WORKSPACE_ENGINE_PORT=50051
# Logging
LOG_LEVEL=info
Web UI
# API endpoint
NEXT_PUBLIC_API_URL=https://api.ctrlplane.example.com
# Authentication
NEXTAUTH_URL=https://ctrlplane.example.com
NEXTAUTH_SECRET=same-as-auth-secret
Database Setup
Create Database:
CREATE DATABASE ctrlplane;
CREATE USER ctrlplane WITH PASSWORD 'your-password';
GRANT ALL PRIVILEGES ON DATABASE ctrlplane TO ctrlplane;
Enable Extensions:
\c ctrlplane
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
Run Migrations:
DATABASE_URL=postgresql://ctrlplane:password@localhost:5432/ctrlplane \
pnpm --filter @ctrlplane/db migrate
Authentication Setup
GitHub OAuth
-
Create a GitHub OAuth App:
- Go to GitHub Settings → Developer settings → OAuth Apps
- New OAuth App
- Homepage URL:
https://ctrlplane.example.com
- Callback URL:
https://ctrlplane.example.com/api/auth/callback/github
-
Configure environment variables:
GITHUB_CLIENT_ID=your-client-id
GITHUB_CLIENT_SECRET=your-client-secret
API Keys
API keys are used for programmatic access (CI/CD integration).
Generate salt for API keys:
Set in environment:
API_KEY_SALT=generated-salt
Users can generate API keys in the UI under Settings → API Keys.
Resource Requirements
Minimum (Development/Testing)
- CPU: 2 cores
- RAM: 4GB
- Disk: 20GB
- Database: Shared PostgreSQL
Recommended (Small Production)
- CPU: 4-8 cores
- RAM: 8-16GB
- Disk: 50GB SSD
- Database: Managed PostgreSQL (2 vCPU, 8GB RAM)
Scaling (Large Production)
- API Server: 2-4 replicas (2 vCPU, 2GB RAM each)
- Workspace Engine: 2-4 replicas (2 vCPU, 4GB RAM each)
- Web UI: 2+ replicas (1 vCPU, 1GB RAM each)
- Database: Managed PostgreSQL (4+ vCPU, 16+ GB RAM)
- Redis: Managed Redis (optional, for job queue)
High Availability
For production deployments:
- Multiple Replicas: Run 2+ replicas of each service
- Managed Database: Use managed PostgreSQL with automated backups
- Load Balancing: Use Kubernetes service or external load balancer
- Health Checks: Configure liveness and readiness probes
- Monitoring: Set up observability with metrics and logs
- Backups: Regular database backups
Upgrades
Before Upgrading
-
Backup Database: Always backup before upgrading
pg_dump -h localhost -U ctrlplane ctrlplane > backup.sql
-
Check Release Notes: Review breaking changes
-
Test in Staging: Test upgrade in non-production environment
Upgrade Process
Docker Compose:
docker compose down
git pull
docker compose pull
docker compose up -d
Kubernetes:
helm repo update
helm upgrade ctrlplane ctrlplane/ctrlplane \
--namespace ctrlplane \
--values values.yaml
Rollback
Docker Compose:
git checkout previous-tag
docker compose up -d
psql < backup.sql # Restore database if needed
Kubernetes:
helm rollback ctrlplane -n ctrlplane
Troubleshooting
Cannot connect to database
- Verify DATABASE_URL is correct
- Check database is running and accessible
- Verify credentials and database exists
Migrations fail
- Ensure database user has proper permissions
- Check for schema conflicts
- Review migration logs
Services won’t start
- Check logs:
docker compose logs or kubectl logs
- Verify all environment variables are set
- Ensure ports are not already in use
Authentication not working
- Verify AUTH_SECRET is set and consistent across services
- Check OAuth configuration if using GitHub
- Review callback URLs match your domain
Next Steps