Every household has the drawer. Tax letters, warranty cards, the lease, a pay stub from three jobs ago, the vet's invoice you'll need exactly once. It all goes in the drawer, and finding anything means digging through all of it.

Paperless-ngx replaces the drawer. Scan a document, or drop in a PDF, and it reads the text with OCR, figures out who sent it and what it is, tags it, and files it into a searchable archive on your own server. It's one of the most popular self-hosted apps there is, with around 45,000 stars on GitHub, and once it's running it quietly changes how you deal with paper.

Where it came from

Paperless-ngx is the third generation of the idea. The original Paperless was followed by Paperless-ng, a rewrite with a modern interface. When that project's single maintainer stepped back, the community forked it as Paperless-ngx so that a team would carry it forward instead of one person. It's GPL-3.0 licensed, built on Django and Angular, and on the 3.x release line.

What it does

  • OCR on everything. It uses the open-source Tesseract engine to read more than 100 languages, adding searchable, selectable text even to image-only scans.
  • Archival PDFs. Each document is stored as a PDF/A, the format built for long-term storage, next to the untouched original.
  • Automatic filing. A machine-learning classifier trained on your own documents suggests and assigns tags, correspondents and document types.
  • Full-text search with autocomplete, relevance ranking, highlighted matches and "more like this".
  • Many file types. PDFs, images and plain text work out of the box. Word, Excel, PowerPoint and LibreOffice files work with an optional add-on.
  • Email import. It watches mail accounts and pulls in attachments according to rules you define.
  • Workflows that assign metadata, send emails, call webhooks and more, based on triggers.
  • Multiple users with global and per-document permissions, two-factor login, and share links that can expire.
  • Your files stay plain. Documents are ordinary files on disk, in a folder layout you control. Nothing is locked inside a database.

The four things every document has

Paperless doesn't use folders. Everything is organized with four kinds of metadata, and understanding them is the key to the whole app:

CORRESPONDENT   who it's from or to      Electric Co, IRS, Dr. Patel
DOCUMENT TYPE   what kind of thing it is  invoice, contract, statement
TAGS            any labels you like       taxes-2026, car, paid, inbox
STORAGE PATH    where the file lands      {{ correspondent }}/{{ created_year }}/{{ title }}

Tags are the clever part. A document can carry many tags, so "car insurance renewal" can live under car, insurance and taxes-2026 at the same time. A folder can't do that. Add custom fields (amounts, due dates, policy numbers) and an archive serial number that matches the label on the physical copy in your binder, and you can find anything, digital or paper.

Install it with Docker

The quickest route is the official install script. It asks a few questions, writes the compose files, starts the containers and creates your admin account:

bash -c "$(curl --location --silent --show-error \
  https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/install-paperless-ngx.sh)"

If you prefer to see every piece, set it up by hand. The project ships compose files for SQLite, PostgreSQL and MariaDB, each with an optional -tika variant that adds Office document and email support. PostgreSQL is the recommended choice for new installs. Trimmed down, the Postgres version looks like this:

services:
  broker:
    image: docker.io/valkey/valkey:9-alpine
    restart: unless-stopped
    volumes:
      - redisdata:/data
  db:
    image: docker.io/library/postgres:18
    restart: unless-stopped
    volumes:
      - pgdata:/var/lib/postgresql
    environment:
      POSTGRES_DB: paperless
      POSTGRES_USER: paperless
      POSTGRES_PASSWORD: paperless
  webserver:
    image: ghcr.io/paperless-ngx/paperless-ngx:latest
    restart: unless-stopped
    depends_on: [db, broker]
    ports:
      - "8000:8000"
    volumes:
      - data:/usr/src/paperless/data
      - media:/usr/src/paperless/media
      - ./export:/usr/src/paperless/export
      - ./consume:/usr/src/paperless/consume
    env_file: docker-compose.env
    environment:
      PAPERLESS_REDIS: redis://broker:6379
      PAPERLESS_DBHOST: db
      PAPERLESS_DBENGINE: postgresql
volumes:
  data:
  media:
  pgdata:
  redisdata:

Grab the matching docker-compose.env and .env from the repo's docker/compose folder, then set at least these in docker-compose.env:

# Required. Generate one with:
#   python3 -c "import secrets; print(secrets.token_urlsafe(64))"
PAPERLESS_SECRET_KEY=change-me

PAPERLESS_TIME_ZONE=America/New_York
PAPERLESS_OCR_LANGUAGE=eng

# Your host user's IDs (run: id -u / id -g), so you can
# write into the consume folder
USERMAP_UID=1000
USERMAP_GID=1000

# Only if you'll reach it from a domain
#PAPERLESS_URL=https://paperless.example.com

Then:

docker compose pull
docker compose up -d
# open http://localhost:8000 and create your superuser

Getting paper in

