Paperless-ngx: Self-Hosted Document Archive with OCR and Automatic Tags
Your documents exist — but never turn up when you need them
Tax receipts, contracts, insurance policies, payslips, bills — all stored somewhere. The problem is, "somewhere" can mean the Downloads folder, an old email attachment, a box in a cupboard, or all three at once. When a document is suddenly needed, you spend your time hunting for it instead of using it.
Paperless-ngx was built for that. It is an open-source document archive that runs on your own server: every document that comes in — a scan, a photo, or a digital PDF — gets its text read with OCR (optical character recognition), fully indexed, then tagged and grouped automatically. After that, you just type a keyword, like a bank name or contract number, and the document shows up. No folder structure to memorize.
The difference from simply storing PDFs in Google Drive: Paperless-ngx search reads document contents, not just filenames. And the difference from a paid archive service: the data sits on your server, with no per-document fee and nobody scanning your private documents for ads.
One thing to be honest about up front: Paperless-ngx archives; it does not turn a bad document into a good one. A blurry or skewed scan still produces poor OCR. The quality of your archive depends heavily on the quality of the scans going in.
What you need
- A VPS with a practical baseline of 2 CPUs and 4 GB of RAM (not a vendor figure). OCR loads the CPU — the more documents at once, the more you feel it. For a home archive, this is enough.
- Docker and Docker Compose.
- Enough disk: archived documents are stored twice (original + searchable archive version), so plan for double the size of your archive.
- Optional but strongly recommended: a domain or subdomain, for example
documents.yourdomain.com, so outside access goes over HTTPS.
Commands here use Ubuntu 24.04; on another distro, adapt the package manager — the Paperless-ngx steps stay the same.
Install Docker
If Docker is not installed yet, install it from Ubuntu's repositories:
sudo apt update
sudo apt install -y docker.io docker-compose-v2
sudo systemctl enable --now docker
sudo usermod -aG docker $USERThe last command adds your user to the docker group so you skip sudo for Docker. Log out and back in, then check:
docker --version
docker compose versionInstall Paperless-ngx with Docker Compose
Paperless-ngx has three core services: the web app, a Postgres database for metadata, and a queue broker (Redis) for background jobs like OCR. Two optional services — Gotenberg and Tika — add the ability to convert Office documents and other formats into PDF; the official -tika compose variant provides them, but a first install does not need them.
First, prepare the directory and a secret key:
sudo mkdir -p /opt/paperless
sudo chown "$USER:$USER" /opt/paperless
cd /opt/paperless
openssl rand -base64 32That output becomes your PAPERLESS_SECRET_KEY — never use a sample key from any article.
Then create docker-compose.yml:
services:
broker:
image: redis:7-alpine
container_name: paperless_broker
restart: unless-stopped
volumes:
- redisdata:/data
db:
image: postgres:16-alpine
container_name: paperless_db
restart: unless-stopped
environment:
POSTGRES_DB: paperless
POSTGRES_USER: paperless
POSTGRES_PASSWORD: REPLACE_WITH_STRONG_PASSWORD
volumes:
- pgdata:/var/lib/postgresql/data
webserver:
image: ghcr.io/paperless-ngx/paperless-ngx:latest
container_name: paperless_web
restart: unless-stopped
depends_on:
- db
- broker
ports:
- "127.0.0.1:8000:8000"
environment:
PAPERLESS_REDIS: redis://broker:6379
PAPERLESS_DBHOST: db
PAPERLESS_DBENGINE: postgresql
PAPERLESS_DBNAME: paperless
PAPERLESS_DBUSER: paperless
PAPERLESS_DBPASS: REPLACE_WITH_STRONG_PASSWORD
PAPERLESS_SECRET_KEY: REPLACE_WITH_YOUR_SECRET_KEY
PAPERLESS_TIME_ZONE: Asia/Jakarta
PAPERLESS_OCR_LANGUAGE: eng
PAPERLESS_ADMIN_USER: admin
PAPERLESS_ADMIN_PASSWORD: REPLACE_WITH_ADMIN_PASSWORD
PAPERLESS_URL: https://documents.yourdomain.com
volumes:
- data:/usr/src/paperless/data
- media:/usr/src/paperless/media
- ./consume:/usr/src/paperless/consume
volumes:
redisdata:
pgdata:
data:
media:In short, what that file does:
- Port 8000 is bound to
127.0.0.1only — Paperless-ngx is not exposed directly to the internet, but reached through a reverse proxy with HTTPS. dataholds app data,mediaholds original documents and their archive versions,consumeis the watched folder: any file dropped there gets processed automatically.PAPERLESS_OCR_LANGUAGEusesengin the example for English-language documents. Adjust it to your documents' language — Paperless-ngx supports many OCR languages, and you can combine several language codes.PAPERLESS_DBENGINE: postgresqlmust be set — Paperless 3 no longer infers it fromPAPERLESS_DBHOST.- The database password in
POSTGRES_PASSWORDandPAPERLESS_DBPASSmust match exactly.
Run it and verify:
docker compose up -d
docker compose psWait 2–3 minutes on first start while images download and the database initializes. Open http://127.0.0.1:8000 temporarily through an SSH tunnel (ssh -L 8000:127.0.0.1:8000 user@VPS-IP), then log in with the admin account from the Compose file. After your first login, remember: documents here can be very personal, so outside access must go over HTTPS (reverse proxy or Tunnel) before you upload anything sensitive.
Three ways to get documents in
1. Through the consume folder. Drop files into the ./consume folder on the server — via scp, rsync, or a folder synced from your phone — and Paperless-ngx picks them up itself, runs OCR, then moves them into the archive. Best for bulk scanning: scan a stack, copy it all at once, let the queue work.
2. Through web upload. Open the dashboard, drag files into the upload area. Good for one or two documents arriving by email or download.
3. Through email. Paperless-ngx can fetch attachments from a mailbox over IMAP. Useful when bills arrive by email — but use a dedicated mailbox, not your main one.
Once in, Paperless-ngx runs OCR locally with Tesseract — nothing goes to a cloud service — stores the original plus a searchable PDF, then indexes the text.
Automatic tags: from pile to system
Archiving alone is not enough — without structure, you just move the mess from folders into an app. Paperless-ngx has three tools for this:
- Correspondent (sender): who issued the document — bank, power company, tax office. After you tag a few documents from the same sender, Paperless-ngx can predict the sender of new documents.
- Document type: receipt, contract, bill, report. Like correspondent, its predictions improve once you give it enough examples.
- Tags and matching rules: you can create rules like "if the document text contains the power company's name, add the Electricity tag". These rules turn the archive from a storage place into a system that tidies itself.
What works in practice: don't create 50 tags on day one. Start with correspondents for the 5–10 most frequent senders, one tag per big category (Finance, Tax, Home, Health), then add matching rules gradually as patterns show up. Paperless-ngx automatic predictions only become reliable after a dozen or so similar documents have been tagged — early on, manual correction is part of the process, not a failure.
Also use saved views from the start — e.g. "unpaid bills" or "this year's tax documents" — to skip repeated searches.
Paperless-ngx vs folders vs paid archive services
| Aspect | Paperless-ngx | Plain folders / Drive | Paid archive service |
|---|---|---|---|
| Full-text search | Yes, local OCR | Filename only (usually) | Yes |
| Tags and automatic rules | Yes | Manual | Yes, varies |
| Cost | Free, server rent only | Free up to storage limits | Monthly subscription |
| Document privacy | Data on your server | Depends on provider | Data at provider |
| Who runs the server | You | Provider | Provider |
Paperless-ngx wins on search and privacy at minimal cost — but backup and security are on you, as with any self-hosted service.
Backup: three things that must survive
A document archive is one of the most painful things to lose, because some documents cannot be recreated. Back up all three:
- The
mediavolume — original documents and their archive versions. - The
datavolume — Paperless-ngx app data. - The Postgres database — metadata, tags, and rules. Dump it from the database container:
docker exec -t paperless_db pg_dumpall -U paperless > /opt/paperless/backup-$(date +%F).sqlThen copy the media volume, data volume, SQL dump, and docker-compose.yml (passwords kept separately, somewhere safe) to another location — another VPS or cloud storage at minimum. Schedule it nightly. And as usual: test a restore occasionally in a separate folder; a backup never tested for restore is still just an assumption.
Checklist before you finish
- Docker and Docker Compose installed,
docker compose versionworks. - Paperless-ngx up via Compose, all three containers (web, db, broker) running.
- Admin login works, and outside access already goes over HTTPS (not plain HTTP).
- One test document went in through the consume folder, OCR finished, and its text is findable via search.
- Correspondents and basic tags created for the most frequent senders.
- Media volume, data volume, and database dump included in the backup schedule.
If every item is checked, your archive already works on its own: documents come in, get read, get labeled, and show up when searched — no subscription fee and no documents wandering around on someone else's servers.
Which document do you search for most often but never find?
Read also: Docker Volumes and Backup: Don't Lose Your Data, Automatic Encrypted VPS Backup to Google Drive, Reading Server Logs with journalctl and logrotate.


Komentar
Posting Komentar