Create a Paperless-ngx Document Workflow with OCR and Restore Validation
Deploy a small Paperless-ngx Lab from the project's maintained Docker Compose files, ingest and OCR a test document, then use the supported document exporter/importer workflow to...
Expected Outcome
A working Paperless-ngx Lab with a searchable test document, a version-matched full export, and a documented restore rehearsal using the supported document importer.
Assumptions
A Linux host with Docker Engine and the Docker Compose v2 plugin.
At least 2 GB of free RAM and sufficient storage for documents plus exports.
A scanner or test PDF/image to place in the consumption directory.
A backup destination outside the live Paperless Docker volumes.
This Lab uses the project's SQLite Compose file to keep the recovery exercise small; Paperless-ngx recommends PostgreSQL for new durable installations.
Bill of Materials
Paperless-ngx maintained Compose files from the official repository.
One disposable test document with recognizable text.
A location where the generated `export` directory can be copied off-host.
Build Steps
- Verify Docker Compose and create the Lab directory
Use Compose v2. Do not install the retired standalone docker-compose executable just for this Lab.
Changes system state: review before running
docker --version docker compose version mkdir -p ~/paperless-lab && cd ~/paperless-lab
- Download the maintained Paperless-ngx Compose files
Download the official SQLite Compose definition, Docker environment template, and project .env as files for review. This avoids executing the project's convenience installer through a remote shell and keeps the exact configuration used by the Lab visible.
Read-only command: verify target and scope
curl -fLo docker-compose.yml https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/docker-compose.sqlite.yml curl -fLo docker-compose.env https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/docker-compose.env curl -fLo .env https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/main/docker/compose/.env sed -n '1,220p' docker-compose.yml sed -n '1,220p' docker-compose.env
- Set the required application secret and local identity mapping
The current Docker environment template requires a unique PAPERLESS_SECRET_KEY. Generate one locally and set UID/GID values so the host user and container can work with the consumption/export directories. Preserve the reviewed configuration as part of your recovery evidence.
Security-sensitive: review before running
SECRET=$(python3 -c 'import secrets; print(secrets.token_urlsafe(64))') sed -i "s|^PAPERLESS_SECRET_KEY=.*|PAPERLESS_SECRET_KEY=$SECRET|" docker-compose.env printf '\nUSERMAP_UID=%s\nUSERMAP_GID=%s\n' "$(id -u)" "$(id -g)" >> docker-compose.env chmod 600 docker-compose.env docker compose config --quiet
- Pull and start Paperless-ngx
Use the maintained Compose definition. The container image already includes the OCR tooling needed by Paperless-ngx; installing a second Tesseract package on the host does not configure OCR inside the container.
Changes system state: review before running
docker compose pull docker compose up -d docker compose ps docker compose logs webserver --tail=80
- Create the first user and ingest one test document
Open the local Paperless-ngx web interface and create the first account when prompted. Copy one disposable PDF or image into the host consume directory that the official Compose file mounts into the container, then watch the task complete.
Changes system state: review before running
cp '<test-document>' ./consume/ docker compose logs webserver --since=5m
- Validate OCR and document retrieval
In the Paperless UI, confirm the test document appears, its extracted text contains a known phrase from the source, and searching for that phrase returns the document. This is the functional boundary for OCR; container health alone is not enough.
- Create a supported full export
Paperless-ngx documents the document_exporter as a backup/migration path that includes documents, thumbnails, metadata, and database contents. Avoid replacing this with a blind rsync --delete of live application directories. Make sure Paperless is not actively consuming documents while the export runs.
Read-only command: verify target and scope
docker compose exec -T webserver document_exporter ../export --compare-checksums --no-progress-bar
Manual or UI step
find ./export -maxdepth 2 -type f | head -50
test -f ./export/manifest.json && echo 'Manifest present'
- Record the running Paperless version with the export
Capture the image/container version evidence beside the export so a future restore can use a compatible application version.
Read-only command: verify target and scope
docker compose images > ./export/container-images.txt docker compose exec -T webserver document_exporter --help | head -20 > ./export/exporter-help.txt
Manual or UI step
tar -C . -czf paperless-export-$(date +%Y%m%d-%H%M%S).tar.gz export
- Rehearse the importer in an isolated copy
A true restore test should not overwrite the live Lab. Create a second disposable Paperless environment at the same application version, place a copy of the export into its mounted export directory, and run document_importer ../export. Confirm the restored account metadata and test document appear. The exact isolated Compose paths depend on where you choose to stage the second instance, so keep this as a deliberate recovery exercise rather than running an importer against the live database.
Validation
The Paperless-ngx containers are healthy under `docker compose ps`.
The test document is consumed, OCR text is searchable, and the original document remains retrievable.
The export contains `manifest.json` plus document/metadata artifacts and is copied or archived outside the live application volumes.
The Paperless container/image version used to create the export is recorded with the backup.
A disposable matching-version instance can import the export with `document_importer` and recover the test document.
Troubleshooting
If documents remain in `consume`, inspect webserver logs and verify host UID/GID mapping, file permissions, and whether the consumption directory supports the filesystem notification behavior Paperless expects.
Read-only command: verify target and scope
ls -la ./consume docker compose logs webserver --tail=150
If OCR results are poor, check the configured OCR language inside Paperless before installing host-side Tesseract packages. Additional OCR languages are configured through `docker-compose.env` and installed in the container environment.
If an import fails after an application upgrade, verify the restore instance matches the version that created the export before attempting ad hoc database manipulation.
Cleanup or Rollback
Keep the exported recovery artifact before removing the Lab if you intend to retain its documents.
Stop a disposable Lab with `docker compose down`; do not add `-v` unless you have explicitly decided to destroy the Paperless data/media volumes.
Remove test documents and any isolated restore instance only after the recovery evidence has been recorded.
Next Improvements
Use the current PostgreSQL Compose path for a longer-lived installation, as recommended by Paperless-ngx for new deployments.
Schedule `document_exporter` during a quiet period and replicate the export to independent storage with retention.
Repeat a version-matched restore rehearsal after meaningful upgrades or backup-process changes.
