Paperless backup script:
#!/bin/bash
# ==============================================================================
# Standalone Paperless-ngx Database Backup Script
#
# Creates a timestamped SQL dump of the Paperless-ngx PostgreSQL database.
# Cleans up old dumps older than a specified number of days.
# Logs actions to a dedicated log file.
# ==============================================================================
# --- Configuration ---
# Exit immediately if a command exits with a non-zero status.
set -e
# --- !!! IMPORTANT: SET THESE VARIABLES !!! ---
# Find this using Portainer or `docker ps`
PAPERLESS_DB_CONTAINER="paperless-db-1"
# Default user from paperless .env (change if you modified it)
PAPERLESS_DB_USER="paperless"
# Default db name from paperless .env (change if you modified it)
PAPERLESS_DB_NAME="paperless"
# Directory to store the database dumps (relative to where script is run is difficult with cron, use absolute path)
DB_DUMP_DIR="/srv/docker-data/paperless-ngx/db_dumps"
# Log file location
LOG_FILE="/var/log/paperless_db_backup.log"
# Number of days to keep old dump files
KEEP_DAYS=7
# --- End Configuration ---
# Generate timestamped filename
DB_DUMP_FILE="${DB_DUMP_DIR}/paperless_db_backup_$(date +%Y%m%d_%H%M%S).sql"
# --- Functions ---
log_message() {
# Use sudo tee for logging as cron might run as root and need explicit permission
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | sudo tee -a ${LOG_FILE}
}
# --- Main Script ---
# Ensure log file exists and has permissions (useful for first run)
sudo touch ${LOG_FILE}
# Set permissions suitable for root cronjob and manual sudo run
sudo chown root:root ${LOG_FILE} # Or adjust if running cron as different user
log_message "================== Starting Paperless DB Dump =================="
# Ensure dump directory exists
log_message "Ensuring dump directory exists: ${DB_DUMP_DIR}"
# Use sudo as cron might run as root
sudo mkdir -p ${DB_DUMP_DIR}
# Set permissions if needed (e.g., owned by root if cron runs as root)
sudo chown root:root ${DB_DUMP_DIR} # Or adjust owner/group as needed
# Create the database dump
log_message "Creating database dump: ${DB_DUMP_FILE}"
# Execute pg_dump inside the container, outputting to the host file via sudo redirection
# Using 'sh -c' allows sudo to handle the redirection correctly
if sudo sh -c "docker exec ${PAPERLESS_DB_CONTAINER} pg_dump -U ${PAPERLESS_DB_USER} -d ${PAPERLESS_DB_NAME} > ${DB_DUMP_FILE}"; then
log_message "Database dump created successfully."
# Clean up old dumps
log_message "Cleaning up dumps older than ${KEEP_DAYS} days in ${DB_DUMP_DIR}..."
# Use sudo with find as well
sudo find ${DB_DUMP_DIR} -name 'paperless_db_backup_*.sql' -mtime +${KEEP_DAYS} -exec rm {} \;
log_message "Cleanup finished."
log_message "================== DB Dump Successful =================="
exit 0
else
log_message "ERROR: Failed to create database dump!"
# Optionally remove the failed (likely empty) dump file
sudo rm -f ${DB_DUMP_FILE}
log_message "================== DB Dump FAILED =================="
exit 1
fi
jGuide for Standalone Paperless-ngx Database Dump Script
This guide explains how to set up and automate the paperless_db_dump.sh script.
1. Understanding the Script
-
Purpose: Creates a timestamped backup (
.sqlfile) of your Paperless-ngx PostgreSQL database using thepg_dumpcommand executed inside the database container. -
Location: Saves the dump files to
/srv/docker-data/paperless-ngx/db_dumps/(or theDB_DUMP_DIRyou specify). -
Cleanup: Automatically deletes dump files older than the specified
KEEP_DAYS(default is 7 days). -
Logging: Records actions and errors to
/var/log/paperless_db_backup.log. -
Independent: Runs separately from your main file backup script.
2. Setup Steps
Step 1: Save the Script
Save the content of paperless_db_dump.sh to a location on your server. A logical place is within the Paperless config directory itself for organization: /srv/docker-data/paperless-ngx/paperless_db_dump.sh
Step 2: Configure the Script
Open the script for editing:
sudo nano /srv/docker-data/paperless-ngx/paperless_db_dump.sh
-
CRITICAL: Verify and set the
PAPERLESS_DB_CONTAINERvariable to the exact name of your Paperless database container (find it in Portainer). -
Verify
PAPERLESS_DB_USERandPAPERLESS_DB_NAMEmatch your Paperless.envsettings (defaults are usuallypaperless). -
Adjust
DB_DUMP_DIR,LOG_FILE, andKEEP_DAYSif desired. Save and exit (Ctrl+X,Y,Enter).
Step 3: Make the Script Executable
sudo chmod +x /srv/docker-data/paperless-ngx/paperless_db_dump.sh
Step 4: Test Manually
Run the script once by hand to ensure it works and creates a dump file:
sudo /srv/docker-data/paperless-ngx/paperless_db_dump.sh
Check the output on the screen and the contents of the log file (cat /var/log/paperless_db_backup.log). Verify that a .sql file appears in /srv/docker-data/paperless-ngx/db_dumps/.
3. Automation with cron
Schedule the script to run regularly. Running it shortly before your main file backup is a good idea.
Step 1: Edit the Crontab
Open the root user’s schedule for editing (using sudo ensures it has permissions to run docker exec and write logs):
sudo crontab -e
Step 2: Add the Cron Job
Add a line to schedule the script. For example, to run it daily at 2:55 AM (5 minutes before the main backup):
# Create Paperless-ngx database dump daily at 2:55 AM
55 2 * * * /srv/docker-data/paperless-ngx/paperless_db_dump.sh
(Make sure the path to the script is correct)
Step 3: Save and Exit
Save the file and exit the editor (Ctrl+X, Y, Enter).
Your Paperless-ngx database dump is now automated. The resulting .sql files stored in /srv/docker-data/paperless-ngx/db_dumps/ will be automatically included in your main server backup when simple_backup_script.sh runs and copies the entire /srv/docker-data/ directory.
4. Restoring the Database
If you need to restore your Paperless-ngx setup (e.g., after a server migration, data corruption, or container issue), using the .sql dump file is the cleanest way to restore your metadata (tags, correspondents, dates, file links).
Prerequisites:
-
The Paperless-ngx database container must be running.
-
You must have access to your
.sqlbackup files (either from the original server at/srv/docker-data/paperless-ngx/db_dumps/or restored from your main backup at/mnt/backup/config_mirror/paperless-ngx/db_dumps/).
Steps:
Step 1: Stop Other Paperless Containers
To prevent conflicts during the restore, stop the Paperless webserver, consumer, etc., leaving only the database container running. You can do this easily via Portainer or using docker compose stop in the Paperless directory:
# Navigate to your paperless config directory
cd /srv/docker-data/paperless-ngx/
# Stop all services EXCEPT the database (e.g., 'db')
sudo docker compose stop webserver consumer scheduler broker # Adjust service names based on your compose file
Step 2: Identify and Prepare the Backup File
-
Locate the
.sqldump file you want to restore from. It’s usually the most recent one unless you need to revert to an older state. -
Note its full path (e.g.,
/srv/docker-data/database_dumps/paperless_db_backup_20251024_180000.sql).
Step 3: Copy the Backup File into the DB Container
Use the docker cp command to copy the .sql file from your host server into a temporary location inside the running database container.
# Syntax: sudo docker cp <host_path_to_sql_file> <container_name>:<path_inside_container>
sudo docker cp /srv/docker-data/database_dumps/paperless_db_backup_20251024_180000.sql paperless-db-1:/tmp/restore.sql
(Replace the host path and container name (paperless-db-1) with your actual values.)
Step 4: Execute Restore Commands Inside the DB Container
Get an interactive shell inside the database container:
sudo docker exec -it paperless-db-1 bash
(Replace paperless-db-1 with your container name.)
Now, inside the container’s shell, run the following psql commands. Replace paperless with the correct database username and database name if you changed them from the defaults:
# Become the postgres user (or the paperless user if needed)
# Often connecting directly as paperless is simpler:
# psql -U paperless -d postgres
# Connect to the maintenance database (postgres) as the paperless user
psql -U paperless -d postgres
# --- Inside the psql shell ---
# Drop the existing paperless database (THIS DELETES CURRENT DATA)
DROP DATABASE paperless;
# Create a new, empty paperless database owned by the paperless user
CREATE DATABASE paperless OWNER paperless;
# Exit the psql shell
\q
# --- Back in the container's bash shell ---
# Now, import the dump file into the newly created database
psql -U paperless -d paperless < /tmp/restore.sql
# Check for any errors during the import.
# Once done, exit the container's shell
exit
Step 5: Start Other Paperless Containers
Now that the database is restored, start the other Paperless services:
# Navigate back to your paperless config directory if needed
cd /srv/docker-data/paperless-ngx/
# Start the rest of the services
sudo docker compose start webserver consumer scheduler broker # Adjust service names
Step 6: Verify
Access your Paperless-ngx web UI. Your documents, tags, correspondents, and settings should be restored to the state they were in when the backup dump was created. You might need to refresh your browser cache (Ctrl+Shift+R).
This process ensures a clean and consistent restoration of your Paperless-ngx metadata.