Requirements
What the host needs, and which sizing figures are measured.
Requirements
What the host needs, and what to expect from memory and disk. Where DocSlurp has no measured figure, this page says so.
On this page
Host requirements
- A Linux host with Docker Engine and Compose v2. Docker Desktop is untested. The parser sandbox (bubblewrap) is Linux-only.
- A kernel that allows unprivileged user namespaces, and a container runtime that lets the worker create namespaces. Ubuntu 23.10 and later restrict unprivileged user namespaces with
kernel.apparmor_restrict_unprivileged_userns=1; CI sets it to 0 before the bubblewrap tests (.github/workflows/ci.yml). Not verified on an AppArmor host: Docker’s default AppArmor profile may also block bubblewrap’s mounts. If the worker fails the sandbox check there, addapparmor=unconfinedto the worker’ssecurity_opt. The sandbox unshares network, PID, IPC and UTS namespaces, and Compose runs the worker with thesystempaths=unconfinedsecurity option so bubblewrap can mount a fresh/proc. Capabilities stay dropped. See Security. - Node.js, for the one-time configuration generator (
node scripts/selfhost-init.mjs). Node is not needed to run the containers after setup. - Disk for Docker images, the
postgres_dataandminio_datavolumes, and the worker scratch space. Document artifacts (raw files, page images, derived Markdown) go tominio_data. There is no measured per-document figure; watch disk use on your own corpus.
Source: compose.selfhost.yml, worker/scripts/parser-sandbox.sh, Self-hosting overview.
Sizing
Start with at least 8 GB of RAM for the lean worker. The full worker needs more memory and disk. This is the current guidance from the Compose install. No measurement is recorded for it.
No measured CPU figure; parsing, OCR and local embedding are CPU-bound, so throughput scales with cores. Watch CPU alongside memory when raising WORKER_DOC_CONCURRENCY.
Image sizes, measured on local builds on 2026-10-14 (linux/amd64):
| Item | Uncompressed | Compressed | Source |
|---|---|---|---|
Lean worker image (worker/Dockerfile.lean) |
1,884 MiB | 615 MiB | Worker image, “Measured sizes” |
Full worker image (worker/Dockerfile.full) |
2,552 MiB | 873 MiB | same |
docling vendor bundle |
1,743 MiB unpacked | 656 MiB .tar.zst |
same |
unstructured vendor bundle |
2,085 MiB unpacked | 599 MiB .tar.zst |
same |
The lean figure does not include baked ClamAV signatures (about 110 MB on the production machine) or the private native PDF engine. The bge-m3 embedding model is about 560 MB and is cached under ~/.cache in the worker. Both are from Worker image. Vendor bundles are off unless DOCSLURP_VENDOR_BUNDLE_BASE_URL is set; see Configuration.
Worker scratch space in Compose is tmpfs, which counts against host memory when used: /tmp is 2048 MB and /var/tmp is 512 MB for worker, and 4096 MB and 1024 MB for worker-full (compose.selfhost.yml).
How the per-command memory budget works
The worker caps the resident memory of each parser command. resolveCommandRssBudgetMb in worker/src/tools/runner.ts picks the cap:
- If
WORKER_COMMAND_MAX_RSS_MBis set, that value is used. - Otherwise the cap is 60% of the container memory limit, with a floor of 1024 MB.
- If no limit is known, there is no cap.
resolveContainerMemoryLimitMb reads the limit from the cgroup (/sys/fs/cgroup/memory.max, then /sys/fs/cgroup/memory/memory.limit_in_bytes) and falls back to MemTotal in /proc/meminfo. With no memory limit on the container, the host’s total RAM is the limit, so the cap is 60% of host RAM. scripts/start-worker.sh applies the same 60% rule when it starts the worker. It also sizes the Node heap at 35% of the limit, clamped between 768 MB and 1536 MB. The worker logs the result at startup as [worker-memory] container_limit_mb=... command_rss_budget_mb=....
The cap is per command, not per document. DocSlurp does not publish a memory figure per document.
What scales with concurrency
WORKER_DOC_CONCURRENCY is the number of documents each worker processes at once. The Compose default is 1. Memory scales with it, because each document can run its own parser commands. Extraction feature matrix gives minimum RAM per extractor (for example about 2 GB for Docling and 512 MB for Kreuzberg) and notes that four parallel documents with Docling need about 8 GB. Worker image puts a Docling call at about 2 GB RSS. Raise concurrency only after you have watched memory and latency at the current setting.
GPU
The default stack needs no GPU. The lean and full workers run on CPU, and local embedding runs on CPU.
A GPU is optional in two places:
- The
vision-runtimeextractor for handwriting, degraded scans and charts is listed with 1 GB of VRAM or more and an optional GPU (Extraction feature matrix). - Private model endpoints let you point
local-onlyandstrict-privacyworkspaces at an OpenAI-compatible server you run, such as vLLM on a rented GPU. The GPU lives on that server, not in this Compose stack. See Model configuration.
The Compose file has no GPU device reservations.