Move from Dokploy
BetaA wizard that reads an existing Dokploy installation over its API and recreates it in 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.
A wizard that reads an existing Dokploy installation over its API and recreates it here: projects, apps, domains, environment variables, volumes and databases, with the data copied across.
Settings -> System -> Migrations, for instance admins. Each Dokploy
organization lands in a Deplo team of your choosing - one that exists, where
you hold create_projects, or a new one named after it.
Deplo going on the same machine?
If Deplo installs on the machine Dokploy already runs on, the installer does all of this for you: it brings everything across, takes ports 80 and 443, and removes Dokploy when you say so. See Take over your VPS.
Will your apps make it across?
What migrates lists the shapes that come across untouched, the ones that need a look, and how each release is measured against live installations.
How it works
Deplo does not scrape files or ask you for SSH. It talks to the source panel's API for the configuration, and for the data it puts an agent on the source machine.
That agent is installed in a fourth, deliberately minimal server role: a migration source. It is out of every deploy picker and every build picker, never a backup destination, never swept by cleanup, absent from monitoring and from the fleet count, and granted to one team only. It is also the only server Deplo will uninstall itself from when you are done.
Volumes are copied by the agent standing on the disk that holds them, relayed through the control plane, because agents cannot dial each other.
What Deplo touches, and what it leaves alone
Nothing on Dokploy is deleted. Volumes, bind-mounted directories and bind-mounted files all stay exactly where they are. Deplo reads them and copies the bytes across; the originals are still on that machine afterwards, so you can run the migration again or go back to Dokploy if you change your mind.
It does stop what it copies, and leaves it stopped. A volume read while its container is still writing to it arrives corrupted, so the data step stops the service on Dokploy first. That stop is the cutover: Deplo never starts it again on Dokploy. If Dokploy refuses to stop a service that is running, its data is not copied at all and the report says so, rather than copying something that moved under the read.
On this side, only the paths the app itself mounts are written. Each volume and each bind mount is emptied and rewritten with what came across, so a second run does not merge two copies. Nothing else on the destination server is touched. A managed database is started again and checked; every other app waits for you to press Deploy.
The host is not part of the app. What belongs to the machine rather than to what you are moving - the Docker socket, the kernel's own pseudo-filesystems, and the machine's timezone, hostname and resolver files - is left out of the copy on both sides. The destination server already has its own, and rewriting them would change that machine rather than the app.
The only thing Deplo puts on Dokploy's machine is its own agent, and Remove from Deplo takes it off again.
Run a migration
The wizard's steps are Connect, Install, Review, People (for an instance admin) and Done. A step opens only when the one before it has finished.
Connect
Open Settings -> System -> Migrations, the Migrate tab, and enter the
Panel address and the API key of the source installation. Deplo reads
the panel and puts the organization the key covers on the Teams to bring
over list, with the Deplo team it lands in beside it: the team of the
same name when there is one, otherwise a new team named after it. Change it
from the dropdown - any team where you hold create_projects, or New
team. A new team is created when its migration starts, not before.
A private address - the same machine (http://172.17.0.1:3000) or another
box on your network - works too, but only for an instance admin. There
is nothing to switch on: the address itself is what decides.
Mint the key from Dokploy's own dialog
A key created there has no rate limit. One created through Dokploy's API without rate-limit settings is born at 10 requests a day, and an import reads the panel hundreds of times: it stops part-way, and Dokploy answers 401 for it, the same as for a wrong key. Deplo says which it was, and where to raise the limit (Settings, Profile, API/CLI).
One key reads one organization
A Dokploy key is minted for one organization and reads only that one. If your Dokploy has three, mint a key each: paste the next one and press Add, and it joins the Teams to bring over list with its own landing team. Deplo names the organizations the key does not cover, so you can see what is still missing. Two organizations may land in the same team, or each in its own.
Install
Deplo needs its agent on each machine the source runs on, to read the disks. The step prints one line per machine: sign in to that machine as root, paste it, and wait here. It shows Waiting for the agent until the machine calls home, and Connected once it has. Deplo takes the agent back off when the migration is done.
The machine's own address, not the panel's
Deplo's first guess for a machine is the address you gave the panel. Behind
a proxy or a CDN that address is the proxy, so nothing answers on 9443
and the wizard shows Cannot connect with a box to type the machine's
real address into. That address is remembered for the next attempt.
A machine that already answers has a Change address link too: a live agent on the wrong box reads as connected, and every volume of the services on it would then arrive empty.
Review
Deplo shows the tree: every project, environment, app and database it found. Tick what comes over. Per item you can set Expose publicly and a Host port where that applies, and which server it lands on; Place everything on sets the whole tree at once. A row that cannot come over says why in a badge, and the badge's tooltip carries the reason.
Then press Start migration. The run happens on the server: the step shows the progress, the log is one click away under Show log, and you can close the tab. Stop and undo takes the run back out - see below for what that means once the data step has begun.
The chip at the top of every page shows the same progress to the whole team. When the run ends it turns green and says Migration finished, and it stays there until somebody closes the report: a run that ends while you are on another page is not missed.
One migration runs at a time per team. Starting a second one while the first is still going is refused by name, so a double click cannot create the same app twice.
With several organizations on the list, the review shows one section per organization, each headed by the team it lands in, and Migrate N teams runs them one after another on its own: a new team is created as its turn comes, and Deplo leaves its agents on the source machines until the last one is over, so only the first pays for the install. An organization with nothing ticked is skipped.
At the end the report is on the same step, one line per organization. It names everything that did not come across cleanly, and you acknowledge it to move on.
People
For an instance admin: the step offers single-use registration links for the members of the source organization, so you can hand them out. Everyone arrives as a plain member.
Done
Nothing is deployed yet. Open each app, check it over, and press Deploy when you want the traffic. The report of every past run stays under the History tab, with its log.
Stop during the data step
Before the data step, Stop and undo removes everything the run created and takes the agent off the source. Once data has started moving, a stop keeps what came across, marks every service whose data is not here yet so it refuses to deploy on empty storage, starts again what it stopped on the old panel, and leaves the agents where they are so the copy can run again.
After it lands
Two clean-up actions, and they are different:
- Stop and undo, while a run is moving, deletes what the migration created here, if you want to start again.
- Remove from Deplo takes the migration source out of the fleet. Deplo uninstalls its own agent from that machine first, and warns you with Agent still installed if it could not.
The History tab keeps every past run with its report.
An app whose data did not come across refuses to deploy. The report names it, its page says why, and it stays that way on purpose: starting it would run it on empty storage. Bring that data over yourself, or press Deploy anyway on the app to accept starting without it.
What changes on the way across
- A published host port comes across. An app that bound
16379:6379on the source binds it here too, under Settings -> Advanced -> Published ports. It needs the publish-ports permission; without it the app still arrives and the report names the ports it left behind. A port under 1024 cannot be republished - the report says so, and a domain is usually the answer. - The same app name in two environments keeps both.
production/wikiandstaging/wikiare two apps and both stay called wiki. Only the internal name has to differ, so the second one is filed under/<team>/apps/wiki-1- that name is what its container and its volumes take. The report says which one it took. - Throwaway hostnames get re-hosted. A source app served on a
generated
*.sslip.io,*.traefik.meor*.nip.ioname has the old server's IP baked into it, so that name would keep pointing at the old machine. Deplo mints its own equivalent, keeps the same route, and the app's Domains section tells you which address became which. Real domains you own come across as they are, and you repoint DNS when you are ready. On a takeover the generated name points at the same machine, so it stays as it is. - Connection strings are rewritten to the new names. A database keeps
its data but not its hostname - it answers as
db-<name>here - and every variable that named the old one is updated on the way across. Same for an address that had to be re-hosted. The report names every variable it changed. What Deplo cannot reach is what an app stores about itself: a savedtrusted_domainsorsiteurlstill holds the old address, and the report tells you to fix it from the app's Console. - A database lands in the same Environment as its apps. An Environment
owns a Docker network here, so a database placed anywhere else would not
answer to
db-<name>from the apps that name it. It arrives beside them, and its Networking card moves it later if you want it somewhere else. - A network you created yourself does not come across. A stack attached to a network made on the source machine - by hand, or from Dokploy's own Networks page - arrives without it. That network exists only on that machine, and left in place the stack would not start here at all. You rarely lose anything by it: an Environment owns one network and every app in it shares that one, so two stacks that talked over a network of your own keep talking as long as they land in the same Environment. The report names each network it dropped.
- A service name another stack already answers to is renamed. Every
stack in one Environment shares that network, so two one-click apps both
calling their database
dbcannot both have the name. The second one arrives as<app>-dbrather than being refused, and itsdepends_on, its variables and its domain all follow the new name. The report says which names changed. - A bind comes across with what is in it, a single file included. A stack
that keeps files beside its own compose file - a
./contentdirectory, a./nginx.conf- has them copied into the app's files directory in the data step. A bind that names a host path outside the stack works the same way, and one that names a file rather than a directory copies that file alone, never the directory around it. Nothing else in that directory travels. - The machine's own files stay on the machine.
/etc/localtime,/etc/timezone,/etc/hosts,/etc/resolv.confand the like are mounted by half the compose files in the world, and they belong to the host, not to the app. The server you are moving to already has its own, so Deplo never reads or overwrites them, and the report does not mention them. - A file that is not text arrives with the data. A config file comes across as a File under Settings -> Storage, which holds text. A binary one - an SQLite database mounted at a path, say - is copied in the data step instead, byte for byte. The report says which files took that route.
- A
${{project.KEY}}reference becomes a real link. Dokploy resolves those only at deploy time, so a value that is exactly one reference to a project or environment variable of the same name arrives here as a link to that shared variable, not as a second copy. When the names differ a link cannot express it, so the variable arrives with the resolved value and the report says so. Only the apps that referenced a shared variable are linked to it; the others still see it offered under Variables. A${{ <service>.<field> }}reference to a sibling service is a different thing and still arrives as it is written - the report names those keys. - Every variable arrives plain. Dokploy has no notion of a secret
variable, and Deplo never types one secret on its own: a
secret is write-only and can never
be edited or turned back, so guessing from the name would lock away a value
nobody can check against Dokploy.
MYSQL_ROOT_PASSWORDarrives as readable asPORT. Once you have checked a value, mark it Secret under Variables; that direction is always open. - Preview deployments come across with their own variables. The base domain, the port and the limit land under Previews, and a variable Dokploy kept for previews only becomes one of the app's preview variables here.
- Backup destinations and schedules come across. Dokploy hands over its S3 destinations with their credentials, so each one is created and tested on arrival, and a database that was backed up to it keeps its schedule on that destination.
- A volume backup becomes an app backup. A volume backed up from an app or from a stack's service, and a stack's own database dump, arrive as backups of the app on that destination, one per schedule. An app backup here covers every volume of the app, so two volumes on one schedule become one backup, and the report says so.
- A middleware written into an app's own Traefik file is named. Dokploy's forms never produce one, so it is the one route setting the import cannot carry. The report names it with its kind; define it in the proxy's configuration here, then add it to the domain.
- A service on a remote server is read on that server. Its containers, its volumes and whether it is running are asked of the machine Dokploy says it runs on, never of the panel's own host.
- Imported basic-auth credentials are flagged. They never went through Deplo's password policy or the breach check.
- Anything needing a permission you do not hold lands in the report
instead, naming what asked for it and who turns it on. A Compose stack
that reaches the server needs the permission before it can come across
at all; everything else about the app comes over either way. Authored Compose is treated as hostile here exactly as it is
everywhere else: host bind mounts,
privileged, published ports and foreign networks or volumes each need their grant. - A service that was never started comes across empty. It has no data on the source yet, so nothing is copied for it and nothing holds its first deploy here - which is what creates its volumes. A service that IS running and whose volume Deplo cannot find on that machine is the other case, and it does hold the deploy: the report says which machine was asked.
- An app still being created refuses every action and draws as pending until its run finishes.
What the report tells you
Besides what did and did not come across, the report carries a few checks that are cheaper to read now than to find out later.
- A copy that would erase another app is refused. Two apps mounting the
same absolute path on the same server -
/opt/dataon both is enough - is all it takes, because the data copy empties its target before it writes. Deplo names the other app and writes nothing: on the review screen before the run starts, and again in the report. Give one of the two its own directory, then copy the data again. - Free disk on the machine receiving the data, when it is under 10% or under 5 GiB. A copy writes a second copy of everything before the old one goes, so free some room first.
- A project that is empty on Dokploy is named, rather than left out silently and read as one that vanished between the scan and the report.
- An API key belongs to one organization, so one key covers that one only. Add a key per organization on the Connect step and Deplo brings them over one after another; the ones no key covers are named there.
- The registries a stack pulls its images from. Dokploy never exposes the password, so add a private one under Registries before the deploy fails on it.
Limits and gotchas
- Cut DNS over yourself, when you are ready. The migration does not touch your registrar.
- Copying data takes as long as the data is big. Volumes stream host to host through the control plane.
- Running it again is safe. Everything already here is kept, its data is copied across again when you tick it, and a backup schedule the first run could not set because its destination was not here yet is added. Deplo took its agent off the source machine when the first run finished, so Install shows the line to paste once more.
- Check the report, always. A migration that says "done" with twelve lines in the report has twelve things waiting for you.
- Check that the source is gone afterwards. Deplo takes its agent off the machine when the run finishes; if it could not, Agent still installed says so, with the command to run there.
If it does not work
- The scan finds nothing: wrong panel address, or the API key lacks access. Dokploy keys are scoped per organisation.
- The panel's certificate is not trusted: Deplo cannot be told to accept one, so use Dokploy's plain http address instead.
- Dokploy stopped accepting this API key part-way: the key has a rate limit and ran out. Raise or disable it under Settings, Profile, API/CLI, and run the import again - nothing is lost, everything already here is skipped.
- Stuck on Waiting for the agent: the install command has not run on the source, or that machine cannot reach this one.
- A volume arrives empty: the report says so, and the app it belongs to refuses to deploy until you decide what to do about it. A single volume has six hours to copy - past that it fails and the report marks it empty, so a very big volume over a slow link is one to bring over yourself.
- One source machine will not answer: the services on it are named in
the report and blocked from deploying, and the machines that do answer
are still copied. Only when nothing answers at all does the step stop
before touching anything. Copying dials that machine on inbound
9443, which its call home never uses, so a source that went green can still be out of reach. Check it from this machine withnc -vz <source-ip> 9443. - A file the target agent is too old to take: copying a bind that names a single file needs a recent agent on the DESTINATION server. An older one refuses the file by name rather than putting an empty directory in its place - update that server's agent and run the copy again.
- The data step stops half way: nothing is rolled back. Everything already created here stays exactly as it is, and every service whose data did not arrive is named in the report and blocked from deploying. A second run skips everything already created and copies the data again, or bring the missing data over yourself with Copy the data again on the app.
See Servers and agents for more.
See also
Did this page help you?
Take over your VPS
Install Deplo on the machine that already runs Dokploy or Coolify. It brings your projects across, takes the ports, and removes the old panel when you say so.
Move from Coolify
A wizard that reads an existing Coolify installation over its API and recreates it in Deplo, with the data copied across.