Backing up from a Synology Build and Restoring on A Docker Build

Hi,

I am trying to back up my Orthanc PACS server, running on a Synology NAS to a portable HDD, then will restore it on another Orthanc build, running on Docker, on another Synology NAS system.

The Orthanc version running on the original NAS is the Orthanc beta app, which was part of the beta apps included with the Synology NAS. To my knowledge, the Orthanc app in Synology never got out of the beta status. When the Synology OS got upgraded from version 6 to version 7 (at least 3-4 years ago), the app was not supported anymore (I think due to a database support issue) and also was not going to work on version 7, so I never upgraded my original NAS system’s OS to version 7. The beta app is working without any issues.

As the NAS drive got older, some HDD issues started to show up (the NAS system is 8 years old now), so I had to replace 3 HDDs at different periods, when they gave errors. Thanks to RAID system, I didn’t have an issue with rebuilding the HDDs, so I never lost data. However, I only have 1 drive redundancy, and 4 of the drives in the unit are made at the same period and the same batch, so there is a high risk that more than 1 drive could give errors, and then I won’t be able to repare the database anymore. That’s why I want to create a copy of my Orthanc database.

I’ve bought a newer Synology NAS system and was able to install Orthanc using Docker. Now, what I need to do is to copy my old database and rebuild it on the new one.

I understand that the procedure involves stopping the Orthanc app, copying the app, the database and the patients.

I know where the Orthanc app is installed and I can copy it. I know where the patients are installed and I can copy them too.

My problem is, I don’t know where tha database is, and I am not even sure if it is using Postgres or another database system. On the Orthanc configuration file on the original Nas, there is mention of Postgres, but I don’t see any Postgres software install on the original Synology (I can post the config file’s contents if required). I also don’t know how to restore it on my new Docker build, which is a newer version of Orthanc (I probably shouldn’t overwrite the original Orthanc app’s contents).

Any help would be immensly useful.

Thanks

Hi @Drmaestro

Since you are familiar with Docker and since your ā€œoldā€ Orthanc is still accessible, I would suggest your to use an Orthanc Cloner from the orthanc-tools python module.

version: "3"
services:
    orthanc-cloner:
        image: orthancteam/python-orthanc-tools:0.17.7
        volumes: ["orthanc-cloner:/status"]
        environment:
#            TZ: "Etc/UTC"
#            RUN_ONLY_AT_NIGHT_AND_WEEKEND: "true"
 #           NIGHT_START_HOUR: "15"
  #          NIGHT_END_HOUR: "6"
            SOURCE_URL: "http://orthanc-a:8042"
#            SOURCE_USER: "user"
#            SOURCE_PWD: "pwd"
            DEST_URL: "http://orthanc-b:8042"
#            DEST_USER: "user"
#            DEST_PWD: "pwd"
            MODE: "Default"
            PERSIST_STATE_PATH: "/status/status.txt"
            WORKER_THREADS_COUNT: "6"
#            VERBOSE_ENABLED: "true"
            ERROR_FOLDER_PATH: "/status"
            MAX_RETRIES: "3"
        entrypoint: python -m orthanc_tools.orthanc_cloner
volumes:
    orthanc-cloner: 

Hope this helps,

Alain

Hi Alain,

Thank you very much for the information. I am not a programmer and not very fluent with Python, but from what I understand, this would require both Orthanc versions to be on the same network, or be accessible on the web? If this is true, unfortunately they are not on the same network.

Also, where is orthanc-tools python module located? Is it in the @AppAppAppApp folder of the Orthanc App?

Thanks again

Also, I’ve accessed my Orthanc config file, I’ve redacted the login and password. Can I be sure that Orthanc is using Postgresql in my case? There should be a postgresql database called ā€œorthancā€ somewhere according to this configuration but it isn’t in ā€œ/run/postgresqlā€ folder:

