1
Clone the example repository
2
git clone git@github.com:Qventu/exulu-example.git
cd exulu-example
3
Create your environment file
4
cp .env.example .env
5
Open
.env and fill in the critical variables listed below. The file ships with comments that explain each one.6
Authentication and security
7
NEXTAUTH_SECRETopenssl rand -base64 32.LITELLM_MASTER_KEY8
INTERNAL_SECRET is optional and is not present in the .env.example template. Set it only when you have internal service-to-service calls that use the internal request header; IMP does not require it for standard deployments.9
npm registry access
10
@exulu/backend is published to the public npm registry — no token is required. The NPM_TOKEN build argument in the example repo’s Dockerfiles is legacy plumbing and may be left empty or unset.11
Postgres
12
POSTGRES_DB_HOSTexulu-pgvector when using the services compose file).POSTGRES_DB_PORT5432POSTGRES_DB_USERpostgresPOSTGRES_DB_PASSWORDPOSTGRES_DB_NAMEexulu)LITELLM_DATABASE_URLPOSTGRES_DB_NAME.13
S3-compatible storage
14
COMPANION_S3_REGIONeu-central-1)COMPANION_S3_KEYCOMPANION_S3_SECRETCOMPANION_S3_BUCKETCOMPANION_S3_ENDPOINThttp://exulu-minio:9000 when using the MinIO container)15
Frontend and backend URLs
16
FRONTENDhttps://imp.example.com)BACKENDhttps://api.imp.example.com)NEXT_BACKENDhttp://exulu-backend:9001.NEXTAUTH_URLFRONTEND.17
For the LiteLLM proxy to work you also need to configure
config.litellm.yaml with at least one model entry before starting the backend. Copy config.litellm.yaml from the repo and edit the model_list section to add your providers.18
Start the infrastructure services
19
Launch Postgres (with pgvector), Redis, and MinIO:
20
docker compose -f docker-compose.services.yml up -d
21
This starts three containers:
exulu-pgvector, exulu-redis, and exulu-minio. Wait for the health checks to pass before proceeding.22
The services compose file mounts
./postgres/schema.sql into the pgvector container’s init directory. This file is referenced in the compose definition but may not exist in all repo checkouts. If Postgres fails to start, check whether postgres/schema.sql is present and create it as an empty file if needed (mkdir -p postgres && touch postgres/schema.sql).23
Build and start the backend
24
The backend has no published Docker image. Build it locally from your
exulu-example checkout so your own configuration is baked in. @exulu/backend installs from the public npm registry — no token is needed.25
docker compose -f docker-compose.backend.yml up -d --build
26
This builds the image and starts the
exulu-backend container on ports 9001 and 4000.27
Capture the first-boot log output before it scrolls away. On the very first startup, The default admin credentials are
initdb runs automatically and prints a one-time admin password and API key to stdout. You cannot retrieve the API key again after this point.admin@exulu.com / admin. Change the password immediately after first login. The API key printed to the log is the only copy — store it in your secrets manager now.initdb runs on every backend boot and logs a freshly generated key each time, but only the key from the very first startup is ever persisted. Keys logged on subsequent startups are never stored and will not work.28
The
security_opt flags (seccomp:unconfined, apparmor:unconfined) in the compose file are required for the skill sandbox (bwrap) to create user namespaces. Without them, sandboxed skill execution will fail with permission errors.29
Start the worker (optional)
30
Workers handle background jobs: knowledge ingestion, embeddings, evals, and routines. Skip this step if you do not need these features.
31
docker compose -f docker-compose.worker.yml up -d --build
32
The worker container starts on port
9002. It connects to the LiteLLM proxy on port 4000 (the backend must be running first). Give the worker container at least 8 GB of memory — knowledge processing tasks can hold large document representations in memory. The Docker entrypoint does not set NODE_OPTIONS by default; set it yourself via the compose environment section:33
environment:
NODE_OPTIONS: "--max-old-space-size=8192"
34
docker-compose.worker.yml does not include an env_file entry (unlike the backend compose file). Outside Dokploy — where environment variables are injected by the platform — the worker will start without database and Redis credentials and crash on first use. Add the following to docker-compose.worker.yml under the worker service, or inject the variables another way:35
Start the frontend
36
docker compose -f docker-compose.frontend.yml up -d
37
This pulls
ghcr.io/qventu/exulu-frontend:latest and starts the container on port 3000. No build step is needed.38
Verify the deployment
39
Check that all containers are running:
40
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
41
You should see
exulu-pgvector, exulu-redis, exulu-minio, exulu-backend, exulu-worker (if started), and exulu-frontend all in Up status.42
Open your
FRONTEND URL in a browser and log in with admin@exulu.com and the password from the first-boot log. Navigate to Administration → Models to verify that the LiteLLM proxy is reachable and your configured models appear.Production network note
The backend and worker compose files attach todokploy-network, an external Docker network used by Dokploy. If you are not using Dokploy, create a shared network and update the networks section in both compose files to match your setup before running the commands above.
Next steps
See the service guides for customizingconfig.litellm.yaml, SMTP and auth, and observability, and the environment variable reference for the full configuration surface.
See LiteLLM service for adding and managing model providers through the proxy.