I recently started using paperless-ngx and so far, I really like it. I’m running it with Docker, and after importing and tagging around 1,000 documents, I thought it was time to set up backups.
The documentation describes two different approaches, and I’m going with document_exporter, which seems to be the intended way to create backups.
My basic idea is to use ofelia as a cron service that triggers the document_exporter in the paperless container. Then a second service containing only restic is called by ofelia to start the backup. Both the paperless and backup services have the export path mounted. The paperless images aren’t touched or changed in any way, which keeps things simple and separated.
One caveat: The export and backup jobs can’t run directly after each other since we don’t know when the export job will finish. I’m setting the backup job to run 1-2 hours after the export, which should be enough time, but you’ll need to adjust this if your export takes longer. You could handle this with job-local and docker compose exec, but I find that approach a bit messy.
Setup
First, add ofelia to your paperless docker-compose.yml:
|
|
Next, add ofelia labels to the webserver service that runs paperless itself:
|
|
Make sure the export volume ./export:/usr/src/paperless/export is added.
With this configuration, ofelia will trigger the export every night at 01:30:00 (the cron format includes seconds) and write the export data to the local ./export folder.
Now add the restic backup service and update the RESTIC_PASSWORD environment variable:
|
|
The restic backup command will run every night at 02:30:00, one hour after the export. You should adjust this timing based on how long your export takes. My export only takes a few minutes, so there’s enough buffer time even as my database grows.
Now restart all the services with docker compose down && docker compose up -d.
Initialize repository
First, we need to initialize the restic repository manually:
|
|
You should now see the local folder ./backup/paperless-backup.
First manual backup
Let’s manually trigger a paperless export to verify everything works:
|
|
Then, let’s run our first manual backup:
|
|
Now we can validate our first backup:
|
|
Looks good!
When ofelia finally triggers the jobs on schedule, we’ll see log files in the ./ofelia-logs folder:
$ ls ofelia-logs/
total 15
-rw-r--r-- 1 root root 737 Dec 21 14:10 20251221_151000_paperless-export.json
-rw-r--r-- 1 root root 0 Dec 21 14:10 20251221_151000_paperless-export.stderr.log
-rw-r--r-- 1 root root 0 Dec 21 14:10 20251221_151000_paperless-export.stdout.log
-rw-r--r-- 1 root root 684 Dec 21 14:12 20251221_151200_paperless-backup.json
-rw-r--r-- 1 root root 0 Dec 21 14:12 20251221_151200_paperless-backup.stderr.log
-rw-r--r-- 1 root root 279 Dec 21 14:12 20251221_151200_paperless-backup.stdout.log