This article documents the process for updating and upgrading the Paperless-NGX stack. This covers everything from simple container image updates to complex major version upgrades of backend services like PostgreSQL.
Part I: Routine Maintenance
Updating Paperless-NGX itself and its stateless dependencies is simple. I installed it to /opt/paperless, so I always execute the following commands under the dedicated unprivileged user.
Stopping, Pulling, and Restarting
The process involves stopping all containers, pulling new images, and bringing the stack back up.
# 1. Stop all containers
~:/opt/paperless/paperless-ngx# sudo -Hu paperless docker compose down
[+] Running 6/6
✔ Container paperless-webserver-1 Removed 6.2s
✔ Container paperless-db-1 Removed 0.3s
... (remaining container removal output)
✔ Network paperless_default Removed 0.2s
# 2. Update/Pull latest images
~:/opt/paperless/paperless-ngx# sudo -Hu paperless docker compose pull
[+] Pulling 15/15
✔ db Pulled 1.0s
... (Detailed output confirming image downloads)
✔ gotenberg 10 layers [⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿] 0B/0B Pulled 48.6s
...
# 3. Starting the stack (The -d detaches the process)
~:/opt/paperless/paperless-ngx# sudo -Hu paperless docker compose up -d
[+] Running 5/5
✔ Container paperless-db-1 Started 0.5s
... (Output confirming all services started)
Part II: Major Version Upgrades
Upgrading major services (e.g., PostgreSQL or Gotenberg) requires changing the container image tag in docker-compose.yml and executing a specific data migration procedure.
Database Upgrade Strategy
For PostgreSQL (e.g., v15 to v16), I identified three primary variants for handling the underlying database file format change:
- Variant 1 (Dumps): Dump the old database, upgrade the image, and import the dump.
- Variant 2 (App Export/Import): Use Paperless-NGX’s built-in exporter/importer. (My preferred clean strategy).
- Variant 3 (pg_upgrade): Use the official PostgreSQL tool. (Complex, but efficient for very massive databases).
Recommendation: Before proceeding with any major version upgrade, check if the new versions are officially supported by Paperless-NGX, and create a full snapshot or backup.
Variant 2: Application Export/Import
This variant is often the cleanest way to upgrade, as the application handles the data transfer logic.
1. Create Backup and Export Documents
# Export documents via the webserver container
~:/opt/paperless/paperless-ngx# sudo -Hu paperless docker compose exec -T webserver document_exporter ../export
100%|██████████| 1004/1004 [00:07<00:00, 126.43it/s]
root@paperless:/opt/paperless/paperless-ngx# du -sh export
986M export
2. Modify Stack Versions
I update the image: tags in docker-compose.yml to the desired new versions:
# Example modifications in docker-compose.yml
image: docker.io/library/postgres:16
image: docker.io/gotenberg/gotenberg:8
3. CRITICAL STEP: Volume Isolation
To ensure the new PostgreSQL container initializes a clean, compatible database, the old volume data must be isolated. This is the manual, atomic volume management step.
# Manually rename the old volumes for a clean start:
cd /var/lib/docker/volumes
mv paperless_media paperless_media_backup
mkdir -p paperless_media/_data
mv paperless_pgdata paperless_pgdata_backup
mkdir -p paperless_pgdata/_data
4. Start and Import Data
The new environment starts up with the fresh PostgreSQL 16 database.
# Start the new environment
~:/opt/paperless/paperless-ngx# sudo -Hu paperless docker compose up -d
... (Success output)
# Import the data into the clean database
~:/opt/paperless/paperless-ngx# sudo -Hu paperless docker compose exec -T webserver document_importer ../export
Checking the manifest
Installed 1278 object(s) from 1 fixture(s)
Copy files into paperless...
100%|██████████| 1004/1004 [00:16<00:00, 62.37it/s]
Updating search index...
100%|██████████| 1004/1004 [00:24<00:00, 41.64it/s]
Part III: Automation and Operational Considerations
Automation Script (Example Cronjob)
For simple minor version updates (where latest tags are used and volumes are untouched), this script provides basic automation.
#!/bin/bash
set -e
# Simple script to stop, pull, and restart the stack
PDIR=/opt/paperless/paperless-ngx
LOG=/opt/paperless/docker-compose-cron.log
# Stop all containers and pull if successful
/usr/bin/docker compose down >> $LOG 2>&1 && /usr/bin/docker compose pull >> $LOG 2>&1
# Start all containers
/usr/bin/docker compose up --wait -d >> $LOG 2>&1
Note: Automating major version upgrades (requiring volume management) must always be performed manually.
Operational Pitfalls
It is crucial to verify the integrity of the stack after any upgrade. Issues like compatibility problems between new versions of supporting services (e.g., Gotenberg) and Paperless-NGX confirm that manual verification after a major upgrade is mandatory.
Sources / See Also
- Paperless-NGX Documentation. Upgrade Guide.
https://docs.paperless-ngx.com/upgrade/ - Docker Documentation. Docker Compose Upgrade and Maintenance.
https://docs.docker.com/compose/compose-file/08-upgrade/ - PostgreSQL Documentation. Major PostgreSQL Version Upgrades.
https://www.postgresql.org/docs/current/upgrading.html - GitHub Repository paperless-ngx/paperless-ngx. Discussions on Gotenberg Compatibility and Database Schema.
https://github.com/paperless-ngx/paperless-ngx/