There are four doors into Paperless, and most setups end up using all of them:

  • The consume folder. Anything dropped into ./consume is picked up, processed and moved into the archive. Point your scanner's "scan to network folder" at it through a Samba share or FTP, and scanning becomes a one-button job. (The file leaves the consume folder once it's processed. That's expected.)
  • Drag and drop. Drop a file anywhere in the web interface.
  • Email. Add an IMAP account under Settings → Mail, then write rules: which folder to watch, which attachments to take, which tags to apply, and what to do with the message afterwards.
  • Phone. Community mobile apps scan and upload straight from your camera. The project wiki keeps a list of them.

Tip: if your consume folder lives on an NFS share, set PAPERLESS_CONSUMER_POLLING_INTERVAL. Network file systems don't send the change notifications Paperless listens for, so without polling, new files just sit there.

Let it file things for you

This is where Paperless earns its keep. Every tag, correspondent, document type and storage path has a matching rule that runs against each new document's text:

Any      any of the words appear        "electric power"
All      every word appears, any order  "invoice 2026"
Exact    the exact phrase appears       "Bank of America"
Regex    a regular expression           Policy\s+No\.\s*\d+
Fuzzy    close-enough partial match     Hydro Quebec
Auto     learn from how you've filed things before

Auto is the default, and it gets good fast. File your first few dozen documents by hand and the classifier learns your habits. A new statement from your bank arrives already tagged, typed and assigned. Use the explicit rules for the cases where you want certainty, such as "anything containing my policy number goes under insurance".

Workflows

Workflows go a step further: when this happens, do that. Triggers include a document starting to be consumed, being added, being updated, or a scheduled date. Actions include assigning or removing metadata, sending an email, calling a webhook, removing a PDF password, or moving a document to the trash. Some real-world uses:

  • Everything that arrives by email from your accountant gets the taxes tag and is shared with your partner's account.
  • Warranty documents trigger a scheduled reminder email 30 days before a custom "warranty ends" date field.
  • Bank statements, which always come password-protected, get the password stripped on arrival so they can be OCR'd and searched.
  • A webhook pings your home-automation system whenever a new invoice lands.

Barcodes and ASNs

For heavy paper users: Paperless reads barcodes on PDF pages. Print a sheet of ASN barcode stickers, put one on each paper document before scanning, and the archive serial number is set automatically. To find the original later, read the ASN off the screen and pull that number from your binder. Barcode pages can also split a big batch scan into separate documents.

The optional AI features

Recent versions add opt-in AI features on top of the classic classifier: LLM-written suggestions for titles, dates and tags, chatting with a single document or your whole archive, and similar-document search. They're off by default and work with a local model through Ollama or any OpenAI-compatible API.

Think before you switch them on. With a remote provider, your document text leaves your server, and that defeats much of the point of self-hosting tax returns and medical letters. If you want these features, a local model keeps everything at home.

Backups, and one big warning

The project says it plainly: Paperless stores your documents unencrypted, and you should never run it on an untrusted host. Run it on your own hardware or a server you control, keep it off the open internet (use a VPN like WireGuard or Tailscale to reach it from outside), and back it up.

For backups, use the built-in exporter. It writes every document plus all metadata into a folder that can be re-imported into a fresh install:

docker compose exec -T webserver document_exporter ../export

Put that on a nightly cron job and copy the export folder off the machine with your usual backup tool. A document archive with no off-site backup is just a fancier drawer that can burn down.

Running it on small hardware

Paperless runs fine on a Raspberry Pi 4 or a cheap mini PC. On low-power machines:

  • Use SQLite instead of Postgres to save memory.
  • Set PAPERLESS_OCR_PAGES=1. The first page is usually enough to find a document.
  • Lower PAPERLESS_TASK_WORKERS and PAPERLESS_THREADS_PER_WORKER, so a big batch doesn't freeze the machine.
  • Set PAPERLESS_WEBSERVER_WORKERS=1.
  • Let your scanner do the OCR if it can, and leave PAPERLESS_OCR_MODE on auto.

Tips from the trenches

  • Use an inbox tag. New documents get the inbox tag automatically. Review the inbox once a week, fix anything mis-filed, and remove the tag. Every correction trains the classifier.
  • Start with the backlog in batches. Scanning ten years of paper in one go is overwhelming. Do a box a weekend.
  • Keep the paper you're legally required to keep. A scan isn't always a legal substitute. Put an ASN on those originals and keep them in a binder in number order.
  • Try the demo first. There's a public demo at demo.paperless-ngx.com (login demo / demo). It resets often, so don't upload anything real.

Paperless-ngx or Mayan EDMS?

The other big name in self-hosted document management is Mayan EDMS, which gets its own transmission today. The short version: Paperless-ngx is built for a household or small office that wants paper to vanish into a searchable archive with as little effort as possible. Mayan is built for organizations that need formal document types, approval workflows, version control and fine-grained access control, and it asks for more setup and more server in return. For most homelabs, Paperless is the right first stop.

Verdict

Paperless-ngx is the rare self-hosted app that pays you back in time every week. The setup is a compose file. The first weekend of scanning is a chore. After that, paper stops being a problem: it goes in the scanner, comes out tagged and searchable, and the drawer gets recycled.

Start with the GitHub repo and the documentation, which is excellent. Links are also in the downloads directory and the resource index.

End of transmission.