This page is about a single server. To pull apps onto a different server, use Migrating from Coolify, Dokploy or CapRover and its cutover section instead.
The path in five stages
1. Install in coexist mode
On a server where Coolify’s Traefik (or another proxy container) holds ports 80 and 443, the installer notices and switches to coexist mode by itself. See Server already runs a proxy for the full list of what changes.8088 and 8443, and the managed routes live in the old proxy’s dynamic configuration (see Run behind an existing proxy). The old platform keeps serving everything.
2. Import and stage
Open Migrate in the dashboard and follow the wizard: connect to the old platform with a read-only token, pick what to import, preflight, stage, move images, build and verify, copy volumes. Every step is described in Migrating from Coolify, Dokploy or CapRover. Nothing on the old platform is written to.3. Verify the staged apps
Enable routing for each app, then check each domain through the old proxy:Two copies of one domain
An app imported from Coolify keeps its Traefik labels on the old container, and those labels register a router for the same hostname Levelrail now routes. Traefik can pick the old router, so a domain looks fine while it still reaches the old container. The proxy page flags this as “the proxy answers, but not through this server’s ingress”. It matters only while the old proxy runs: after the takeover the old proxy is stopped and only Levelrail answers. The preflight lists every domain that is claimed twice so you know which old containers to stop on the old platform after you are happy.4. Take over this server’s ports
Take over ports is the last step of the Migrate wizard and a tab on the Migrate page. It is root only.1
Read the preflight
The checklist shows who holds ports 80 and 443 and what routes it still serves, whether every app is healthy here, whether DNS for each domain points at this server, whether certificates are uploaded or can be issued, whether automatic certificates are on, whether disk and memory have headroom, and whether the control plane can restart itself. Every blocker has a typed fix: a button, a copy command or a link, plus Re-check.
2
Read the plan
The plan lists the exact steps and what rollback restores. Nothing changes until you confirm.
3
Run it
Click Take over ports, type
takeover and confirm. The run records the way back, stops the old proxy container (stopped, never removed), lets this server terminate TLS, stores the new listen addresses, restarts the control plane once and verifies every domain over real HTTPS. The page shows each step live and reconnects by itself after the restart.From the CLI
plan and run --dry-run print the preflight and the steps and change nothing. run --confirm takeover waits through the restart until the run settles. Add --json to any of them for machine output and --accept-unmanaged to accept that domains the old proxy serves, and Levelrail does not manage, go offline.
From the API
All five need the root ability. Repeating
POST .../runs while a run is in flight or done returns that run instead of starting another.
What the run does, exactly
- Records the way back. The previous listen addresses, TLS settings and the names of the containers it will stop are stored in the control plane database. No secrets are stored.
- Stops the old proxy through the Docker Engine API. The container is stopped, not removed. Nothing else on the old platform is touched.
- Switches TLS to this server. The setting that says a proxy in front terminates TLS is turned off, so the ingress serves HTTPS and requests certificates.
- Stores the new listen addresses
:80and:443in the database. The control plane reads them at start and they win overAPP_INGRESS_HTTP_ADDR,APP_INGRESS_HTTPS_ADDRand systemd socket activation. The systemd drop-in is not edited: the control plane never writes host files, so the drop-in values stay as the baseline rollback returns to. - Restarts the control plane once, using the same supervised restart as the dashboard restart button.
- Verifies each domain from the control plane over real HTTPS on its own listener, with the domain as SNI and Host header. A domain passes only with a trusted certificate and the reply that only this ingress can give, so an old proxy that came back and answers instead is caught.
The verification window
If verification has not succeeded for every domain within the window, the run rolls back by itself. The default is 5 minutes. If the control plane restarts again before verification finishes (a crash on bind counts), the next start rolls back instead of trying again.5. Rolling back
Click Roll back on the run, or runlevelrail-cli import takeover rollback. Rollback records the intent, restarts the control plane so the previous listen addresses apply, restores the TLS settings, then starts the old proxy container again once the ports are free (it retries while they are released). It is the same path the automatic rollback takes, and repeating it is harmless.
If the old proxy cannot be started, the run ends as “Needs attention” with the container names and the docker start command to run by hand. Every step of a run and of a rollback is written to the audit log.
What can go wrong
Related
- Run behind an existing proxy for coexist mode and managed routes
- Domains and ingress for certificates and the restart-safe sockets
- Environment variables