Paperless-ngx turns a pile of paper (and a downloads folder full of PDFs) into a searchable archive. Drop in a scan and it reads the text with OCR, guesses the correspondent, date and document type, and files it with tags. A year later, finding "that insurance letter from March" takes three seconds.

Prerequisites

  • Docker Engine and the Compose plugin
  • Nginx Proxy Manager running from /opt/npm if you want HTTPS access
  • About 2 GB of RAM free. OCR is the hungry part, mostly while documents are being processed.

1. Download the official Compose files

Paperless publishes ready-made Compose files. I use the PostgreSQL variant:

sudo mkdir -p /opt/paperless
cd /opt/paperless
BASE=https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose
sudo curl -fsSL $BASE/docker-compose.postgres.yml -o docker-compose.yml
sudo curl -fsSL $BASE/docker-compose.env -o docker-compose.env
sudo curl -fsSL $BASE/.env -o .env

That gives you three services: a Redis broker, a Postgres database and the Paperless web server, with named volumes for their data and two folders next to the file. consume is the inbox, where anything you drop in gets imported. export is where backups go.

2. Make two edits to the Compose file

Open docker-compose.yml. Under the webserver service, change the published port so it's localhost-only:

    ports:
      - "127.0.0.1:8000:8000"

And add Paperless to NPM's network so the proxy can reach it, under webserver:

    networks:
      - default
      - npm

plus, at the very bottom of the file:

networks:
  npm:
    external: true
    name: npm_default

3. Set the important options

Edit docker-compose.env and set (uncommenting where needed):

PAPERLESS_URL=https://docs.example.com
PAPERLESS_SECRET_KEY=paste-a-long-random-string-here
PAPERLESS_TIME_ZONE=America/Denver
PAPERLESS_OCR_LANGUAGE=eng
USERMAP_UID=1000
USERMAP_GID=1000

Generate the secret key with openssl rand -base64 48. USERMAP_UID/GID should match your own user (id tells you), so files in consume and export are owned by you rather than root.

4. Start it and create the admin account

sudo docker compose pull
sudo docker compose up -d

On your own computer:

ssh -L 8000:localhost:8000 your-user@your-server-ip
# then open http://localhost:8000

The first visit asks you to create the superuser (admin) account. Then upload a test PDF with the upload button and watch it appear with its text recognized, usually within a minute.

5. HTTPS and a good first setup

In NPM, add a proxy host for docs.example.com → http · webserver · 8000 (that's the service name in the official file) with an SSL certificate and Force SSL. Make sure it matches the PAPERLESS_URL you set.

Before importing hundreds of documents, create a few correspondents (your bank, your insurer, your employer) and tags (taxes, house, car). Paperless learns from how you file the first batch and starts auto-assigning them, so ten minutes of tidy filing up front pays off for years.

6. Updates and backups

cd /opt/paperless
sudo docker compose pull && sudo docker compose up -d

Backups: use the built-in document exporter, which the project recommends. It writes every document, plus all your tags, correspondents and settings, into the export folder in a format that can be imported into a fresh install:

cd /opt/paperless
sudo docker compose exec -T webserver document_exporter ../export

Schedule that nightly with cron, then copy export off the server, ideally encrypted, because this folder is your tax returns and contracts. My Google Drive backup setup encrypts before upload for exactly this reason.

Troubleshooting

  • Documents sit in consume and never import: usually permissions. USERMAP_UID/GID must be able to read the files. Check sudo docker compose logs webserver.
  • "CSRF verification failed" when logging in through the domain: PAPERLESS_URL doesn't exactly match the address in your browser.
  • OCR text is gibberish: the wrong PAPERLESS_OCR_LANGUAGE, or a low-resolution scan. Scan at 300 DPI.

Official documentation: Paperless-ngx docs · Repository: paperless-ngx/paperless-ngx