External Migrations: from cPanel or DirectAdmin into this server ​
The External migrations page moves hosting accounts from a remote cPanel or DirectAdmin server into this AdminBolt server, and you drive the whole run from the panel. You connect the source once, review the accounts it reports, choose which of them to bring over, and approve the DNS cutover when the run asks for it.
The work itself runs on the source server, not in your browser. Once a run starts it survives a closed tab, a dropped SSH session, and a restart of its own process, so a migration that takes hours does not depend on your workstation staying awake.
Migrating into AdminBolt, not between AdminBolt servers
This page brings a cPanel or DirectAdmin server's accounts into AdminBolt, with their files, databases, and mailboxes. Moving an account from one AdminBolt node to another under a hub is a different feature with a narrower scope, documented in Fleet Accounts. The same source server can also be attached to a hub as a read-only external DNS source, which moves no hosting at all. All of these are compared in Migration: which one do you need?.
This page covers the prerequisites, running a migration step by step, the DNS cutover, recovery after an interruption, and troubleshooting.
Overview ​
URL: /admin/migration/external-migrations - under Migration → External migrations
Migrate accounts from a remote cPanel or DirectAdmin server into this AdminBolt server.
The screen lists your migration runs and starts new ones. Each run has its own page at /admin/migration/external-migrations/<run id>, which is where discovery results, account selection, progress, decisions, and the final report live.
Note: If your sidebar has no Migration row, open the URL above directly. Notification links about a run also take you straight to its run page.
Two ways to migrate from cPanel or DirectAdmin ​
AdminBolt has two paths from the same kind of source server, and they suit different jobs:
| External migrations (this page) | bolt-migrate on the source | |
|---|---|---|
| You drive it from | This panel | A terminal on the source server |
| Scope | The accounts you select | The whole server, every account at once |
| Converts the source in place | No, the source keeps running | Yes, that is one of its two paths |
| Survives a closed browser | Yes | The run is tied to your terminal session unless you detach it |
| Needs a shell on the source | Once, to paste a bootstrap command, or not at all if the panel connects over SSH for you | Yes, throughout |
Pick this page when you want a subset of accounts, or when you want the panel to keep the state for you. Pick bolt-migrate when you are converting a server in place or moving everything in one pass.
Before your first external migration ​
- Outbound HTTPS from this server to
get.adminbolt.com. The panel pins one exact release of the migration runner and fetches it the first time you create a run, then verifies its checksum and keeps the verified copy. If the download fails or does not match the pin, the wizard refuses to create the run rather than start an unverified program as root on a customer's server. - Network from the source to this server. The source needs outbound HTTPS to this panel's port (
8443by default), which is also where it downloads the runner from, and outbound SSH for the data path. On the source itself you need nothing beyondcurlandsha256sum. - SSH from this server to the source, but only if you choose the upload bootstrap mode. The one-time command mode needs no inbound access to the source at all.
- A second factor on your administrator account. The DNS cutover decision requires it, and the requirement cannot be bypassed. Enable it before you need it, not while a run waits.
- Free space on this server for the incoming accounts. Preflight reports the sizes it finds on the source, not what this server has left, so check the target side yourself.
- A working backup of the source server. You confirm you have one before a run starts.
Running an external migration ​
1. Connect the source server ​
Open the External tab and enter the source host and SSH port. Add notes if you want the run labelled for a colleague.
2. Approve the host fingerprint ​
The panel reads the source's SSH host key and shows its fingerprint. Compare it with the source before you approve, by running this on the source server:
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pubApproving pins that key for the whole run. A key that changes mid-run stops the run instead of trusting the new one.
3. Choose how to start the runner ​
| Bootstrap method | What happens | When to use it |
|---|---|---|
| One-time command | You paste a command as root on the source. It downloads the runner from this panel over the panel's pinned certificate, verifies the checksum carried in the command, and starts it. Nothing connects inbound to the source. | The source is behind a firewall or a bastion, or you would rather not hand over an SSH key. |
| Upload over SSH | This server connects to the source once, with the private key path or root password you supply, performs the same steps through that session, and drops the connection. | You already have SSH access and want fewer manual steps. |
Either way the SSH connection is never a control channel. It reads the host key and, in the upload mode, starts the runner. Everything after that flows over HTTPS from the source to this panel.
4. Review discovery ​
The runner enumerates the source and reports the account list with sizes, the capabilities it detected, and preflight results. This step is read-only: nothing on either server has changed yet.
5. Select accounts and start ​
This is where you choose the scope of the run:
| Control | What it does |
|---|---|
| Accounts to migrate | The accounts discovery found. Select one, several, or all of them. A run with nothing selected is refused. |
| Source plan mapping | Maps each hosting plan found on the source onto a plan on this server, so migrated accounts land on the limits and features you intend. |
| Skip file transfer | Provisions the accounts without copying website files and mail content. |
| Skip database transfer | Provisions the accounts and their database users without copying database contents. |
| I have a working backup of the source server | A required acknowledgement. The run does not start without it. |
A failing preflight blocks the start. Fix what it names, then start the run.
6. Watch the run ​
The run page shows overall progress, per-account resource states, and the event log, and it updates while you watch. Closing the browser does not affect the run; reopen the page to pick it back up.
You can Pause, Resume, or Cancel a run. Both pause and cancel take effect at the next safe point, between accounts and between resources, so the page shows cancelling until the runner confirms it has actually stopped. It never reports a stopped run while work is still in flight.
7. Answer the decisions the run asks for ​
The run stops and waits at each gate:
- Export finished, import into this panel? confirms that the exported packages should be provisioned here.
- Repoint DNS for the migrated domains to this server? is the cutover decision, covered below. It is always present and always requires an explicit answer.
8. Read the report ​
When the run finishes, the page shows the final report and the cleanup status of the runner, the target, and the panel. A cleanup that did not complete appears as a visible warning with a retry action, not as a silent condition.
DNS and the cutover ​
A migration never changes DNS without your approval, and even then it changes only what lives on a server it controls.
| What | Who changes it |
|---|---|
Zones on this AdminBolt server: A, AAAA, SPF, and DKIM records | The migration, after you approve the cutover |
| Zones on the source server, when the source is authoritative | The migration, if you approve that option |
| Registrar nameserver delegation | You, by hand |
| DNS hosted with an external provider such as Cloudflare, registrar DNS, or a third party | You, by hand. The report lists the exact records |
Accounts that failed verification are left out of the DNS change, so a broken account never takes traffic.
Warning: The source keeps serving until DNS propagates, and this version has no delta sync. Treat the source as frozen from the moment the transfer starts: content changed there afterwards is not migrated. Lower your zone TTLs before the migration if you want a fast switch, because propagation takes as long as the old TTL.
If something is interrupted ​
| Situation | What happens | What you do |
|---|---|---|
| You close the browser | Nothing. The run continues | Reopen the run page |
| The bootstrap SSH session drops | Nothing. It only started the runner | Nothing |
| The runner process dies | It is restarted and resumes from its checkpoints, without repeating completed imports, file syncs, or database copies | Watch the run return to running |
| The source server reboots | The run stops reporting and shows stalled | Run the bootstrap again with the same run id. The working directory and checkpoints are reused |
| No heartbeat for three minutes | The status flips to stalled and a notification is sent. The runner may still be working behind a broken uplink | Check the source: systemctl status bolt-migrate-<run id> |
| One account fails | It is isolated. The other accounts continue, and the failed one is excluded from the DNS cutover | Fix the cause, then retry that account |
| The panel API times out during an import | The runner retries with the same idempotency key and receives the recorded result, rather than provisioning the account twice | Nothing |
Credentials and cleanup ​
Every credential a run uses is scoped to that run and short-lived. No permanent API key and no agent token is ever placed on the source server.
| Credential | Where it lives | When it goes away |
|---|---|---|
| Enrollment token, valid for minutes and single use | The bootstrap command or a file on the source | Consumed on first use, and the file is deleted |
| Run credential, scoped to the run and its endpoints, 12 hour lifetime | Runner memory and the run working directory, mode 0600 | Revoked on success, failure, cancellation, watchdog expiry, or when the feature is disabled |
| Transfer key, an SSH key locked to the source address and a forced command, 4 hour lifetime | The runner working directory, with its public half in this server's authorized_keys | Removed when the run reaches a terminal state, retried by the watchdog, and expired by the agent's own sweep |
| Per-run database account, granted only on the approved schemas | This server's database, with credentials in a 0600 option file | Dropped together with the transfer key |
What the transfer key can reach is bounded by this server rather than by good behaviour on the source: file transfer is confined to the staging root and cannot carry ownership, setuid bits, device nodes, or live symlinks across, and the database connection is granted only on the schemas you approved.
To confirm by hand on this server that a finished run left nothing behind:
grep bolt-migration-run /root/.ssh/authorized_keys # expect no output
ls /var/lib/bolt-agent/migration-targets # expect an empty directoryTurning the feature off ​
To stop every active run and revoke its credentials:
bolt-cli external-migration-disableTo act on one run only:
bolt-cli external-migration-disable --run=<run id>Add --force to skip the confirmation prompt.
This revokes every active run credential, removes the transfer credentials through the agent, deletes the run-private SSH material, and marks the runs cancelled. Hosting accounts that were already imported are untouched and keep working as ordinary accounts on this server. To start again afterwards, create a new run.
Troubleshooting ​
| Symptom | Cause and fix |
|---|---|
| Runner is not available | This server could not fetch the pinned runner release from get.adminbolt.com, or the download did not match the pinned checksum. The message names which one. Never bypass a checksum mismatch |
| Could not read the host key | The source did not answer on SSH. Check the host, the port, and the firewall |
Bootstrap fails on curl | The source cannot reach this panel's port, or the panel certificate changed after the command was generated, so the pin no longer matches. Generate a new run |
Bootstrap fails on sha256sum | What the source received is not what this panel serves. Do not bypass it. Check for a proxy between the source and this panel |
The run stays in bootstrapping | The runner never enrolled. Check systemctl status bolt-migrate-<run id> on the source, and its outbound HTTPS to this panel |
E_CRED_REVOKED in the runner log | The run ended, was cancelled, or the watchdog expired its credential. Start a new run |
E_RUN_SCOPE on import | The account is not in the approved selection, or the run is no longer active |
E_IDEMPOTENCY_CONFLICT | The same import key was reused with a different payload, which means the source data changed mid-run. Restart the run for that account |
| Transfer fails although imports succeeded | The transfer credential is missing or expired. Check grep bolt-migration-run /root/.ssh/authorized_keys and the agent log, then restart the run for the transfer phase |
Status stalled while the source is clearly working | The uplink from the source to this panel is broken, and the migration continues regardless. Restore outbound HTTPS and the run resumes reporting |
Related ​
- Migration: which one do you need? - how this differs from the other features called migration.
- Migrating to AdminBolt - the
bolt-migratetool run from the source server, for whole-server moves and in-place conversions. - Hosting Accounts - where migrated accounts appear once they are provisioned.
- Fleet Accounts - account migration between AdminBolt nodes.