Skip to main content

Self-hosted installation

This guide shows how to deploy the complete Logos stack with Docker Compose. The stack contains the web UI, the API service, the orchestrator, PostgreSQL and Traefik. The development stack also runs a local Keycloak. Production needs an external identity provider. Configure it with the KEYCLOAK_* variables in .env.

Prerequisites​

  • Docker Engine with the Compose plugin
  • A domain name and an SMTP/identity-provider configuration for production
  • Python 3.13 and uv, only if you develop Logos outside containers
  • A GPU worker node, if you serve local models

Clone the repository and go to the service directory:

git clone https://github.com/ls1intum/edutelligence.git
cd edutelligence/logos
cp .env.example .env

Development deployment​

The development compose file builds all services locally. It includes a development Keycloak realm:

docker compose -f docker-compose.dev.yaml up --build

The compose stack serves the API (Traefik at http://localhost:18081). It does not serve the web UI. Also start the Angular dev server on the host:

cd logos-ui
npm ci
npm start

Then open http://localhost:4200/ and sign in with one of the seeded development accounts. keycloak/tum-realm.json defines these accounts and their roles. Do not use them in a production deployment.

Production deployment​

For production, use docker-compose.yaml. Every image is on the public mirror at ghcr.io/ls1intum/edutelligence. The compose file pulls from this mirror by default. You do not need registry configuration or a login:

docker compose --env-file .env up -d

The mirror receives images from main, so it has one tag: latest. Version tags go to the deployment registry of the project, which is team-internal. To pull from that registry, or from your own mirror, set both variables in .env and log in one time:

REGISTRY=<registry-host>/<namespace>
IMAGE_TAG=<published tag>
docker login <registry-host> # host only, no path

To run images that you built yourself, build them from the Dockerfiles that the build workflow uses. Tag them for a registry from which the host can pull, for example a local registry:

# The build contexts below are relative to the repository root. Go there
# first (the working directory of this guide is edutelligence/logos):
cd ..
REGISTRY=localhost:5000
IMAGE_TAG=latest
docker build -t "$REGISTRY/logos:$IMAGE_TAG" -f logos/logos-orchestrator/Dockerfile .
docker build -t "$REGISTRY/logos-webservice:$IMAGE_TAG" logos/logos-webservice
docker build -t "$REGISTRY/logos-ui:$IMAGE_TAG" logos/logos-ui
docker build -t "$REGISTRY/logos-db:$IMAGE_TAG" logos/db
docker build -t "$REGISTRY/logos-agent:$IMAGE_TAG" -f logos/logos-agent/Dockerfile .
docker build -t "$REGISTRY/logos-agent-gateway:$IMAGE_TAG" -f logos/agent-gateway/Dockerfile .
docker build -t "$REGISTRY/logos-agent-workspace:$IMAGE_TAG" -f logos/logos-agent/workspace/Dockerfile .
docker build -t "$REGISTRY/logos-rate-gateway:$IMAGE_TAG" -f logos/rate-limit-gateway/Dockerfile .

The full stack needs all eight images. logos-rate-gateway is the only router on the public entrypoints. Without it, the stack serves no public traffic. If the logos-agent-workspace image is absent, the agent runner refuses to start a session.

Set the same REGISTRY and IMAGE_TAG in .env, then start the stack. Build the worker node image on the GPU host instead (see the worker node guide):

cd logos
docker compose --env-file .env up -d

Set real values for LOGOS_DOMAIN, ACME_EMAIL and LOGOS_CORS_ALLOWED_ORIGINS. Set strong values for LOGOS_INTERNAL_SECRET and PROMETHEUS_API_KEY. Make sure that ports 80, 443 and (if necessary) 8080 of the host are available. If you configure ACME_EMAIL, Traefik gets a certificate through Let's Encrypt.

After startup, verify the UI at https://<your-domain>/. Verify the API documentation at https://<your-domain>/docs.

Persistent data and upgrades​

The production stack keeps the following data:

StorageTypeContents
postgres_datanamed volumePostgreSQL data
data_volumenamed volumeorchestrator working data (/src/logos)
agent_artifactsnamed volumeagent session artifacts
agent_state (literal name logos_agent_state)named volumeagent session state
./letsencryptbind mountTraefik Let's Encrypt certificate state

Before an upgrade, back up these volumes and the ./letsencrypt directory. Keycloak is external to the stack. Back up its realm export together with your identity provider (for the realm format, see keycloak/tum-realm.json in this repository). In the development stack, the Keycloak state is temporary. Pull the necessary image tag and recreate the stack:

docker compose --env-file .env pull
docker compose --env-file .env up -d