New releases
Recipe version compared with the latest known upstream release. A version number, not a reading of what changed.
Paperless-ngx ingests scans and PDFs, runs OCR over them, extracts metadata, and turns a document archive into a searchable full-text database. This recipe uses PostgreSQL and Valkey, keeps originals locally, and exposes the web interface on localhost only.
Paperless-ngx turns a folder of scans and PDFs into a searchable archive. It keeps originals, creates PDF/A renditions and thumbnails, recognizes text, extracts metadata, and automatically suggests tags, document types, and correspondents. It suits personal, family, and small workplace archives and can replace cloud document storage and manual folder searches.
This recipe runs the pinned Paperless-ngx 3.1.2 image with PostgreSQL 18 and Valkey 9. English OCR is enabled by default, and one variable adds more languages. Application data, originals and derived files, import/export, the database, and broker state use separate Docker volumes. Tika and Gotenberg are omitted, so this recipe does not support Office and email ingestion that requires those services.
The full HTTP smoke test has passed on amd64; document export and restore remain untested in practice. Paperless-ngx does not encrypt documents or recognized text at rest; sensitive archives need disk encryption and encrypted off-server backups. OCR, Ghostscript, and image handlers process untrusted files that can exhaust resources or attack parsers. The web port binds to localhost, while PostgreSQL and Valkey are not published at all.
These are stored results of separate checks, not real-time data. An unknown status means the check has not been performed yet.
Recipe version compared with the latest known upstream release. A version number, not a reading of what changed.
Result of a dedicated Docker image scan, not a Compose configuration check.
A new major version is found by comparing version numbers. A compatibility verdict is entered by hand after reading the release notes and the migration steps.
Upstream Compose changes relative to the verified recipe.
Pinned image tags checked for newer versions.
From observation to action
The recipe already pins the latest known release. The steps below show the evidence retained for that version.
3.1.23.1.2Open this release on GitHub ↗ The link is evidence to review, not proof of compatibility.
The version numbers do not cross a major compatibility boundary. No compatibility verdict has been recorded.
No image-tag change is currently planned.
Manual steps after the pull. Release-specific migration steps still come from the release notes and installation guide.
No version change is currently planned. The recipe includes a backup procedure. Restore has not been tested.
An exact Fully verified check for this target was recorded on 2026-09-03.
The status shows how fully the published recipe meets each level's requirements.
A minimal setup for a local network or access through a VPN.
You still need to add: single server, local access, minimum components.
A public deployment with protected access and backups.
You still need to add: domain, https via reverse proxy, off-server backup.
A setup designed for predictable operations and observability.
You still need to add: external monitoring, cpu and memory limits.
Tailored to your server
Answer five questions and download a ready-to-run Paperless-ngx bundle.
Screenshots have not been added yet.
Read the full guide first: it explains external access, backups, and data locations.
cp .env.example .envdocker compose up -ddocker compose psUse Ubuntu 22.04+ or Debian 12+ with Docker Engine and Compose v2.24+. Allocate at least 2 CPUs, 2 GB RAM, and 10 GB disk; 4 GB RAM is recommended. OCR briefly loads the CPU and needs extra room for originals, PDF/A renditions, and thumbnails.
docker --version
docker compose version
mkdir -p ~/services/paperless-ngx
cd ~/services/paperless-ngx
cp .env.example .env
chmod 600 .env
sed -i "s|^PAPERLESS_SECRET_KEY=.*|PAPERLESS_SECRET_KEY=$(python3 -c 'import secrets; print(secrets.token_urlsafe(64))')|" .env
sed -i "s|^PAPERLESS_DB_PASSWORD=.*|PAPERLESS_DB_PASSWORD=$(openssl rand -hex 32)|" .env
Never publish .env. PAPERLESS_SECRET_KEY signs sessions and sensitive data;
PAPERLESS_DB_PASSWORD protects PostgreSQL. Both are required. Store them in a
secret manager and do not change them when restoring an existing archive.
Every .env variable:
PAPERLESS_PORT is the local web port, default 8000;PAPERLESS_URL is the sole public origin with https, no trailing /, and no path; it configures allowed hosts, CORS, and CSRF origins;PAPERLESS_SECRET_KEY is the required random signing key;PAPERLESS_DB_PASSWORD is the required random database password;PAPERLESS_DB_NAME and PAPERLESS_DB_USER name the database and role and should change only before first start;PAPERLESS_TIME_ZONE is an IANA time zone for dates and background tasks;PAPERLESS_OCR_LANGUAGE is what to recognize in a document, default eng; use rus+eng for two;PAPERLESS_OCR_LANGUAGES is which tesseract packs to install at start, so add rus here before naming it above;PAPERLESS_*_VOLUME variables name data, media, export, consume, PostgreSQL, and Valkey volumes;PAPERLESS_BACKUP_DIR selects the final archive directory on the host.paperless-data holds the index, classifier, and auxiliary state;
paperless-media stores originals, archive renditions, and thumbnails;
paperless-export stores exporter output; paperless-consume holds incoming
files; the remaining volumes store the PostgreSQL cluster and Valkey state. The
recipe encrypts none of them.
docker compose config
docker compose pull
docker compose up -d --wait
curl -I --fail http://127.0.0.1:8000/
docker compose exec webserver createsuperuser
The last command asks for username, email, and password interactively. The
password enters neither .env nor shell history and does not remain in the
container environment. Self-registration is disabled. Do not expose the service
before creating the administrator. Inspect it with docker compose ps and
docker compose logs --tail=100 webserver.
Keep 127.0.0.1:${PAPERLESS_PORT}:8000; only an HTTPS reverse proxy on the host
should reach web. PostgreSQL and Valkey have no published ports. Allow only SSH,
HTTP, and HTTPS through the firewall. Before the first login, replace the domain
in PAPERLESS_URL and the proxy example, then configure DNS and TLS.
Without a domain, keep the localhost binding and use
ssh -L 8000:127.0.0.1:8000 user@server; set
PAPERLESS_URL=http://localhost:8000 and recreate webserver for that temporary
access. For permanent LAN access, replace 127.0.0.1 in compose.yaml with a
specific private address such as 192.168.1.10, set
PAPERLESS_URL=http://192.168.1.10:8000, and restrict the port by firewall. Do
not use 0.0.0.0 without network controls.
Set PAPERLESS_URL=https://paperless.example.com with no trailing slash. A path
such as /paperless is invalid in this setting. Replace the domain in
proxy/Caddyfile, proxy/nginx.conf, or proxy/traefik.yaml. Caddy obtains a
certificate, Nginx expects Certbot files, and Traefik uses the letsencrypt
resolver. Then run:
docker compose up -d --force-recreate webserver
The proxy must preserve Host, send X-Forwarded-Proto: https, and forward the
client address. Background processing status uses /ws/status/ WebSockets:
Caddy and Traefik handle upgrades automatically, while Nginx is configured
explicitly. For a containerized proxy, 127.0.0.1 refers to that proxy; use a
reachable host gateway instead.
Wait for tasks to finish and ensure consume is empty, then run:
chmod +x backup.sh restore.sh
./backup.sh
The script runs the official document_exporter and packages its export,
unconsumed files, .env, and Compose into one tar. The export contains documents,
thumbnails, metadata, users, and an exact data snapshot, but does not contain
API tokens; issue new tokens after restore. Changes started during export may
not belong to one consistent snapshot, so do not ingest documents or edit
metadata during the operation. The archive contains documents and secrets:
encrypt it, keep an off-server copy, and test restores.
Import irreversibly replaces all six volumes. It is supported only into a
completely empty installation of the same Paperless-ngx version, with the
same path settings. Verify tag 3.1.2, free space, and the active .env, then:
./restore.sh ./backups/paperless-ngx-YYYYMMDDTHHMMSSZ.tar
docker compose ps
docker compose exec webserver document_sanity_checker
The script first exports the state about to be replaced, removes the volumes,
starts an empty installation, and runs document_importer. The archived
configuration.env remains a reference for manual comparison and does not
replace active .env. This procedure has not passed a practical restore test;
test a copy on another server first. Issue new API tokens after import.
Wait for tasks, back up, and read the release notes and migration instructions.
Replace only the exact paperlessngx/paperless-ngx:3.1.2 tag with a reviewed
version; never use latest. Then run:
docker compose pull
docker compose up -d --wait
docker compose logs --tail=200 webserver
docker compose exec webserver document_sanity_checker
Startup applies migrations automatically. Do not update Paperless, PostgreSQL, and Valkey together; separate changes keep failures and rollback unambiguous.
postgres:18-alpine is pinned independently. Changing major is not a normal
docker compose pull: data directory formats can be incompatible. Follow the
official PostgreSQL pg_upgrade or dump/restore procedure, or use
document_exporter --data-only and importer with a new empty database. Make and
verify a full backup first; do not change paths or remove the old volume before
verifying the new database.
Never run an older image over a database after migrations. Restore the previous
exact tag and the complete pre-update export through restore.sh; this rolls
back database, documents, and index together. For a failed PostgreSQL major
update, restore the old tag and old volume. Never attach an old server to a new
major’s data directory.
docker compose down preserves data. After verifying an external backup, remove
everything irreversibly:
docker compose down
docker volume rm paperless-data paperless-media paperless-export paperless-consume paperless-database paperless-broker
rm -rf ~/services/paperless-ngx
Substitute the actual names when volume variables differ in .env.
Sources: configuration, backup, exporter/importer, and update, release 3.1.2, and PostgreSQL major upgrades.
docker compose ps
docker compose logs --tail=200 webserver database broker
docker inspect --format '{{json .State.Health}}' "$(docker compose ps -q webserver)"
Verify that both required secrets were replaced, PostgreSQL and Valkey are
healthy, disk space is available, and curl http://127.0.0.1:8000/ returns a
redirect. The first start takes longer while migrations, indexing, and OCR
language installation run.
PAPERLESS_URL must exactly match the public origin: https scheme, domain,
optional nonstandard port, no trailing /, and no path. After changing it, run
docker compose up -d --force-recreate webserver. Verify that the proxy keeps
the original Host and sends X-Forwarded-Proto.
Inspect the WebSocket route and broker:
docker compose logs --tail=200 webserver broker
docker compose exec broker valkey-cli ping
The proxy must permit connection upgrades for /ws/status/. A containerized
proxy cannot reach host 127.0.0.1 without a host gateway.
Two variables have to agree. PAPERLESS_OCR_LANGUAGES installs the tesseract
pack at container start, and PAPERLESS_OCR_LANGUAGE selects what to recognize;
naming a language only in the second one silently does nothing. For Russian
alongside English set PAPERLESS_OCR_LANGUAGES=rus and
PAPERLESS_OCR_LANGUAGE=rus+eng, then check the startup logs for the language
data installation. Re-run OCR on existing
documents through the UI only after a backup: it is CPU intensive and may
replace the archived rendition.
docker compose logs --since=30m webserver
docker system df
docker compose exec webserver document_sanity_checker
Check the format, volume permissions, free disk, and RAM. Tika and Gotenberg are not included, so this stack cannot process Office and email files that require them.
On the host, run curl -I http://127.0.0.1:8000/. Then inspect the upstream,
firewall, and proxy network namespace. Inside a container, 127.0.0.1 refers to
that container, not Paperless-ngx on the host.
Fossary is an independent informational catalog and is not affiliated with the developers of the listed applications. We collect information from public sources and verify published recipes, but we do not develop, distribute, or control these applications.
A listing or validation status is not a requirement, endorsement, or personal recommendation to use an application. You decide whether it is suitable and use it at your own risk. We do not warrant an application's security, availability, or fitness for purpose and, to the extent permitted by law, are not liable for resulting loss or damage. Review its license, security settings, data processing, and backup procedures before installation.