Docker Compose Setup
Deploy Ovyxa in 5 minutes using Docker Compose. Perfect for single-server deployments up to millions of events per day.
Prerequisites
- Linux server (Ubuntu 22.04+ recommended)
- Docker 24+ installed
- Docker Compose 2.x installed
- 4GB+ RAM, 20GB+ disk
- Domain name pointing to your server
Quick Start
1. Clone Repository
git clone https://github.com/ovyxa/ovyxa.git
cd ovyxa/deployments/docker-compose
2. Configure Environment
Copy the example environment file:
cp .env.example .env
Edit .env with your settings:
# Base Configuration
BASE_URL=https://analytics.yourdomain.com
SECRET_KEY_BASE=$(openssl rand -hex 64)
# PostgreSQL
POSTGRES_PASSWORD=$(openssl rand -hex 32)
DATABASE_URL=postgresql://ovyxa:${POSTGRES_PASSWORD}@postgres:5432/ovyxa
# ClickHouse
CLICKHOUSE_HOST=http://clickhouse:8123
CLICKHOUSE_DATABASE=ovyxa
# Redis
REDIS_PASSWORD=$(openssl rand -hex 32)
REDIS_URL=redis://:${REDIS_PASSWORD}@redis:6379
# Email (optional, for user invites)
SMTP_HOST=smtp.yourdomain.com
SMTP_PORT=587
SMTP_USER=noreply@yourdomain.com
SMTP_PASSWORD=your-smtp-password
# Admin User (created on first start)
ADMIN_EMAIL=admin@yourdomain.com
ADMIN_PASSWORD=$(openssl rand -hex 16)
3. Start Services
docker-compose up -d
This starts:
- PostgreSQL (metadata)
- ClickHouse (analytics)
- Redis (cache)
- API server (ingestion + stats)
- Web dashboard
- Caddy (reverse proxy with auto-SSL)
4. Initialize Database
# Run migrations
docker-compose exec api npm run migrate
# Create admin user
docker-compose exec api npm run create-admin
5. Access Dashboard
Visit https://analytics.yourdomain.com and log in with your admin credentials.
Complete docker-compose.yml
version: '3.8'
services:
postgres:
image: postgres:15-alpine
container_name: ovyxa-postgres
environment:
POSTGRES_DB: ovyxa
POSTGRES_USER: ovyxa
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ovyxa"]
interval: 10s
timeout: 5s
retries: 5
clickhouse:
image: clickhouse/clickhouse-server:23-alpine
container_name: ovyxa-clickhouse
environment:
CLICKHOUSE_DB: ovyxa
CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1
volumes:
- clickhouse_data:/var/lib/clickhouse
- ./clickhouse/config.xml:/etc/clickhouse-server/config.d/ovyxa.xml
restart: unless-stopped
healthcheck:
test: ["CMD", "clickhouse-client", "--query", "SELECT 1"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
container_name: ovyxa-redis
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- redis_data:/data
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 5
api:
image: ovyxa/api:latest
container_name: ovyxa-api
depends_on:
postgres:
condition: service_healthy
clickhouse:
condition: service_healthy
redis:
condition: service_healthy
environment:
NODE_ENV: production
PORT: 3000
BASE_URL: ${BASE_URL}
SECRET_KEY_BASE: ${SECRET_KEY_BASE}
DATABASE_URL: ${DATABASE_URL}
CLICKHOUSE_HOST: ${CLICKHOUSE_HOST}
CLICKHOUSE_DATABASE: ${CLICKHOUSE_DATABASE}
REDIS_URL: ${REDIS_URL}
SMTP_HOST: ${SMTP_HOST}
SMTP_PORT: ${SMTP_PORT}
SMTP_USER: ${SMTP_USER}
SMTP_PASSWORD: ${SMTP_PASSWORD}
volumes:
- ./logs:/app/logs
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
web:
image: ovyxa/web:latest
container_name: ovyxa-web
depends_on:
- api
environment:
NODE_ENV: production
NEXT_PUBLIC_API_URL: ${BASE_URL}/api
restart: unless-stopped
caddy:
image: caddy:2-alpine
container_name: ovyxa-caddy
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
restart: unless-stopped
depends_on:
- api
- web
volumes:
postgres_data:
clickhouse_data:
redis_data:
caddy_data:
caddy_config:
Caddyfile Configuration
Create Caddyfile:
analytics.yourdomain.com {
# Dashboard
handle /* {
reverse_proxy web:3000
}
# API & Ingestion
handle /api/* {
reverse_proxy api:3000
}
handle /e {
reverse_proxy api:3000
}
# Logs
log {
output file /data/access.log
}
# Security headers
header {
X-Content-Type-Options "nosniff"
X-Frame-Options "SAMEORIGIN"
Referrer-Policy "strict-origin-when-cross-origin"
Strict-Transport-Security "max-age=31536000;"
}
}
Caddy automatically provisions Let's Encrypt SSL certificates.
Management Commands
View Logs
# All services
docker-compose logs -f
# Specific service
docker-compose logs -f api
docker-compose logs -f clickhouse
Restart Services
# All services
docker-compose restart
# Specific service
docker-compose restart api
Update to Latest Version
docker-compose pull
docker-compose up -d
docker-compose exec api npm run migrate
Stop Services
docker-compose down
Stop and Remove Data
docker-compose down -v # WARNING: Deletes all data
Configuration
See Configuration Guide for all environment variables.
Monitoring
Health Checks
# Check service health
docker-compose ps
# API health endpoint
curl https://analytics.yourdomain.com/api/health
Database Sizes
# ClickHouse storage
docker-compose exec clickhouse clickhouse-client --query \
"SELECT database, formatReadableSize(sum(bytes)) as size FROM system.parts WHERE active GROUP BY database"
# PostgreSQL size
docker-compose exec postgres psql -U ovyxa -c \
"SELECT pg_size_pretty(pg_database_size('ovyxa'))"
Backups
See Backup Guide for complete backup procedures.
Quick backup:
# Backup all data
./scripts/backup.sh
# Backup files saved to ./backups/
Troubleshooting
Services Won't Start
Check logs:
docker-compose logs postgres
docker-compose logs clickhouse
Common issues:
- Port conflicts (change ports in docker-compose.yml)
- Insufficient memory (increase RAM or swap)
- Permission issues (check volume permissions)
Can't Access Dashboard
- Check Caddy logs:
docker-compose logs caddy - Verify DNS:
dig analytics.yourdomain.com - Check firewall:
sudo ufw status - Test local:
curl http://localhost
Events Not Being Recorded
- Check API logs:
docker-compose logs api - Test ingestion:
curl -X POST https://analytics.yourdomain.com/e -d '{"site":"test"}' - Check ClickHouse:
docker-compose exec clickhouse clickhouse-client --query "SELECT count() FROM ovyxa.events"
Performance Tuning
For high traffic, adjust resources in docker-compose.yml:
services:
clickhouse:
deploy:
resources:
limits:
memory: 4G
reservations:
memory: 2G
api:
deploy:
resources:
limits:
memory: 1G
reservations:
memory: 512M
Next Steps
- Configuration Reference - All environment variables
- Backup & Restore - Data safety procedures
- Kubernetes - Scale to multiple servers
Docker Compose is production-ready for most use cases up to 10M+ events/day.