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 $USER

The 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 version

Install 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 32

That 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.1 only — Paperless-ngx is not exposed directly to the internet, but reached through a reverse proxy with HTTPS.
  • data holds app data, media holds original documents and their archive versions, consume is the watched folder: any file dropped there gets processed automatically.
  • PAPERLESS_OCR_LANGUAGE uses eng in 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: postgresql must be set — Paperless 3 no longer infers it from PAPERLESS_DBHOST.
  • The database password in POSTGRES_PASSWORD and PAPERLESS_DBPASS must match exactly.

Run it and verify:

docker compose up -d
docker compose ps

Wait 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

AspectPaperless-ngxPlain folders / DrivePaid archive service
Full-text searchYes, local OCRFilename only (usually)Yes
Tags and automatic rulesYesManualYes, varies
CostFree, server rent onlyFree up to storage limitsMonthly subscription
Document privacyData on your serverDepends on providerData at provider
Who runs the serverYouProviderProvider

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:

  1. The media volume — original documents and their archive versions.
  2. The data volume — Paperless-ngx app data.
  3. 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).sql

Then 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 version works.
  • 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