Deplo

Migrations

Beta

Move an existing Dokploy or Coolify installation onto Deplo, with the data copied across.

Beta

This feature is currently beta/experimental and subject to change. It is not recommended for production. Try it out and share your feedback on our GitHub.

Deplo reads an existing Dokploy or Coolify installation over that panel's own HTTP API and recreates it here: projects, apps, databases, domains, variables and volumes, with the data copied across. It never asks for SSH into the panel, and it never deletes anything on the source. Two routes reach the same wizard.

Two routes

Take over this serverFrom another server
Where Deplo runsThe machine the old panel already runs onA machine of your own
How you start itThe installer finds the panel and asksSettings -> System -> Migrations
Who can run itWhoever installs DeploAn instance admin
Where apps landThis machineA server you pick, per app
Ports 80 and 443Deplo takes them at the endUntouched
The old panel afterwardsRemoved from the machineStill running, still yours

Everything after Connect is the same wizard and the same import engine. The takeover only adds a step at the front, where you choose whether to bring anything across at all, and a step at the end, where Deplo takes the ports.

On both routes the volume bytes are read by an agent on the source machine and relayed through the control plane, because agents cannot dial each other. That is true even when the source and the destination are the same box.

The wizard

Seven steps, and a step opens only when the one before it has finished.

StepWhat it asks for
ChooseTakeover only. Bring your data over, or start clean.
ConnectThe panel's address and a token, one per source team.
InstallOne shell command to run on each source machine.
ReviewWhat comes over, where each item lands, then Start migration.
PeopleInstance admins only. Single-use registration links for the panel's members.
Take overTakeover only. The confirmation that moves ports 80 and 443.
DoneThe report.

Once Start migration is pressed the review goes inert and it is the only step you can reach until the run ends. A takeover that chose Start clean skips the middle entirely: only Take over and Done.

What comes across

These shapes land on both panels and by either route.

ShapeNotes
An app from a Docker imageImage, tag, command, environment, ports.
An app from a compose fileRendered as written, with its named volumes.
An app built from a git repositoryRepository, branch, build settings.
Managed databasesPostgres, MySQL, MariaDB, MongoDB, Redis and ClickHouse, with their data.
Named volumesIncluding deep trees, empty directories and zero-byte files.
Bind mounts of a host directoryCopied to the destination and re-pointed.
Bind mounts of a single fileCarried with its contents, not just re-mounted.
Config filesThe bytes travel, not only the mount path.
A volume shared between services of one stackCopied once, mounted where it was.
Environment variablesPer app and shared, with their values.
Domains and routesIncluding a path prefix and a per-domain port.
Basic authUsers and passwords, re-hashed on arrival.
Cron jobsSchedule and command.
Backup destinations and schedulesThe store's credentials, tested on arrival.
Preview-only variablesAs the app's own preview variables here.

Inside a volume, this is preserved and checked on every release: file contents byte for byte, permissions and ownership, empty directories and zero-byte files, unicode and long paths, hard links that stay hard links, and symbolic links pointing inside their own volume.

What needs a look

Not failures. These are the shapes where a machine cannot decide for you, so Deplo brings across what it can and names the rest in the report.

ShapeWhat happens
A stack that reaches the hostprivileged, network_mode: host, cap_add, device passthrough. Deplo refuses to render it rather than stripping the line, and says which key stopped it.
An image from a private registryThe image reference comes across, the credentials do not. The report names the registry so you can add it.
A compose file kept in a git repositoryDokploy will not resolve it over its API. The app is created and the report tells you to paste the file in.
Device nodes, sockets and named pipes in a volumeNot copied: they are runtime objects, not data. Each one is listed with its path.
Symbolic links pointing outside their volumeNot copied, for the same reason a bind mount of / is not. Listed with its path.
State that lives outside the appA cron entry on the host, a systemd unit, a file no mount points at. Deplo only knows what the app mounts.
Data written outside a declared mountIt is inside the container and it is gone on the next restart, on the old panel as much as here.
A very large volume onto a tight diskDeplo checks the destination's free space first and warns before it starts.

What does not come across

  • Private registry credentials. No panel hands the password over.
  • Git deploy keys and connected-source credentials. Attach a git connection here instead.
  • Device nodes, sockets and named pipes inside a volume.
  • Symbolic links that leave their own volume.
  • Host files such as /etc/localtime and /etc/resolv.conf. They belong to the machine.
  • Networks you created by hand on the source machine.
  • Engines with no twin here: libsql on Dokploy, keydb and dragonfly on Coolify.

Stopping, data, and going back

Read this before you start. It is the part that cannot be undone by pressing a button.

  • Every service you tick is stopped on the old panel when its data copy starts. A volume read while its container is writing to it arrives corrupted, so the copy stops the service first.
  • On a run that finishes, it stays stopped. Deplo starts a service again only when you stop the run during the data step, or cancel a takeover. Neither happens on its own.
  • The source is only ever read. Nothing on the old panel is deleted, except by the takeover's own final confirmation.
  • The destination is emptied before it is written. Each volume and each bind is wiped and rewritten, so a second run does not merge two copies.
  • There is no byte-level rollback. Once the data step has begun, a stop keeps everything already created here. A service whose data did not arrive is marked and refuses to deploy, so it cannot start on empty storage: copy the data again, or press Deploy anyway to accept it.
  • Nothing is deployed for you. You open each app, check it, and press Deploy.

How this is measured

Every release, migrations run against a live Dokploy and a live Coolify installation with real apps and real data. Each app is checked five ways: a record is created through the app's own interface before anything moves, the same requests are compared on both sides, the same count-and-checksum query is run per engine, every volume and bind is compared file list by file list including permissions and owner, and the record from step one is looked for afterwards. The same suite runs behind a closed firewall, behind a CDN with an invalid origin certificate, across a panel spread over several machines with one going unreachable mid-run, onto a nearly full disk, and against a crowded instance with several teams, a private registry and clashing service names.

Measured on 4 September 2026, each panel spread over two machines, the remote route landing on a third.

SourceRouteApps that landed untouchedWhat did not
DokployBoth66 of 67One app on a private git repository: the deploy key never leaves the old panel, and the report names it.
CoolifyBoth60 of 62The same private repository, plus one app the token could not stop.

Next steps

Did this page help you?

On this page