Paperless-ngx Migration
This is the step-by-step guide I used to migrate my Paperless-ngx data, maintaining version v2.12.1, from an old container to a new one, without using Docker.
Entering and exiting containers
pct enter <ct_id>
Step 1: Checking disk space on the old container
Enter the old container and run the following commands.
Before starting the export, I checked the space used by the main folders:
du -sh /opt/paperless/media /opt/paperless/data
And also how much free space was available:
df -h /
Since there was enough space, I proceeded without increasing the disk size.
Step 2: Exporting the data
I entered the project folder and ran the document_exporter
, pointing to a directory as required in version v2.12.1:
mkdir /opt/paperless/src/export
python3 manage.py document_exporter /opt/paperless/src/export
The command generated files directly inside the export/
folder, including manifest.json
and all .pdf
and .webp
files at the same level.
Step 3: Compressing the exported files
To make the transfer easier, I compressed the contents of the folder (not the folder itself):
cd /opt/paperless/src/export
tar -czf /tmp/paperless-export.tar.gz *
Step 4: Transferring the export to the Proxmox host
On the Proxmox host, I copied the .tar.gz
file from the old container to the host:
pct pull <old_ct_id> /tmp/paperless-export.tar.gz /root/paperless-export.tar.gz
Step 5: Creating the new container with updated Paperless
On the Proxmox shell, I used the official script to install a new container:
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/paperless-ngx.sh)"
Step 6: Transferring the export to the new container
Still on the host, I pushed the export file to the new container:
pct push <new_ct_id> /root/paperless-export.tar.gz /tmp/paperless-export.tar.gz
Step 7: Checking or setting the database password
Enter the new container and run the following commands.
In the new container, I checked the auto-generated password from:
cat /opt/paperless/paperless.conf
If needed, I could have changed the password directly in PostgreSQL and updated this same file:
sudo -u postgres psql -c "ALTER USER paperless WITH PASSWORD 'new_password';"
nano /opt/paperless/paperless.conf
Step 8: Resetting the database in the new container
Since the new database already had data (default user created automatically), I dropped and recreated it to ensure a clean import:
sudo -u postgres dropdb paperlessdb
sudo -u postgres createdb paperlessdb
sudo -u postgres psql -c "ALTER USER paperless WITH PASSWORD 'new_password';"
Step 9: Fixing database permissions
Inside psql
:
\c paperlessdb
ALTER SCHEMA public OWNER TO paperless;
GRANT USAGE, CREATE ON SCHEMA public TO paperless;
GRANT ALL PRIVILEGES ON DATABASE paperlessdb TO paperless;
\q
Step 10: Applying migrations
I exported the environment variables before running the migrations:
export PAPERLESS_DBUSER=paperless
export PAPERLESS_DBPASS=new_password
export PAPERLESS_DBNAME=paperlessdb
export PAPERLESS_DBHOST=127.0.0.1
cd /opt/paperless-ngx/src
python3 manage.py migrate
Step 11: Importing the data
I imported the data from the .tar.gz
file:
python3 manage.py document_importer /tmp/paperless-export.tar.gz
Step 12: Indexing documents
To rebuild the search index and OCR:
python3 manage.py document_indexer
Step 14: Starting the services
Since I’m using systemd, I enabled and started the services:
systemctl daemon-reexec
systemctl daemon-reload
systemctl start paperless-webserver
systemctl start paperless-consumer
systemctl start paperless-scheduler
systemctl enable paperless-webserver
systemctl enable paperless-consumer
systemctl enable paperless-scheduler
Result
Paperless-ngx was successfully migrated to a new container with all data intact and a functional structure, maintaining compatibility with version 2.12.1 and ready for future upgrades.