Install Paperless-ngx With Docker Compose and OCR

Run Paperless-ngx with the upstream Compose bundle, keep OCR support on, and get clear about persistent data, imports, and recovery before you dump a lifetime of documents into it.

Paperless-ngx Docker Compose OCR pipeline
Illustrated guide cover for Install Paperless-ngx With Docker Compose and OCR
Paperless-ngx • Docker Compose • OCR pipeline
What you learn

How to start from the official Compose files, keep the Tika and Gotenberg path available for richer document handling, and verify ingestion end to end.

Best for

Home labs and small-office operators who want searchable document storage without hand-assembling every service from scratch.

Risk to watch

Paperless feels simple at the UI layer, but the real risk is losing track of where the media, database, and import boundaries actually live.

Before you begin

  • A Linux host with Docker Compose already working.
  • Enough persistent storage for scanned documents, thumbnails, and OCR output.
  • At least a basic backup plan before you import anything hard to replace.

Paperless-ngx's setup docs explicitly recommend downloading one of the official Compose files from the project's docker/compose directory, along with docker-compose.env and .env. If you want richer document conversion support, use the file with -tika in the name.

Expected outcome: you should end with a working Paperless-ngx web UI, a successful OCR import test, and a documented answer to the question "what do I back up?"

Step 1: Pull the official Compose bundle

mkdir -p ~/apps/paperless
cd ~/apps/paperless

curl -fsSLO https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/docker-compose.postgres-tika.yml
curl -fsSLO https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/docker-compose.env
curl -fsSLO https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/.env

mv docker-compose.postgres-tika.yml docker-compose.yml

This keeps you close to the upstream-supported layout instead of freezing a random blog post into your long-term document system. If you need the SQLite variant instead, pick the corresponding upstream file deliberately and document why.

Step 2: Configure the environment files

Review the two environment files before you start anything:

sed -n '1,200p' .env
sed -n '1,240p' docker-compose.env

At minimum, set these values intentionally:

  • PAPERLESS_URL so generated links point to the correct address.
  • PAPERLESS_TIME_ZONE so ingestion timestamps make sense.
  • USERMAP_UID and USERMAP_GID if you need clean file ownership on bind-mounted paths.
  • Any mail settings you plan to use for notifications.

If you plan to reverse-proxy Paperless later, keep the app itself private during first boot. A local bind or tailnet path is enough to verify the core ingestion loop before you add public routing.

Step 3: Start the stack and create the first admin account

docker compose pull
docker compose up -d
docker compose ps

The official install flow says Paperless should become reachable on http://127.0.0.1:8000 or a similar local address depending on your configuration. On first access, use the web UI to create the first superuser if Paperless prompts you for it. If your Compose variant does not offer that first-run prompt, create one explicitly from the container:

docker compose run --rm webserver createsuperuser

Use a strong password and store it like you would any other admin credential. A document archive is more sensitive than a casual demo app.

Step 4: Verify OCR and document ingestion

Test the actual workflow, not just the login page:

  1. Sign in to Paperless.
  2. Upload a scanned PDF or image-based document.
  3. Wait for the task queue to finish processing.
  4. Search for text that only OCR could have extracted.

Useful checks from the host:

docker compose logs webserver --tail 100
docker compose logs gotenberg --tail 50
docker compose logs tika --tail 50

A passing test means you can upload a document, see it arrive in the library, and search text from that document successfully. If upload works but search does not, the stack is not really done.

Step 5: Operate it with sane storage habits

Paperless stores more than a simple config folder. You need to know where the database, consumed media, exported documents, and thumbnails live in your chosen Compose variant before you can claim to have backups.

Good day-two tasks:

docker compose exec webserver document_exporter /usr/src/paperless/export
docker compose logs --tail 100
docker volume ls | grep paperless
Warning: do not assume OCR success on day one means every later document is safe. Storage exhaustion, queue failures, and bad restore habits show up later, not during the first pretty demo.

Rollback and update notes

Before changing Compose files or image tags, export documents and confirm you have a recent backup of the database and persistent volumes. If an update fails, you want a recovery point that predates both the schema change and the document import that followed it.

docker compose down
docker compose pull
docker compose up -d

If you used the upstream files unchanged, future upstream changes are easier to compare. If you customized heavily, keep a short note explaining what you changed and why.

Troubleshooting

The web UI loads but document processing stalls.
Inspect the webserver, gotenberg, and tika logs together. Upload success alone does not prove the conversion pipeline is healthy.

OCR text never becomes searchable.
Confirm you actually chose a -tika Compose file and that the related services are healthy.

You are not sure what to back up.
Pause and map the real persistent data first. If you cannot name the volume or bind path for the database and document store, your backup plan is still imaginary.

Uploads work locally and you want remote access next.
Keep the app behind a trusted reverse proxy or private network path instead of publishing the container directly.