Docker Deployment¶
Quick start¶
docker run -d \
--name soulacy \
-p 18789:18789 \
-v $(pwd)/config.yaml:/home/soulacy/.soulacy/config.yaml \
-v $(pwd)/agents:/home/soulacy/.soulacy/agents \
-v $(pwd)/memory:/home/soulacy/.soulacy/memory \
ghcr.io/vmodekurti/soulacy:latest
Docker Compose (recommended)¶
Basic setup (SQLite)¶
docker-compose.yml
version: "3.9"
services:
soulacy:
image: ghcr.io/vmodekurti/soulacy:latest
restart: unless-stopped
ports:
- "18789:18789"
volumes:
- ./config.yaml:/home/soulacy/.soulacy/config.yaml:ro
- ./agents:/home/soulacy/.soulacy/agents:ro
- soulacy_data:/home/soulacy/.soulacy/memory
volumes:
soulacy_data:
Full stack (Postgres + Qdrant)¶
docker-compose.yml
version: "3.9"
services:
soulacy:
image: ghcr.io/vmodekurti/soulacy:latest
restart: unless-stopped
ports:
- "18789:18789"
volumes:
- soulacy_data:/home/soulacy/.soulacy
depends_on:
postgres:
condition: service_healthy
qdrant:
condition: service_started
environment:
- SOULACY_STORAGE_BACKEND=postgres
- SOULACY_STORAGE_POSTGRES_DSN=postgres://soulacy:secret@postgres:5432/soulacy?sslmode=disable
- SOULACY_VECTOR_BACKEND=qdrant
- SOULACY_VECTOR_URL=http://qdrant:6333
- SOULACY_VECTOR_COLLECTION=soulacy_memory
postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: soulacy
POSTGRES_PASSWORD: secret
POSTGRES_DB: soulacy
volumes:
- pg_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U soulacy"]
interval: 5s
timeout: 5s
retries: 5
qdrant:
image: qdrant/qdrant:latest
restart: unless-stopped
volumes:
- qdrant_data:/qdrant/storage
volumes:
soulacy_data:
pg_data:
qdrant_data:
Environment variable overrides¶
All config values can be set via environment variables (useful for secrets in CI/CD). Note that Soulacy uses single underscores (_) as separators:
SOULACY_SERVER_API_KEY=sy_secret
SOULACY_LLM_PROVIDERS_OPENAI_API_KEY=sk-...
SOULACY_CHANNELS_TELEGRAM_TOKEN=1234:AAH...
Health check¶
Docker healthcheck in Compose:
healthcheck:
test: ["CMD", "curl", "-fs", "http://localhost:18789/api/v1/health"]
interval: 30s
timeout: 10s
retries: 3
Using a reverse proxy (nginx)¶
nginx.conf
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
location / {
proxy_pass http://soulacy:18789;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 120s; # allow time for long LLM responses
}
}