SELFHOST.COMPUTER

Paperless-ngx: a searchable paper archive on your own server

#paperless-ngx#docker#backups

Paperless-ngx turns a drawer of scanned letters, invoices and contracts into a searchable archive. You drop a PDF in a folder, it runs OCR, tags it, and a year later you find the heating invoice by typing one word. It is one of the most recommended apps on r/selfhosted for good reason: it solves a real problem and, once set up, needs very little attention.

What it needs

  • About 1.5 to 2 GB of RAM for the web app, workers, Redis and Postgres together. OCR spikes CPU while a document is processed.
  • Disk space for originals plus the searchable archive copies. A few GB covers thousands of pages.
  • A small VPS is fine. See the VPS size calculator and the RAM budget post.

Get the official compose files

The project ships a Postgres-based compose file. Download it rather than copying from a blog, because settings change between releases:

mkdir -p ~/stack/paperless && cd ~/stack/paperless
wget -O docker-compose.yml https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/docker-compose.postgres.yml
wget -O docker-compose.env https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/docker-compose.env

Edit docker-compose.env and set at least:

PAPERLESS_URL=https://docs.example.com
PAPERLESS_SECRET_KEY=a-long-random-string
PAPERLESS_TIME_ZONE=Europe/Berlin
PAPERLESS_OCR_LANGUAGE=eng+deu
PAPERLESS_OCR_LANGUAGES=deu

Generate the secret key with the secret generator. PAPERLESS_OCR_LANGUAGE lists the languages your documents are in; wrong languages are the number one cause of bad OCR. Also change the Postgres password in the compose file, and pin the Paperless image to a version tag instead of latest. See updating containers safely.

Start it and create a user

docker compose up -d
docker compose exec webserver createsuperuser

The first start takes a minute while the database migrates. Do not publish port 8000 to the internet. Put it behind Caddy instead:

docs.example.com {
    request_body {
        max_size 200MB
    }
    reverse_proxy webserver:8000
}

If you have not set up a proxy yet, follow the Caddy and Docker guide.

Get documents in

  • Consume folder: anything placed in the consume directory is picked up automatically. Point your network scanner (SMB or SFTP) at it.
  • Web upload: drag and drop in the browser.
  • Phone: mobile apps for Paperless-ngx can scan and upload with the camera.
  • Email: configure a mail account and rules to import attachments from, for example, your invoices folder.

Tags, correspondents and matching

Don't over-plan. Start with a few document types (invoice, contract, letter), correspondents (your bank, insurer, landlord) and tags. Set their matching to Auto and Paperless learns from the documents you've already filed. After 30 to 50 documents it guesses most of them right. Use a simple storage path such as {{ correspondent }}/{{ created_year }}/{{ title }} so the files on disk are still understandable if you ever leave the app.

Back it up

Do not just copy the data folder while the app runs. Use the built-in exporter, which writes your documents and metadata in a portable form:

docker compose exec webserver document_exporter ../export

Schedule that with a cron job, then send the export folder offsite with restic. These are often your most important documents (tax, contracts, insurance), so the backup must be on a different machine from the server. The backup planner helps size it. Test a restore into a fresh instance at least once.

Security

Paperless holds sensitive personal data. Keep it behind a VPN such as WireGuard or Tailscale if you only use it at home or on your phone. If it must be public, use a strong password, enable two-factor authentication in the user settings, and harden SSH and the firewall as in the SSH hardening guide.

Common problems

  • Garbled OCR: check the OCR language setting, and scan at 300 dpi.
  • Uploads fail: the proxy body limit is too small.
  • Permission errors on the consume folder: set USERMAP_UID and USERMAP_GID in the env file to the owner of the folders.
  • High CPU after bulk import: normal; lower PAPERLESS_TASK_WORKERS on small servers.

Is it worth it?

If you keep paper records or get invoices by email, yes. The payoff is the day you need a document in five seconds. Looking for more apps to pair with it? See what to self-host first and the self-hosted Dropbox alternatives.

< all posts · netcup voucher codes

Keep reading