ClouisleClouisle

Docker Compose deployment

Start all Clouisle services on a single server

Docker Compose suits single-server deployments. Requires Docker and Docker Compose v2.

Guided installer

curl -fsSL https://raw.githubusercontent.com/clouisle/Clouisle/main/deploy/install.sh | bash

Select Docker Compose, confirm the install directory and domain, and the installer downloads files, generates strong secrets, validates the Compose file, pulls images, and starts the services.

Non-interactive install (skips prompts, uses defaults):

CLOUISLE_DEPLOYMENT=docker CLOUISLE_YES=1 curl -fsSL https://raw.githubusercontent.com/clouisle/Clouisle/main/deploy/install.sh | bash

The default install directory is /opt/clouisle.

Manual installation

cd deploy
cp .env.example .env
internal_api_token="$(openssl rand -hex 32)"
sed -i.bak "s/^INTERNAL_API_TOKEN=.*/INTERNAL_API_TOKEN=${internal_api_token}/" .env
rm .env.bak
unset internal_api_token
docker compose pull
docker compose up -d

macOS BSD sed has different arguments from GNU sed; on macOS, edit .env directly or use the installer to generate the Token.

Check the services

docker compose ps
docker compose logs -f api
curl http://localhost:8000/api/v1/health

Configure the external reverse proxy so /api/* goes to api:8000 and / goes to frontend:3000. The browser entry point defaults to http://localhost:3000.

Service inventory and ports

deploy/docker-compose.yml defines 5 application services plus 3 infrastructure services — 8 containers in total:

ServiceImageCommandHost port
dbclouisle-postgres-pg-search:0.24.3-pg17-alpine1postgres -c shared_preload_libraries=pg_search,pg_stat_statements -c pg_stat_statements.track=all5432
redisredis:7-alpineredis-server --requirepass … (when REDIS_PASSWORD is set)6379
qdrantqdrant/qdrant:v1.18.3default6333
apiclouisle-backend:latestpython main.py server -H 0.0.0.0 -w 4 --no-reload8000
workerclouisle-backend:latestpython main.py worker -c 4 -Q default,agent,knowledge,workflownone
sandbox-workerclouisle-sandbox-worker:latestpython main.py sandbox-worker -c ${SANDBOX_WORKER_CONCURRENCY:-1}none
beatclouisle-backend:latestpython main.py beatnone
frontendclouisle-frontend:latestnode server.js (image default)3000

There is no Nginx service. The api healthcheck runs GET http://localhost:8000/api/v1/health inside the container; worker and sandbox-worker wait for api to become healthy, while beat and frontend only wait for api to be started (service_started). db, redis, and qdrant each have their own healthcheck (pg_isready, redis-cli ping, /healthz), and every application service waits for those to pass.

api owns the uploads_data volume (mounted at /app/uploads). worker and sandbox-worker do not mount it: they use UPLOAD_STORAGE_MODE=remote with API_INTERNAL_BASE_URL=http://api:8000 to read and write files through the internal gateway. sandbox-worker additionally runs with user: "0", cap_add: [SYS_ADMIN], and seccomp=unconfined so bwrap can create user and mount namespaces.

Production deployments must set strong random values for POSTGRES_PASSWORD and INTERNAL_API_TOKEN. The Compose file uses the ${VAR:?required} form, so docker compose up fails immediately when either is unset. INTERNAL_API_TOKEN must be shared by api, worker, and sandbox-worker.

Initialization

Tortoise ORM creates and migrates tables automatically at API startup (no Alembic). The first registered user automatically becomes the Super Admin.

Docker Compose services running
Docker Compose services running

Common operations

docker compose logs -f worker
docker compose restart api
docker compose up -d --scale worker=4
docker compose up -d --scale sandbox-worker=2
docker compose down

beat must stay at one replica. docker compose down -v deletes data volumes; complete a backup before running it.

The worker consumes the default,agent,knowledge,workflow queues, so --scale worker=4 grows all four task classes together. To grow one class only, add a worker service subscribed to a single queue (for example -Q agent); the sandbox queue is consumed independently by sandbox-worker. Queue-to-task mapping: Deployment architecture → Celery queue layout.

How is this guide?

On this page