homelab-blueprint/docker-compose-files/paperless-ngx
Brian Pooe 1815beadf4 refactor: restructure docs, sync stacks with Caddyfile, harden compose templates
- Add compose stacks for apps already proxied by Caddy: bento-pdf,
  it-tools, paperless-ngx, and beszel-hub (with Makefile targets)
- Remove the unused Vault stack and the drawio Caddyfile block
- Fix Caddyfile gramps upstream to port 80 to match the compose file
- Bring immich and gramps-web up to the shared template pattern
  (no-new-privileges, log rotation, memory limits, healthchecks)
- Single-quote vaultwarden SSO_AUDIENCE_TRUSTED so regex values like
  ^\d{18}$ render as valid YAML
- Move root docs into kebab-case topic folders, rebuild the docs index
  to cover every doc, and fix all broken links
2026-07-03 17:45:16 +02:00
..
.env.sample refactor: restructure docs, sync stacks with Caddyfile, harden compose templates 2026-07-03 17:45:16 +02:00
README.md refactor: restructure docs, sync stacks with Caddyfile, harden compose templates 2026-07-03 17:45:16 +02:00
template.yaml refactor: restructure docs, sync stacks with Caddyfile, harden compose templates 2026-07-03 17:45:16 +02:00

Paperless-ngx

Document management system that scans, indexes, and archives paper documents with full-text OCR search. Runs with the bundled SQLite database and a Redis task broker.

Persistent Data

  • paperless_data named volume — database, search index, classification model.
  • paperless_media named volume — original and archived documents.
  • paperless_export named volume — target for document_exporter backups.
  • PAPERLESS_CONSUME_DIR host directory — watched for new documents; safe to empty once documents are ingested.

Installation

  1. Create .env if it does not exist:

    cp -n .env.sample .env
    
  2. Set the required values in .env:

    TZ=Africa/Johannesburg
    PAPERLESS_URL=https://paperless-ngx.home.example.com
    PAPERLESS_SECRET_KEY=<random-secret>   # openssl rand -base64 48
    PAPERLESS_CONSUME_DIR=/opt/appdata/paperless/consume
    PUID=1000
    PGID=1000
    
    DOCKERLOGGING_MAXFILE=3
    DOCKERLOGGING_MAXSIZE=10m
    

    PAPERLESS_URL must match the URL used in the browser, otherwise CSRF checks fail behind the reverse proxy.

  3. Create the consume directory:

    mkdir -p /opt/appdata/paperless/consume
    chown 1000:1000 /opt/appdata/paperless/consume
    
  4. Deploy with make:

    make deploy-paperless
    

    Manual equivalent:

    ./substitute_env.sh docker-compose-files/paperless-ngx/template.yaml docker-compose.paperless.yml .env
    docker compose -f docker-compose.paperless.yml config --quiet
    docker compose -f docker-compose.paperless.yml up -d
    
  5. Create the first user, unless PAPERLESS_ADMIN_USER is set in .env:

    docker exec -it paperless createsuperuser
    
  6. Verify the containers and open http://<host-ip>:8000:

    docker compose -f docker-compose.paperless.yml ps
    docker compose -f docker-compose.paperless.yml logs --tail=100 paperless
    

Reverse Proxy

The Caddyfile proxies paperless-ngx.<domain> to this host on port 8000 with header_up Host {host} so CSRF origin checks pass. After changing the port, update docker-compose-files/caddy/Caddyfile_template and run make reload-caddy.

Backup

Run the built-in exporter, then back up the paperless_export volume (it contains documents plus a manifest that restores tags, correspondents, and metadata):

docker exec paperless document_exporter /usr/src/paperless/export --zip

Useful Commands

# Tail logs
docker compose -f docker-compose.paperless.yml logs -f paperless

# Retrain the document classifier
docker exec paperless document_create_classifier

# Re-run OCR on a document
docker exec paperless document_archiver --overwrite --document <id>