If you've spent any time in r/dokploy, the migration thread is familiar: "What's the best way to move my Dokploy install from one Hetzner server to another?" The replies always start with "export the panel and import on the new one," and then immediately someone asks: "what about the volumes?"
That second question is the real one. The panel export is easy. The volumes — the data that lives outside the panel's config — are where migrations get dangerous. A successful Dokploy migration is a successful volume migration. The panel is the small part of the work.
This checklist is the order of operations to get a Dokploy migration done without losing data.
What the panel export actually covers
Dokploy's export gives you:
- The list of applications, services, and databases the panel manages.
- Their environment variables (encrypted with the panel's key).
- The deployment configurations (build commands, ports, domains).
- The user accounts and roles.
- Some platform settings (Traefik labels, networks).
What it does not cover:
- The Docker volumes that store database data.
- Application-specific bind mounts.
- Build caches and image layers.
- TLS certificates managed at the Traefik level.
- Any data Dokploy doesn't know about (manually-created containers, side scripts, etc.).
The export covers the configuration. The migration has to also handle the state.
The migration order
Do these in order. Each step assumes the previous one is complete and verified.
1. Inventory everything
On the old server, list:
- All applications managed by Dokploy:
dokploy app list(or via the UI). - All databases:
dokploy db list. - All Docker volumes:
docker volume ls. Note which volumes belong to which app/db. - All bind mounts from
docker inspect <container>for each running container. - Custom Traefik certificates if you use any (most setups use Let's Encrypt and don't need to migrate).
- DNS records pointing at the old server.
Write this inventory to a file in your repo. The migration is a checklist; the checklist is data.
2. Confirm backups exist and restore
Before you touch the migration, confirm:
- Database backups exist for every database (Dokploy can do this; it does not do it automatically).
- The backup is recent (within hours of the planned migration).
- A test restore works. Spin up a side container and restore the latest backup. Verify the app can read it.
If any of these fail, fix them before continuing. A migration without verified backups is a migration with no rollback.
3. Provision the new server
On the new Hetzner box:
- Same OS family as the old one. Don't mix Ubuntu and Debian if you can avoid it; minor differences will bite.
- Install Docker the same way you installed it on the old box.
- Install Dokploy the same way.
- Set the new server's hostname to something distinct.
- Open the firewall ports Dokploy needs (typically 80, 443, 22, and Dokploy's UI port).
- Confirm you can
sshand reach the Dokploy UI on a non-DNS URL (IP + port).
Do not point any production DNS at the new server yet.
4. Import the panel export
Export from the old server via Dokploy's UI. Import to the new server. Verify:
- All applications appear in the new panel.
- Environment variables are present (might need re-entering the panel encryption key).
- Deployment configs look correct.
The new panel now knows about the apps but they haven't been deployed yet.
5. Migrate the volumes
This is the load-bearing step. For each app that has volumes:
For databases
The safest move is to use the database's own backup/restore. Don't rsync a live Postgres data directory; you'll corrupt the destination.
- Take a fresh logical backup on the old server (
pg_dump,mysqldump). - Copy the backup file to the new server.
- Spin up the empty database container on the new server (via the imported Dokploy config).
- Restore the backup into the new container.
- Verify a sample query returns the same row count as the old server.
For app volumes (uploads, caches, etc.)
Use rsync while the old service is still up:
# On the new server:
rsync -avz --delete root@old-server:/var/lib/docker/volumes/<volume>/_data/ /var/lib/docker/volumes/<volume>/_data/
Do this twice — once now, once during the cutover. The first pass moves most of the data; the second pass catches anything that changed during step 6.
6. Deploy the apps on the new server
With volumes in place, trigger a deploy of each app in Dokploy on the new server. The container starts; it sees the migrated volume; it should boot to the same state the old server was in.
Verify each app:
- The home page loads.
- A protected page (requires DB) loads.
- File uploads still work.
- An action that writes to the DB still works.
If any of these fail, do not proceed to DNS cutover. Diagnose first. The new server hasn't taken traffic yet.
7. The cutover
When the new server passes verification:
- Put the old server's apps into a maintenance state (Dokploy can scale to 0, or you can stop the containers).
- Do a final rsync pass for app volumes (catch any updates since the previous sync).
- For databases, take one more backup on the old server and restore on the new one — or use logical replication if you set it up earlier.
- Update DNS: lower the TTL on the relevant A/AAAA records to 60 seconds 24 hours ahead of cutover; flip the records to the new IP.
- Watch DNS propagation. Most resolvers update within a few minutes if TTL was lowered.
- Verify traffic is hitting the new server (check Dokploy logs or the reverse proxy access logs).
- Confirm TLS works (Let's Encrypt will re-issue against the new server's IP; verify it succeeds).
The cutover window is the only time both servers are simultaneously "in service." Keep it short.
8. Post-cutover verification
After cutover:
- Re-run the same verification queries you ran in step 6.
- Check error logs on the new server for the first hour.
- Watch the database for unusual load.
- Confirm scheduled jobs (cron, panel-scheduled) are firing on the new server.
- Wait at least 24 hours before turning off the old server. Keep it as a hot rollback target.
If nothing has gone wrong in 24 hours, you can begin decommissioning the old server.
9. Decommission the old server
When you're confident:
- Take one last backup of all databases from the old server. Keep it offsite for at least 30 days.
- Snapshot the old server's volumes the same way.
- Document anything migration-specific in your runbook.
- Turn off the old server; cancel after the 30-day backup retention window.
Don't skip the 30-day window. Migration issues often surface days or weeks later.
Common failure modes and how to avoid them
Postgres data directory copied while live. Symptom: new server's Postgres won't start, or starts with corruption. Fix: always use pg_dump/pg_restore or proper file system snapshots, never a live rsync of the data directory.
Environment variables missing on new server. Symptom: app starts but can't reach services. Fix: Dokploy's export sometimes loses env vars that were set outside the panel UI; cross-check from your local notes or the old container's docker inspect.
TLS certificate fails after cutover. Symptom: browsers show cert errors after DNS flip. Fix: Let's Encrypt has rate limits; if you bounced certs too many times, you might need to wait. Mitigate by lowering DNS TTL ahead of time so the flip is fast.
Stale DNS resolvers. Symptom: some users see the old server, some see the new. Fix: pre-lower TTL by 24 hours; expect a small window of mixed traffic.
Volume permissions mismatch. Symptom: app starts but can't write to its volume. Fix: check that the UID inside the container matches the UID on the host (docker exec and id vs ls -ln on the host path).
What this list deliberately doesn't cover
A few things people sometimes try to fold in:
- Upgrading Dokploy version during migration. Don't. Migrate first, upgrade second. Two changes at once obscures which one broke things.
- Changing hostnames or domains. Don't. Keep everything identical; change one variable at a time.
- Migrating to a different OS. Possible, but add a step to test for OS-level differences first.
The shorter you keep the change set during cutover, the easier the diagnosis when something does go wrong.
The summary
Dokploy migrations look like "export and import." The real risk is volumes — both the database data and the app files. The migration that succeeds: verified backups first, side-by-side new server with imported config, volumes migrated and verified before any DNS change, fast cutover, 24-hour rollback window, 30-day final backup. Each step protects the next one. Don't compress the order to save time; the time is in the rebuild if you skip a step.
From across the StoicSoft network
Hand-curated reads on the same topic from sister sites in the StoicSoft family.

