Pick your starting point
The six steps
1
Inventory
List what runs on the old server: apps, databases, volumes, domains, cron jobs, and the secrets each app needs. Note which apps write to local disk and which databases take writes all day. That tells you which apps are the easy ones.
2
Install and connect
Install Levelrail on the new server (or beside the old one, see Behind an existing proxy). It needs its own public address, ports 80 and 443 free, and a network route to the old server if you want it to copy databases directly.
3
Plan with a dry run
Read the old platform without changing anything. You get one verdict per item and a reason for each. Fix the blockers it names (a name collision, a missing port) and run it again. The old platform only ever receives read requests.
4
Stage and verify
Create the apps here stopped and not routed, copy images, data and volumes, then start each app and let it pass its own health check. Test it directly, for example with
curl --resolve, while the old server still serves all public traffic.5
Cutover, one domain at a time
Lower DNS TTLs a day ahead. Run the cutover check, freeze writes for apps with databases, do the final data copy, then switch DNS and verify. Do the least important domain first.
6
Retire the old server
Keep it running, but idle, for at least one full traffic cycle (a week for a weekly job). Stop it only after you have checked backups, cron jobs and logs on the new side.
What stays online during the move
The old server is never stopped by Levelrail. Staging, verifying and dry runs all happen next to it. The only moments users can notice are the final data copy and the DNS switch.
A first HTTPS request to a domain that was just pointed here can be slow or show a certificate warning. Certificates are issued on first use after DNS points here (HTTP-01 needs port 80 reachable), and until then the platform’s own certificate answers. Allow a minute, and check the first domain before you switch the rest. See Domains and ingress.
Pre-flight checklist
- Backups. A fresh backup of every database and volume from the old server, stored somewhere that is not that server. Test one restore.
- DNS TTL. Lower the TTL of every domain you will move to 300 seconds (60 if your provider allows) at least one old-TTL ahead of the switch. The cutover check reads it and tells you to wait if it is above 300.
- Access to your DNS provider. Either connect Cloudflare or Route 53 in Levelrail so the switch can write the record and store the old value, or be ready to edit the record by hand.
- Disk. The new node needs room for every image, volume and database copy. The hub preflight checks free disk for databases with a margin.
- Ports. 80 and 443 reachable from the internet on the new server for certificates. If they are taken by another proxy, use coexist mode.
- Versions. Create each target database with the same or a newer major version than the source.
pg_dumprefuses to read a newer server. - Source credentials. A read-only token for the old platform (Coolify needs
read:sensitiveto return real secret values), and a database user that can read everything you want copied. - Secrets. Know which variables came back empty. They are flagged in the plan and you set them by hand.
- A maintenance page or read-only mode for apps that write to a database, so the freeze is deliberate.
Cutover checklist
- Plan shows every item you are moving as ready, or with a note you have read.
- Each app is healthy here (
import apps --verifyor its own readiness check). - Each database has a verified copy with matching row counts, and you have timed it.
- Each volume has matching file counts and sizes on both hosts.
- TTLs are at or below 300 seconds and the old TTL has expired.
levelrail-cli migrate cutoversaysgofor the domain.- Old app paused (writes frozen), final database copy and volume sync done and verified.
- DNS switched, then
levelrail-cli migrate cutover --verifyor the guided cutover passes. - Watch logs and error rate on the new side for a while before the next domain.
Rollback
Until you stop the old server, rollback is cheap.- Before the DNS switch: delete what the import created, or run
levelrail-cli import apps --session ID --rollbackfor a guided import. The source is untouched, so nothing else needs undoing. Volumes created here are kept on disk. - After the DNS switch: point the record back at the old server. With a low TTL that takes minutes. The guided cutover does this for you (
levelrail-cli import cutover rollback), restoring the stored previous value of a record it wrote through Cloudflare or Route 53. Rollback does not restore a Cloudflare proxy (orange cloud) setting, so check it. - Data written here after the switch is not copied back. If users already wrote to the new database, you decide which side is the truth. This is the main reason to keep the freeze window short and to roll back early or not at all.
Migration status
Maturity here uses the labels on Feature status. The migration importer is not yet listed there. By that page’s definition it is beta: it works and is tested, but has no end-to-end suite and almost no record on real infrastructure.
If something fails, the plan says why and what to do by hand. Tell us what broke on GitHub.
FAQ
Does the old server need to stay up?
Does the old server need to stay up?
Yes, through the whole move. It serves traffic while you stage and test, it is the rollback target, and the data copy reads from it. Levelrail never stops or changes it.
Can I migrate one app at a time?
Can I migrate one app at a time?
Yes, and you should. Use
--only NAME to stage a subset, switch one domain at a time, and keep the rest where they are. Apps that share a database should move in the same window.What happens to my environment secrets?
What happens to my environment secrets?
Secret-looking variables go through the encrypted secrets store here, never plain env. The source token is held in memory for the request and never stored, logged or returned. A variable the source hid from your token comes back empty and is skipped, with a note.
What about volumes?
What about volumes?
The control plane does not copy volume contents, because that needs root on the old host. It prints one
rsync command per volume, you run it, and a checklist step compares file counts and bytes on both sides.How long does it take?
How long does it take?
Planning and staging take minutes. Image moves and copies scale with size. The only number that matters for users is the final database copy, which you can measure with a first copy. Plan a day for the DNS TTL to settle, and a week before retiring the old server.
Can I undo it?
Can I undo it?
Before the old server is stopped, yes: see Rollback above. After you stop and delete it, only your backups remain.
Does it run commands on my old server?
Does it run commands on my old server?
No. The only exception is the optional image move, which opens an SSH connection and runs
docker save on images from the plan, nothing else.