How to Install Paperless-ngx (Scan, OCR and Search Every Document You Own)

Paperless-ngx: the drawer of paper, searchable — Scan it once. Type 'boiler' five years later.

Bills, letters, warranties, school forms, the boiler's service record. Paperless-ngx takes a scan or a photo of any of them, reads the text (OCR), works out the date, sender and type, tags it, and files it so that typing "boiler" finds it five years later. Drop a PDF in a folder, email it, or snap it with your phone; Paperless does the rest.

Quick reference

TaskWhat
Folder~/docker/paperless/compose.yaml
Webhttp://server-ip:8000
Create admindocker compose run --rm webserver createsuperuser
Feed itdrop files in ./consume
Originals./media/documents/originals — back this up
PhonePaperless Mobile (iOS/Android) or any share-to-upload

1. The compose file

mkdir -p ~/docker/paperless && cd ~/docker/paperless
nano compose.yaml

services:
broker:
image: redis:7
restart: unless-stopped

db:
image: postgres:16
environment:
POSTGRES_DB: paperless
POSTGRES_USER: paperless
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- ./postgres:/var/lib/postgresql/data
restart: unless-stopped

webserver:
image: ghcr.io/paperless-ngx/paperless-ngx:latest
ports:
- "8000:8000"
environment:
PAPERLESS_REDIS: redis://broker:6379
PAPERLESS_DBHOST: db
PAPERLESS_DBPASS: ${DB_PASSWORD}
PAPERLESS_SECRET_KEY: ${SECRET_KEY}
PAPERLESS_URL: https://docs.example.com
PAPERLESS_OCR_LANGUAGE: eng
PAPERLESS_TIME_ZONE: Europe/London
USERMAP_UID: 1000
USERMAP_GID: 1000
volumes:
- ./data:/usr/src/paperless/data
- ./media:/usr/src/paperless/media
- ./export:/usr/src/paperless/export
- ./consume:/usr/src/paperless/consume
depends_on:
- db
- broker
restart: unless-stopped

And .env (tutorial 59):

DB_PASSWORD=long-random-string
SECRET_KEY=another-long-random-string

docker compose up -d
docker compose run --rm webserver createsuperuser
sudo ufw allow 8000/tcp

2. First document

Copy any PDF or JPG into ./consume. Within a minute it disappears from the folder and appears in the web UI at http://192.168.1.50:8000, OCR'd and with a guessed date. Click it: the text is searchable, the original is kept untouched.

3. Ways to feed it

4. Teach it to tag

Create Correspondents (British Gas, the council, the school), Document types (invoice, letter, warranty) and Tags (tax, house, car) and set each to Auto matching. Paperless learns from the documents you've already classified and, after a dozen or so, tags new ones itself. Correct the mistakes and it gets better.

5. Keep the originals safe

Everything is in ./media/documents/originals as ordinary files, plus the database in ./postgres. Back up the whole ~/docker/paperless folder (tutorials 23 and 55). For a portable export that doesn't need Paperless to read:

docker compose exec webserver document_exporter ../export

That writes every document plus a JSON manifest into ./export — restorable into a fresh install with document_importer.

Reverse proxy

docs.example.com → 127.0.0.1:8000 (tutorial 28) with client_max_body_size 100M and the WebSocket lines; set PAPERLESS_URL to match. Behind the VPN is a good home for it — it's your whole paper life.

Troubleshooting

Document stuck in consume. Permissions: the folder must be writable by UID 1000. docker compose logs -f webserver shows the consumer's complaint.

OCR is wrong or slow. Language: PAPERLESS_OCR_LANGUAGE: eng+deu for mixed. Slow is normal on a Pi for a 40-page scan; it works through a queue.

Dates are wrong. Set PAPERLESS_DATE_ORDER: DMY for UK-style dates.

"CSRF verification failed" through the proxy. PAPERLESS_URL must be the exact https address you're using.

Wrapping up

Three containers, a consume folder, a superuser. Scan or photograph everything once, tag the first twenty by hand, and from then on the paperwork files itself. The originals are plain files in a folder you back up, so you're never locked in.

Call us