Only media/consume/export/trash stay on the UNAS share; SQLite over NFS risks lock contention and corruption. |
||
|---|---|---|
| .. | ||
| .env.sample | ||
| README.md | ||
| template.yaml | ||
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
Split between local disk and the UNAS paperless_data share (see
nfs-mounts):
paperless_datanamed volume (local disk) — SQLite database, search index, and classification model. Kept off NFS because SQLite file locking over NFS risks corruption and slow queries.- Share dirs, NFS-mounted on the Proxmox host and bind-mounted into the LXC
at
PAPERLESS_DATA_ROOT:media/— original and archived documents.consume/— watched for new documents; safe to empty once ingested.export/— target fordocument_exporterbackups.trash/— deleted documents until emptied.
The share binds use create_host_path: false, so the stack refuses to start
if the share is not mounted. Redis broker state is in the
paperless_redis_data named volume.
Installation
-
Create
.envif it does not exist:cp -n .env.sample .env -
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_DATA_ROOT=/mnt/unas/paperless_data PUID=1000 PGID=1000 DOCKERLOGGING_MAXFILE=3 DOCKERLOGGING_MAXSIZE=10mPAPERLESS_URLmust match the URL used in the browser, otherwise CSRF checks fail behind the reverse proxy. -
Ensure the share is bind-mounted into the LXC and owned by the container user (host-side UID for an unprivileged LXC is
LXC_IDMAP_BASE + PUID):# On the Proxmox host pct set <vmid> -mp0 /mnt/unas/paperless_data,mp=/mnt/unas/paperless_data mkdir -p /mnt/unas/paperless_data/{data,media,consume,export,trash} chown -R 101000:101000 /mnt/unas/paperless_data -
Deploy with
make:make deploy-paperlessManual 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 -
Create the first user, unless
PAPERLESS_ADMIN_USERis set in.env:docker exec -it paperless createsuperuser -
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 PAPERLESS_DATA_ROOT/export (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>