Ctrl AI

Self-Hosted Deployment

Deploy Ctrl AI on your own infrastructure with Docker.

Prerequisites

  • Docker Engine 24+ and Docker Compose v2
  • 4 GB RAM minimum (8 GB recommended)
  • An LLM API key (Gemini, OpenAI-compatible, or local Ollama)

Quick Start

# 1. Clone the repository
git clone https://github.com/ctrlai/ctrlai.git && cd ctrlai

# 2. Create environment file
cp .env.example .env
# Edit .env — at minimum set AUTH_SECRET and an LLM provider key

# 3. Start all services
docker compose up -d

The app will be available at http://localhost:3000. The first startup takes a few minutes while the image builds.

Database

Docker Compose (default)

The included docker-compose.yml runs PostgreSQL 16 automatically. Data is persisted in the postgres_data volume.

Run migrations after first start:

docker compose exec app npx drizzle-kit migrate

Bring Your Own PostgreSQL

Set DATABASE_URL in your .env to point at your existing database and remove the postgres service from docker-compose.yml.

DATABASE_URL=postgresql://user:pass@your-host:5432/ctrlai

LLM Configuration

Google Gemini (default)

Set GEMINI_API_KEY in your .env. No other config needed.

Ollama (fully local)

LLM_PROVIDER=ollama
LLM_BASE_URL=http://host.docker.internal:11434/v1
LLM_MODEL=llama3

Make sure Ollama is running on the host machine before starting Ctrl AI.

OpenAI-Compatible

LLM_PROVIDER=openai
LLM_BASE_URL=https://api.openai.com/v1
LLM_API_KEY=sk-...
LLM_MODEL=gpt-4o

Works with any OpenAI-compatible API (Together, Groq, Azure OpenAI, etc.).

See LLM Configuration for advanced provider setup.

Email Configuration

Email is optional. Without it, invite and notification features are disabled gracefully.

Resend (cloud)

RESEND_API_KEY=re_...

SMTP (self-hosted)

SMTP_HOST=mail.example.com
SMTP_PORT=587
SMTP_USER=noreply@example.com
SMTP_PASS=secret
SMTP_FROM=Ctrl AI <noreply@example.com>

Upgrading

git pull
docker compose build
docker compose up -d
docker compose exec app npx drizzle-kit migrate

Health Check

curl http://localhost:3000/api/health
# {"status":"ok","checks":{"database":"ok","redis":"not_configured"},"version":"0.1.0"}

Troubleshooting

IssueSolution
App exits immediatelyCheck docker compose logs app — usually a missing AUTH_SECRET or unreachable database
Database connection refusedEnsure the postgres service is healthy: docker compose ps
Build fails with OOMIncrease Docker memory to 4 GB+ in Docker Desktop settings
Ollama not reachableOn macOS/Windows, use host.docker.internal instead of localhost in LLM_BASE_URL

Logs

# All services
docker compose logs -f

# App only
docker compose logs -f app

# Database
docker compose logs -f postgres

On this page