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
j

Guide 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 (.sql file) of your Paperless-ngx PostgreSQL database using the pg_dump command executed inside the database container.

  • Location: Saves the dump files to /srv/docker-data/paperless-ngx/db_dumps/ (or the DB_DUMP_DIR you 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_CONTAINER variable to the exact name of your Paperless database container (find it in Portainer).

  • Verify PAPERLESS_DB_USER and PAPERLESS_DB_NAME match your Paperless .env settings (defaults are usually paperless).

  • Adjust DB_DUMP_DIR, LOG_FILE, and KEEP_DAYS if 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 .sql backup 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 .sql dump 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.