Migrating from cPanel
cPanel is the biggest source of migrations there is, so CoreCP reads its archives directly — the same cpmove archive pkgacct writes, and the full account backup a customer can make from their own cPanel without asking anybody.
Written for: Administrator
cPanel is the biggest source of migrations there is, so CoreCP reads its archives directly — the same cpmove archive pkgacct writes, and the full account backup a customer can make from their own cPanel without asking anybody.
Administrators only. An import creates unix users, loads databases and publishes DNS across a whole machine.
What comes over
| The account | Name, unix password (the hash, so the password keeps working), disk quota, shell, and whether it was suspended |
| Websites | The main domain, the subdomains and the addon domains, each with the PHP version cPanel served it on |
| Files | The whole home directory, left where cPanel put it — see Where the files end up below |
| Databases | Every database with its data, its users and their passwords |
| Mailboxes with their password hashes, forwarders, catch-alls, autoresponders and every message | |
| DNS | The zone, with the records that pointed at the old server moved to this one |
| Certificates | The installed certificate and its key, when the archive carries them |
| DKIM | The key itself, republished under CoreCP's own selector so signatures keep verifying during the switch |
| Cron | The account's crontab |
What does not, and what to do about it
Nothing here is dropped quietly. Every line below appears in the report of the import that found it, by name:
| What to do | |
|---|---|
| PostgreSQL | CoreCP has no PostgreSQL role. Dump and restore it yourself, or keep it where it is. |
| Mailman mailing lists | CoreCP has no mailing-list manager. Move the lists to a hosted service before the cutover. |
| Mail filters | The mail still arrives; it is no longer sorted into folders on the server. Rebuild the rules in the customer's mail client, or wait for server-side filters. |
| Extra FTP logins | CoreCP has no FTPS role yet. The account's own SFTP login works and is what everything should use. |
| Apache configuration in the archive | CoreCP renders its own webserver configuration. A custom directive has to be re-made as a CoreCP setting. |
| Reseller packages | Create the reseller and its hosting packages here first, then import — the accounts land under the right owner. |
| cPanel's own extras | FrontPage, cPanel's own cron helpers, its statistics. Gone with cPanel. |
Where the files end up
cPanel serves the main domain from ~/public_html and CoreCP serves every domain from ~/domains/<domain>/public_html. The files are not moved. A site that names its own directory by full path — and most do, somewhere — would break if they were. CoreCP's path is created as a link to cPanel's, so both work and there is only one copy on disk. The report says so per website.
The one exception is mail: cPanel keeps the maildirs inside the home directory and CoreCP keeps them in ~/imap, so the messages move there. They are not left in the home as well — that would count every message twice against the customer's disk quota.
Route 1 — a backup file
The one to use when you have the archive: somebody sent it, or the old server is already gone.
Panel → Migrations → New migration → Source panel: cPanel / WHM → Upload backup. The file is streamed straight to the target server and kept encrypted there; the panel never stores a copy, because a cPanel archive holds every password hash and DKIM key the old server had.
Then press Dry run first. It writes nothing and prints the whole plan: which websites, on which PHP version, which databases under which names, which mailboxes, and everything that will not come over. Read it. Then Migrate now.
On the command line it is the same operation:
corectl import cpanel /root/cpmove-bob.tar.gz --dry-run
corectl import cpanel /root/cpmove-bob.tar.gz --report /root/bob.jsonRoute 2 — pull it live from the old server
CoreCP dials the old machine itself. Two ways in, and which one you have depends on what the customer can give you.
With root on the source (WHM)
The node runs cPanel's own pkgacct, streams the result straight in and deletes it from the source afterwards.
# What will this server let us do? Writes nothing.
corectl import cpanel-server root@old-host.example --mode pkgacct --check
# One account first.
corectl import cpanel-server root@old-host.example --mode pkgacct --accounts bob
# Then the rest.
corectl import cpanel-server root@old-host.example --mode pkgacct --parallel 2With only the customer's own cPanel login
This is the common case for a customer leaving somebody else's shared host: they have their own account and nothing more. CoreCP logs in over SSH as that account and asks cPanel for the same full backup the customer could make from their own control panel.
corectl import cpanel-server bob@old-host.example --mode user --check
corectl import cpanel-server bob@old-host.example --mode userRoot is needed nowhere. Two things are worth knowing before you start:
- cPanel writes the archive into the customer's own home directory, so their disk quota needs room for a second copy of their account.
--checkmeasures this and refuses rather than filling their disk. CoreCP deletes the archive as soon as it has read it. - The account's backup facility can be switched off by the source's administrator. If it is,
--checksays so and the route to take is the archive: ask them for acpmovefile and use route 1.
If you leave --mode out, CoreCP picks: root@… means pkgacct, any other login means user.
The report
Every import ends in a verification report, and it is not a log — it is a list of resources with OK, WARN or FAIL beside each, checked against the live server after the import ran.
- OK — it is there and it works.
- WARN — it is there and somebody has to do something: a mailbox whose password form could not be carried over, an expired certificate, a database that was renamed.
- FAIL — the archive held it and it is not here. That is the only thing that makes the report red.
Read it before you tell the customer their site has moved. It is also where the "what did not come over" list lives, so it is what you send them.
Databases keep their names, unless they cannot
CoreCP reads a database's owner from its <account>_ prefix, the same convention cPanel uses. So a database called bob_shop imported into the account bob keeps that exact name and the site's configuration file keeps working.
It gets renamed only when it has to: when you import under a different account name, or when the source had a database with no prefix at all. The report says so, and it says the thing that matters — the website's own configuration file still names the old one. For a WordPress site that is DB_NAME in wp-config.php.
Extra names, subdomains and hotlink protection
Three things from your old panel come back differently than you might expect.
Pointers and parked domains become extra names of the website they belong to. No second website appears in your list. If a pointer was set to redirect in your old panel it keeps redirecting; if it was set to show the same site, it does that. And mail to that name keeps arriving in the main domain's mailboxes, exactly as it did there.
Subdomains become websites in their own right under their main domain, with their own certificate and their own PHP version. Your files stay where they were — including inside the main domain's folder, if that is where your old panel put them. Nothing is moved, so links that point at a folder keep working.
Hotlink protection does not come along. The migration report says so in as many words:
[corecp] hotlink configuration is NOT carried over for example.com.CoreCP deliberately does not have that feature: it has not worked reliably since 2020, because browsers no longer send the field it looks at. Your .htaccess travels with your files, so the old rules are still there and you can remove them yourself. Extra names and subdomains says what does work.
Doing it twice is safe
Importing the same archive again changes nothing that is already there: no duplicated mailbox, no duplicated forwarder, no doubled rows. That is on purpose — an interrupted migration is repeated rather than unpicked.
Before the cutover
- Lower the TTL on the source's DNS a day ahead, so the switch is quick.
- Dry run, and read the plan.
- Migrate, and read the report.
- Check the site on the new server before the world sees it — a
hostsentry on your own machine pointing the domain at the new node. - Switch the DNS (or the nameservers).
- Import once more after the switch to pick up whatever changed in between: the same command, and it is safe to repeat.
- Only then tell the old provider they can stop.