Move from Coolify
BetaRead a Coolify installation over its API and recreate it in Deplo, data included.
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 reads your Coolify installation over its API and recreates it here: projects, applications, one-click services, databases, domains, variables, volumes and backup destinations, with the data copied across. The configuration comes from the API. The data is read by a Deplo agent installed on each Coolify server.
Pick the tab that matches where Deplo will run: on the machine Coolify already runs on, or on a machine of your own.
Before you start
Turn the API on and create a token
If Coolify's API is off, the scan says API is disabled. Turn it on under Coolify's Settings. If the API is limited to a list of addresses, add the machine Deplo runs on, or the scan says You are not allowed to access the API.
Then go to Keys & Tokens, API tokens. Tick root and create the token from an
account that is an admin or owner of the team. Root covers both things a migration needs:
reading your values and stopping a service before its data is copied.
If you do not want to grant root, tick deploy first, then read and
read:sensitive, in that order (Coolify clears the list when deploy is ticked). Without
read:sensitive every variable, database password and one-click compose file would arrive
empty. Deplo checks this at Connect and refuses to import blanks.
One run per source team
A Coolify token only sees the team it was created in. For each extra team, switch team in Coolify, create a token, paste it here and press Add. It joins the Teams to bring over list with the Deplo team it lands in. Two Coolify teams may land in the same Deplo team, or each in its own.
Each team is one run. The runs are queued on the server and done one after another, so you can close the page and come back later.
On every source machine
A Coolify instance often has more than one server. The Install step lists every one.
- One shell command, as root, on each machine. It installs the Deplo agent that reads the disks. It works behind any firewall.
- Inbound TCP 9443 on each machine. Deplo connects back to read the volumes.
- A snapshot of every machine, taken first. It is the only way back.
- Free space on the destination disk. Deplo warns under 10% free or under 5 GiB.
What the run stops
Every service you tick is stopped on Coolify when its data copy starts. After a finished run it is not started again. Anything you leave unticked is not touched.
Run the migration
Snapshot the server. The final step removes Coolify. The snapshot is your only way back after that.
Run the installer. The same command as any other install:
curl -fsSL https://deplo.build/install.sh | bashIt finds Coolify and asks whether Deplo may replace it. Answer no and nothing is installed.
--yes does not answer this question. To skip it, set DEPLO_TAKEOVER=coolify.
Open the address it prints. Until the ports move, Deplo answers over plain http on port 80.
After the takeover the same address answers over https. If the installer says Coolify has no
dynamic config directory, use a tunnel instead: ssh -L 3001:localhost:3001 [email protected].
Create your account, then choose. The first step of the wizard asks the one question that cannot be undone: Bring your data over, or Start clean. Start clean deletes Coolify and everything it runs, and goes straight to Take over.
Connect, Install, Review. The panel is already filled in. Paste a token per Coolify team, run the printed command on any other machine behind the panel, tick what comes over, and press Start migration. Everything lands on this machine.
Take over the machine. This step opens once every team on the list has landed. Tick I have
no other teams on this panel, tick again for any service whose data copy failed, and type
coolify to confirm.
Deplo then stops Coolify and its apps, copies its certificates, moves Traefik onto ports 80 and 443, removes Coolify's containers, networks, images and directory, and restarts Docker. Volumes and Coolify's own backups stay on the disk.
The page moves to the https address by itself once the certificate is issued.
Deploy your apps. Nothing is deployed for you. Open each app, check it, and press Deploy.
What comes across
What lands as what
| On Coolify | Here |
|---|---|
Application, nixpacks / static / dockerfile | App built from its git repository |
Application, dockerimage | App running that image |
Application, dockercompose | Compose stack |
| Service (one-click) | Compose stack, from the compose its author wrote |
| PostgreSQL, MySQL, MariaDB, MongoDB, Redis, ClickHouse | The same database engine |
| KeyDB, Dragonfly | Nothing. Named in the report |
| Persistent storage | Volume, with its data |
| File storage | Config file under Storage |
| Environment variables | The app's variables, magic SERVICE_* values already resolved |
| Preview-only variables | The app's preview variables |
| Shared variables (team, project, environment, server) | Shared variables at the same level, linked to the apps that referenced them |
| Domains, with their port and path | Domains |
| HTTP basic auth | Access |
| Memory and CPU limits | Resources |
| Health check | Advanced -> Health check |
| Published host ports | Advanced -> Published ports, with the publish-ports permission |
| Scheduled tasks | Cron jobs |
| S3 storages | Backup destinations, tested on arrival |
| Scheduled database backups to an S3 storage | Backup schedules, on the destination that came with them |
What changes on the way
- Temporary hostnames get a new address. A name on
sslip.io,traefik.me,deplo.siteorlocalhostcontains the old server's IP, so Deplo generates a newdeplo.siteaddress. The app's Domains section shows which became which. Domains you own come across as they are. - Connection strings are rewritten. A database answers as
db-<name>here, and every variable that used the old hostname is updated. Values an app stores by itself (a savedtrusted_domainsorsiteurl) are not changed. Fix them from the app's Console. - A volume keeps the name you gave it. Coolify stores it as
<resource id>-<name>. It arrives as plain<name>. - A volume pinned by name in the compose file is not the one that was running. Coolify renames
every volume to
<resource id>_<key>and ignoresexternal: trueandname:. Deplo copies what was actually running. The report names the pinned volume so you can decide what to do with it. - The compose is the one its author wrote, not the copy Coolify renders with its own labels and networks. Deplo adds those itself.
- A middleware label in a compose file comes across when its kind is supported. Router labels never do. See Middlewares in a compose file.
- Security headers stay off on a moved app's domains. The app answered without them before, so nothing that embeds it breaks. Turn them on under Security.
- A published host port comes across and 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 published again; use a domain instead.
- A network you created yourself does not come across. Apps in the same Environment share one network, so put stacks that talk to each other in the same Environment.
- A service name already used by another stack is renamed. The second
dbin one Environment arrives as<app>-db, and itsdepends_on, variables and domain follow. - A bind mount comes across with its contents, single files included. A config file Coolify keeps at a real path on the host lands in Deplo's own files directory. A bind that names a file copies that file alone.
- A
{{team.KEY}}reference becomes a real link. A value that is exactly one reference to a shared variable of the same name arrives linked to it. When the names differ, the resolved value arrives instead and the report says so. - A server-level shared variable is offered to the project. Deplo has no server scope.
- A variable is a secret here only if Coolify marked it one. Deplo never guesses from the name, because a secret is write-only and cannot be read back. Variables Coolify marks shown once arrive plain and empty, because its API returns no value for them. The report names the keys. Fill them in under Variables before you deploy.
- An address stored without a scheme arrives on plain http. The report names it. Add a certificate under Domains when you want https.
- A template address recorded without a port still routes. Deplo reads the port from the service, and the report says which one it took.
- A
$Coolify would have expanded is named. The value arrives as it was written. - Imported basic-auth credentials are flagged. They never went through Deplo's password policy or the breach check.
- Anything that needs a permission you do not hold goes in the report, with who can turn it on.
What is left behind
- KeyDB and Dragonfly. There is no engine for either here. Both are named in the report.
- Coolify's own
COOLIFY_*variables. They name the panel you are leaving. - Deploy keys and connected-source credentials. Attach a git connection for a private repository. This also turns on auto-deploy.
- Private registry passwords. Coolify never exposes them. Add the registry under Registries before you deploy.
- A volume's own backup to an S3 storage. Coolify's API never lists those schedules. Set it again under Backups: one app backup here covers every volume of the app.
- A database backup saved only to the local disk. There is no destination for it here. The report names it.
- The machine's own files.
/etc/localtime,/etc/resolv.confand similar belong to the host. The destination already has its own.
Backing out
- While the run is going, in any step. Stop and undo removes everything the run created here with its data, starts again what it stopped on Coolify, and removes the agent from the source. Coolify keeps all of its data.
- A run that fails on its own during the data step. Nothing is rolled back. A service whose data did not arrive refuses to deploy. The agents stay, so the copy can run again.
- A takeover, before the ports move. Cancel and remove Deplo starts every service the migration stopped, starts Coolify's own containers again, removes everything Deplo created here, and uninstalls Deplo. It asks for the token again.
- A takeover, after the ports move. The snapshot is the only way back. If the port move itself fails, Deplo puts the ports back, starts Coolify again and offers Try again with the reason.
Running the migration again is safe. What is already here is kept, and its data is copied again when you tick it.
Troubleshooting
| Symptom | What to check |
|---|---|
| API is disabled | Turn the API on in Coolify's settings. |
| You are not allowed to access the API | Coolify's IP allowlist does not include this machine. |
| This token cannot read values, or cannot read compose files | The token is not root and has no read:sensitive, or its account is not an admin or owner of the team. |
| This token cannot stop a service | The token is not root and has no deploy. Create a new one with root ticked. |
| Coolify refused the token | The token expired or was revoked. |
| Rate limited | Coolify allows 200 requests a minute. Wait and try again. |
| The panel's certificate is not trusted | Deplo cannot accept an untrusted certificate. Use Coolify's plain http address. |
| A 502, or a Cloudflare 521 | It comes from the proxy or CDN in front of the panel. Start it, or point Deplo at the panel's own address. |
| Stuck on Waiting for the agent | The install command has not run on that machine, or the machine cannot reach this one. |
| The server agent did not install during a takeover | Re-run /opt/deplo/install.sh on the machine, or use the command under Settings -> Servers. |
| One source machine does not answer | Its services are named in the report and blocked from deploying. The other machines are still copied. Check inbound 9443 with nc -vz <source-ip> 9443. |
| A volume arrives empty | The app refuses to deploy until you decide. One volume has six hours to copy, so a very big volume over a slow link is better copied by hand. |
| A shared-variable level is missing from the report | An older panel has no endpoint for it. Copy those in by hand. |
| A single-file bind is refused by name | The destination server's agent is too old. Update that agent and copy the data again. |
| The data step fails half way | Nothing is rolled back. Only Stop and undo does that. A second run skips what is already here and copies the data again, or use Copy the data again on the app. |
| Two apps mount the same absolute path | The copy empties its target before writing, so Deplo refuses and names the other app. Give one of them its own directory. |
| The port move failed | Deplo put the ports back and started Coolify again. The step names what is holding the port, next to Try again. |
More in Servers and agents.
Next steps
Did this page help you?