"Name" : "Orthanc",
"StorageDirectory" : "/volume1/orthanc/OrthancStorage",
"HttpPort" : 8042,
"DicomAet" : "ORTHANC",
"DicomPort" : 4242,
"RemoteAccessAllowed" : true,
"SslEnabled" : false,
"AuthenticationEnabled" : true,
"RegisteredUsers" : {
	"my_user_name" : "my_password"
},
"DicomModalities":{
"Radiant":["RADIANT","10.1.40.43",11112],
"Radiant2":["RADIANT2","10.10.14.13",11112]
},
"PostgreSQL" : {
	"EnableIndex" : true,
	"Host" : "/run/postgresql",
	"Database" : "orthanc",
	"Username" : "Orthanc"
},
"Plugins" : [
	"/var/packages/Orthanc/target/usr/share/orthanc/plugins/libOrthancPostgreSQLIndex.so"
]

}

Also here’s a dump of the most recont log file. I assume it is using Postgresql according to this, but I still have no cloe where the database is located:

W1021 09:13:24.859840 main.cpp:1269] Orthanc version: 1.3.0
W1021 09:13:24.863846 OrthancInitialization.cpp:126] Reading the configuration from: ā€œ/volume1/@appstore/Orthanc/config//merge_server_config.jsonā€
W1021 09:13:24.877770 FromDcmtkBridge.cpp:192] Loading the embedded dictionaries
W1021 09:13:25.144839 OrthancInitialization.cpp:499] Registering JPEG Lossless codecs
W1021 09:13:25.144912 OrthancInitialization.cpp:504] Registering JPEG codecs
W1021 09:13:25.219261 main.cpp:644] Loading plugin(s) from: /var/packages/Orthanc/target/usr/share/orthanc/plugins/libOrthancPostgreSQLIndex.so
W1021 09:13:25.392314 PluginsManager.cpp:269] Registering plugin ā€˜postgresql-index’ (version 2.0)
W1021 09:13:25.392677 PluginsManager.cpp:168] Using PostgreSQL index
W1021 09:13:27.022115 main.cpp:1069] Using a custom database from plugins
W1021 09:13:27.022176 OrthancInitialization.cpp:1088] Storage directory: ā€œ/volume1/orthanc/OrthancStorageā€
W1021 09:13:27.022500 HttpClient.cpp:686] HTTPS will use the CA certificates from this file: /volume1/@appstore/Orthanc/config
W1021 09:13:50.082883 LuaContext.cpp:103] Lua says: Lua toolbox installed
W1021 09:13:50.083021 ServerContext.cpp:182] Disk compression is disabled
W1021 09:13:50.083056 ServerIndex.cpp:1403] No limit on the number of stored patients
W1021 09:13:50.083250 ServerIndex.cpp:1420] No limit on the size of the storage area
W1021 09:13:50.084498 main.cpp:834] DICOM server listening with AET ORTHANC on port: 4242
W1021 09:13:50.084661 MongooseServer.cpp:1029] HTTP compression is enabled
W1021 09:13:50.084962 ServerScheduler.cpp:135] The server scheduler has started
W1021 09:13:50.087705 main.cpp:769] HTTP server listening on port: 8042
W1021 09:13:50.087776 main.cpp:656] Orthanc has started
W1021 11:10:45.718821 OrthancMoveRequestHandler.cpp:179] Move-SCU request received for AET ā€œRADIANT2ā€

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.

:counterclockwise_arrows_button: 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.

:puzzle_piece: 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?


:compass: 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.


:floppy_disk: 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.

:gear: Step 3 — Set Up the New Environment

On the new Synology, I installed Docker and created two containers:

  • PostgreSQL (container name PostgreSQL)

  • Orthanc (orthancteam/orthanc:latest-full)

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)


:brick: 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/


:recycling_symbol: 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.


:puzzle_piece: 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


:brain: 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

:abacus: 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).


:white_check_mark: 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.


:light_bulb: Lessons Learned

  1. The Synology Orthanc package hides its PostgreSQL backend — you must find it via running processes or configuration files.

  2. Always restore globals first, then the dump.

  3. Increase PostgreSQL memory if you have >100k instances — Synology’s Docker can kill it silently.

  4. Orthanc can rebuild missing DICOM tags via /reconstruct without needing a full reload.

  5. Once migrated, the Docker setup is far more stable, maintainable, and transparent than the Synology package.

2 Likes