Iāve finally been able to migrate the database and patients to the new NAS. It was quite complicated, especially if you arenāt used to Linux and database management. Iāve used ChatGPT a lot during this process, and I can say that it is very good on interpreting linux / ssh commands, outputs, logs, etc. It sure makes errors here an there and forgets things when the conversation gets long but still, very useful. Iāve even asked it to create a forum post on what we had to do to migrate. I am sure there a some missing or wrong info on there but most of it should be quite accurate and maybe useful to some people.
Migrating Orthanc from Synology Package to Docker + PostgreSQL (Full Guide + Lessons Learned)
After struggling with the Synology Orthanc package and the lack of clear PostgreSQL access, I finally managed to migrate my entire Orthanc database (ā1.2 TB, ~480k DICOM instances) from the old Synology NAS to a Docker-based Orthanc with PostgreSQL setup on a new NAS.
The Challenge
My old NAS was running the Synology Orthanc package ā the older beta version that came with its own internal PostgreSQL instance, not visible as a standard package or Docker container.
There was no /usr/local/postgresql directory, no visible PostgreSQL service in DSM, and no clue where the actual database lived.
So the main challenge was:
How do you back up and migrate Orthanc if PostgreSQL isnāt accessible and you canāt use the Orthanc Cloner due to hundreds of thousands of studies?
Step 1 ā Locate the Hidden Database
By exploring the NAS through SSH, I discovered that Orthancās Synology package was still using PostgreSQL, but as a system service, not an app.
Using:
ssh admin@old-nas
sudo su - postgres
psql -l # lists databases; you should see one called orthanc
You need to change the user to postgres (the second command on the code above), then you can see the list of postgres databases. That was the key step ā once we knew the actual DB name, the rest followed.
Step 2 ā Back Up the Old Instance
After stopping the Orthanc Synology package, we made two backups:
1. Orthanc Storage
rsync -avh --progress --delete /volume1/data/OrthancStore/ /volumeUSB1/usbshare/OrthancStoreBackup/
This incremental rsync allows you to refresh backups later without recopying everything.
2. PostgreSQL Dumps
Since we had direct access to psql, we used Docker-like commands (adjusting paths as needed):
pg_dump -U root orthanc > /volumeUSB1/usbshare/orthanc_backup_20251023.dump
pg_dumpall -U root --globals-only > /volumeUSB1/usbshare/orthanc_globals_20251023.sql
The globals dump was required to preserve some roles defined in the database (like ārootā or āorthancā), so it is a good practice to dump it too, if you donāt want to see errorrs when restoring the database.
Step 3 ā Set Up the New Environment
On the new Synology, I installed Docker and created two containers:
Volumes:
/volume1/docker/orthanc/orthanc.json ā /etc/orthanc/orthanc.json
/volume1/data/OrthancStore ā /var/lib/orthanc/db
Both containers run in the same Docker network: postgresql_default. (I think this was created while installing the Postgres container. It is important, as you need orthanc to be on teh same network, otherwise it wonāt use the postgres database)
Step 4 ā Rebuild the Database
We started clean:
docker exec -i PostgreSQL psql -U root -d postgres -c 'DROP DATABASE IF EXISTS "orthanc_DB" WITH (FORCE);'
docker exec -i PostgreSQL psql -U root -d postgres -c 'CREATE DATABASE "orthanc_DB" OWNER root;'
Then copied backups into the container:
docker cp /volumeUSB1/usbshare/orthanc_globals_20251023.sql PostgreSQL:/tmp/
docker cp /volumeUSB1/usbshare/orthanc_backup_20251023.dump PostgreSQL:/tmp/
Step 5 ā Restore Dumps
First the globals (roles, permissions):
docker exec -i PostgreSQL psql -U root -d postgres -v ON_ERROR_STOP=0 -f /tmp/orthanc_globals_20251023.sql
Then the main dump:
docker exec -i PostgreSQL pg_restore -U root -d orthanc_DB /tmp/orthanc_backup_20251023.dump
We ignored warnings like role already exists or schema public already exists ā they were safe.
Step 6 ā Fix and Validate the Configuration
Hereās the working orthanc.json section that finally solved the connection issues:
"PostgreSQL": {
"EnableIndex": true,
"EnableStorage": false,
"Host": "PostgreSQL",
"Port": 5432,
"Database": "orthanc_DB",
"Username": "root",
"Password": "password_for_Postgres",
"IndexConnectionsCount": 8,
"StorageConnectionsCount": 1
},
"StorageDirectory": "/var/lib/orthanc/db"
Once Orthanc started successfully, it automatically detected the existing schema:
W... The database schema already exists, checking if it needs to be updated
W... Current Database revision is 6
Step 7 ā The Key Problems and Fixes
| Problem |
Symptom |
Root Cause |
Fix |
database "orthanc" does not exist |
Orthanc refused connection |
Database not created before restore |
Create manually via psql |
role "postgres" does not exist |
pg_restore errors |
Missing globals |
Restore globals first |
| Orthanc āno connection to serverā |
Database crashes |
PostgreSQL OOM (out of memory) |
Increased memory limit to ā„2 GB |
| Old Orthanc warnings (W004) |
Missing MainDicomTagsSignature |
Legacy database entries |
Reconstruct via REST API |
Step 8 ā Reconstructing Old Studies
Older Orthanc entries created before schema revision 6 caused warnings:
W004: study has been stored with an old Orthanc version and does not have a MainDicomTagsSignature
Fix (batch mode, throttled):
curl -s -u orthanc:orthanc http://localhost:8042/studies \
| tr -d '[]" ' | tr ',' '\n' | while read id; do
curl -s -u orthanc:orthanc -X POST "http://localhost:8042/studies/$id/reconstruct" >/dev/null
sleep 0.2
done
(I havenāt used this command as batch yet. I think there is a plug-in (housekeeper) that automatically does this job, maybe this is a better way to correct the warning, which seems to be harmless by the way).
Step 9 ā Verification
Final stats confirmed everything restored:
CountPatients: 12615
CountStudies: 22248
CountSeries: 26228
CountInstances: 477865
TotalDiskSizeMB: 1204028
RadiAnt and other DICOM viewers can now query and retrieve from the PACS successfully.
Lessons Learned
-
The Synology Orthanc package hides its PostgreSQL backend ā you must find it via running processes or configuration files.
-
Always restore globals first, then the dump.
-
Increase PostgreSQL memory if you have >100k instances ā Synologyās Docker can kill it silently.
-
Orthanc can rebuild missing DICOM tags via /reconstruct without needing a full reload.
-
Once migrated, the Docker setup is far more stable, maintainable, and transparent than the Synology package.