Optional services
The worker, the browser service, an S3 bucket and the demo databases, and how to turn each on.
The core is two containers. Everything else is an overlay file you add when you need it. Overlays combine: put every -f on the same command, and keep using that same command for up, build and down.
| Service | File | What it adds | You need it when... |
|---|---|---|---|
| Worker | docker-compose.worker.yml | A container that does the Library's background work (reading, writing pages, topics, link suggestions, interview drafts). The web app stops doing it (SERVICE_ROLE=api). | Many or large documents, several people uploading at once, or you want the web app to stay quick under load. Scale it with --scale worker=3. |
| Browser service | docker-compose.fetcher.yml | An isolated Chromium (Playwright) that renders web pages built by JavaScript. No database, no files, no app secrets; reaches the app over its own private network only. | You capture web addresses of single-page sites or pages that show their content only after scripts run. Plain pages (most articles and documentation) work without it. |
| S3 bucket | docker-compose.storage.yml | A self-hosted S3-compatible store (SeaweedFS, Apache-2.0) plus a one-shot job that creates the bucket. | You want the Library's original files outside the app's data folder (several app hosts, backups at the storage layer, versioning, or simply object storage). Any other S3 service works without this file. |
| Demo databases | docker-compose.demo.yml | PostgreSQL, MariaDB and ClickHouse with the same synthetic data. | You want to try the connectors on realistic data. See The demo database. |
How to turn each one on#
1. Worker. Nothing to configure: the file sets SERVICE_ROLE=api on the app and starts the worker with the same .env and the same ./data.
docker compose -f docker-compose.yml -f docker-compose.worker.yml up -d --build
2. Browser service. Put in .env (or on Settings > Web capture):
FETCHER_TOKEN=<openssl rand -hex 32> # the shared secret between the app and the fetcher
FETCHER_URL=http://fetcher:8001
FETCH_RENDER=auto # auto: render only pages with almost no text without JavaScript; always; never
docker compose -f docker-compose.yml -f docker-compose.fetcher.yml up -d --build
The app attaches to a private fetch network shared only with the fetcher (and the worker). The fetcher container is read-only, drops every capability, has no new privileges and has memory and process limits. Its browser never reaches the network itself: every request it makes is answered by the same address guard the app uses, so private, loopback and metadata addresses stay out of reach. To read an intranet, list the hosts in FETCH_ALLOWED_HOSTS (in .env, for the fetcher) and in Settings > Web capture (for the app).
3. S3 bucket. Pick an access key and a long random secret, then put in .env (or on Settings > Storage):
STORAGE_DRIVER=s3
S3_ENDPOINT=http://s3:8333
S3_BUCKET=library
S3_ACCESS_KEY=<pick one>
S3_SECRET_KEY=<pick one, long and random>
S3_PATH_STYLE=true
S3_REGION=us-east-1
docker compose -f docker-compose.yml -f docker-compose.storage.yml up -d
The s3-init job creates the bucket on the first start and exits. Press Test the storage on Settings > Storage to check the values. Nothing is published on the host: only the app (and the worker) reach the store. Choose the storage before the first upload: files already stored stay where they were and are not moved when the driver changes. Back up the s3_data volume (or use your own S3 service's tools). To use AWS S3, Ceph, Cloudflare R2 or a MinIO you run yourself, skip the file and fill in the same settings with your service's endpoint.
4. Everything together
docker compose -f docker-compose.yml -f docker-compose.worker.yml -f docker-compose.fetcher.yml -f docker-compose.storage.yml up -d --build
Without any of them the app does everything itself: workers inside the web process (LIBRARY_WORKERS, default 2), files in ./data/library, web pages fetched as plain pages.
Other things you can plug in (settings, not containers)#
| What | Where | Notes |
|---|---|---|
| AI endpoint | Settings > AI | Any OpenAI-compatible server: OpenRouter, a LiteLLM gateway, Ollama, vLLM. Nothing here is tied to one vendor. |
| A model per Library job | Settings > AI | Writer, checker, analyzer, topic writer, interviewer and image reader can each use a different model; empty uses the assistant model. |
| Embeddings | .env | local (default, in the container, no key) or a remote model. Any vector size pgvector stores. |
| Reranker | Settings > AI | Optional Cohere-style /rerank endpoint that sharpens Library search; off when empty. |
| Proxy | .env, see Running behind a proxy | nginx, Traefik, a load balancer or Cloudflare in front, with the real client address read safely. |