LensHub/ docs / docker compose
Self-hosting

Docker Compose

The straightforward way to run it.

The quickstart has a working compose file. This page covers what to change before other people use it.

Services

Does
postgresStores everything
migrateApplies pending schema migrations, then exits. api and worker wait for it
apiServes the API and the agent endpoint
webThe browser interface
workerSyncs connectors, indexes and classifies content, sweeps old logs
embeddingTurns content into something searchable, locally
embedding-codeThe same for source code, with a code model

Off until you start them:

ProfileDoes
appdappsRuns agent-deployed apps and their egress proxy (make up-apps)
backupbackupTakes a backup on a schedule
restorerestoreUsed by scripts/restore.sh; never started by hand

Before anyone else connects

api:
  environment:
    BASE_URL: https://lenshub.example.com   # the address people actually use
    CORS_ORIGIN: https://lenshub.example.com
    COOKIE_SECURE: "true"
    LENSHUB_ENV: production

BASE_URL must be the public address, not the container port. Agent sign-in depends on it.

Give PostgreSQL more memory

The defaults are tuned for very small machines. On a real server:

postgres:
  shm_size: 3g   # the compose default; parallel index builds need it
  command:
    - postgres
    - -c
    - shared_buffers=2GB
    - -c
    - work_mem=32MB
    - -c
    - maintenance_work_mem=512MB

Faster indexing

More workers means more parallel syncing:

worker:
  environment:
    WORKER_CONCURRENCY: 8

Persistence

Five named volumes: pgdata, uploads, attachments, git-clones and embedding-models. pgdata is the critical one — it holds all your content — with uploads and attachments next. The last two are caches that refill themselves. See Backup.

Updating

./scripts/backup.sh
docker compose pull
docker compose up -d

up runs migrate before the new api and worker start. Read Upgrades for what that means on a large database.

On this page