Deployment

Deploy Enclavr to production.

Quick Start

Deploy Enclavr using Docker Compose, or use Neon (serverless PostgreSQL) for the database.

Option 1: Neon PostgreSQL (Recommended)

Neon is the default database - create a project at neon.tech:

  1. Create a Neon project at neon.tech
  2. Get your connection string from the Neon dashboard
  3. Set NEON_CONNECTION_STRING environment variable:
    NEON_CONNECTION_STRING=postgres://user:password@host.neon.tech/neondb?sslmode=require
  4. Run Redis with Docker: docker run -d --name enclavr-redis -p 6379:6379 redis:8

Option 2: Docker Compose

# Clone with submodules
git clone --recurse-submodules https://github.com/enclavr/enclavr.git
cd enclavr/infra

# Copy environment file
cp .env.example .env
# Edit .env with your values

# Start services
docker compose up -d

Production Checklist

Docker Compose Profiles

Enclavr uses Docker Compose profiles for flexible deployment. Use the Makefile shortcuts:

# Core services only (default)
make up

# With monitoring (Prometheus, Grafana, Loki, Alertmanager)
make monitoring

# With voice (Coturn TURN server)
make voice

# With automated backups
make backup

# With automatic HTTPS (Caddy)
make tls

# With object storage (MinIO)
make storage

# Full stack (all profiles)
make full

# Production (full + TLS)
make prod

# Development mode (hot reload)
make dev

All Makefile Targets

TargetDescription
make helpShow all available commands
make upStart core services
make downStop all services
make restartRestart all services
make buildBuild all images (no-cache)
make devStart in development mode (hot reload)
make prodStart in production mode (full + TLS)
make fullStart with all profiles
make monitoringStart with monitoring stack
make voiceStart with Coturn TURN server
make backupStart with automated backups
make tlsStart with Caddy automatic HTTPS
make storageStart with MinIO object storage
make validateValidate docker-compose configuration
make statusShow service status
make logsFollow logs for core services
make healthCheck health of all services
make env-checkValidate environment variables
make db-shellOpen PostgreSQL shell
make redis-shellOpen Redis CLI
make cleanRemove stopped containers and unused volumes
make update-imagesPull latest images and recreate
make pg-backupCreate manual database backup
make pg-restoreRestore database from backup file

Development Mode

The docker-compose.override.yml file is automatically loaded by Docker Compose when present. Use make dev to start in development mode.

Production Overrides

A docker-compose.prod.yml file provides production-specific overrides. It is not automatically loaded — you must explicitly include it:

# Start with production overrides
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

# Or use the Makefile (make prod uses --profile full --profile tls)
make prod

Production Override Settings

SettingValueDescription
SENTRY_ENVIRONMENTproductionSentry environment tag
DB_SSLMODErequireEnforce SSL for database connections
NODE_ENVproductionNode.js production mode
Frontend port3000:80Maps container port 80 to host port 3000

Development Features

FeatureDetails
Server hot reloadSource code mounted from ../server, runs with go run ./cmd/server
Frontend hot reloadSource code mounted from ../frontend, runs with bun run dev
Go module cachePersistent server_go_cache volume for faster rebuilds
Node modules cachePersistent frontend_node_modules volume
Next.js cachePersistent frontend_next volume
Delve debuggerServer debugger on port 2345 (localhost only)
PostgreSQL accessPort 5432 exposed to localhost
Redis accessPort 6379 exposed to localhost
NODE_ENVSet to development
DB_SSLMODESet to disable
SentryDisabled (empty DSN)

Automatic HTTPS with Caddy

Caddy provides automatic HTTPS via Let's Encrypt:

# In .env, set:
DOMAIN=enclavr.example.com
ACME_EMAIL=admin@example.com
MONITORING_DOMAIN=monitoring.example.com
GRAFANA_BASIC_AUTH_USER=admin
GRAFANA_BASIC_AUTH_HASH=...  # htpasswd hash

# Start with TLS profile
make tls

Caddy features:

Caddy Subdomain Routing

SubdomainTargetFeatures
{DOMAIN}frontend:80Static files, security headers, hidden file blocking
api.{DOMAIN}server:8080REST API, WebSocket upgrade, rate limiting
{MONITORING_DOMAIN}grafana:3000Basic auth protected, monitoring dashboard

Automatic Container Updates

Watchtower automatically updates running containers:

# Enable the maintenance profile
docker compose --profile maintenance up -d
VariableDefaultDescription
WATCHTOWER_POLL_INTERVAL86400 (24h)Check interval in seconds
WATCHTOWER_LOG_LEVELinfoLog verbosity

Containers with the com.centurylinklabs.watchtower.enable=true label are eligible for auto-updates.

Database Backups

Automated backups run via the backup Docker Compose profile:

# Enable automated backups (daily at 2 AM by default)
make backup

# Manual backup
make pg-backup

# Restore from backup
make pg-restore FILE=backup.sql.gz
VariableDefaultDescription
BACKUP_CRON0 2 * * *Backup schedule (cron format)
BACKUP_RETENTION_DAYS7Days to keep backups

Volumes marked for backup: postgres_data, server_uploads, grafana_data, backup_data.

Alternative Reverse Proxy

If you prefer nginx or another reverse proxy instead of Caddy:

server {
    listen 443 ssl;
    server_name enclavr.example.com;
    
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    location / {
        proxy_pass http://frontend:3000;
    }
    
    location /api/ {
        proxy_pass http://server:8080;
    }
    
    location /ws {
        proxy_pass http://server:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}