Skip to content

Importing cPanel accounts

CorePanel can take over hosting accounts from an existing cPanel/WHM server and recreate them natively — files, mail, databases, DNS, cron and SSL — while preserving the original passwords wherever the hash scheme allows, so most users never have to reset anything.

There are two ways to run an import, and they take different inputs:

Admin panel (UI)CLI
InputLive pull over SSH from the source WHMA staged cpmove/backup archive already on the server
ScaleOne or many accounts (batch)One account per invocation
DNS cut-overOptional, automaticNot performed
ProgressLive, reconnectablePrinted to the terminal
Best forMigrating a whole server, hands-offScripting, air-gapped transfers, a single archived account

Both paths feed the same import engine, so the scope of what gets imported and how credentials are handled is identical.

Everything below is provisioned automatically from one cPanel account:

  • System account — the Linux user, its password hash (when compatible), and optionally its original UID/GID.
  • Primary domain — virtual host, managed DNS zone and a fresh DKIM key.
  • PHP version — the source per-domain version is matched to an installed one: exact X.Y if present, otherwise the newest minor of the same major, otherwise the server default (any downgrade is noted in the report).
  • Secondary domains — addon domains, domain aliases (parked) and subdomains, each with its own vhost.
  • Mailboxes — with their messages (full Maildir) and passwords preserved.
  • Mail extras — forwarders, autoresponders and mail filters (translated to CorePanel’s Sieve model).
  • FTP accounts — the main account plus any extra ones, passwords preserved.
  • MySQL — databases with their data, plus database users (their MySQL password hash is re-applied, so app config keeps working).
  • Cron jobs — installed as panel-managed cron.
  • SSL certificates — cert, chain and key installed via the certificate manager.
  • DNS records — parsed from the source BIND zones and merged into the new zone; A/AAAA records that pointed at the old server IP are rewritten to this server’s IP, while MX, TXT/SPF, DKIM, CNAME and CAA are preserved.
  • Home directory — the full site tree, restored and re-owned (with SELinux contexts fixed).

Every site keeps serving from the path it had on the source server. The importer does not move the files into CorePanel’s own layout, it re-points the vhosts at where the restored home actually put them:

On cPanelOn CorePanel after the import
~/public_html (primary)~/public_html
~/public_html/addon.com (addon, cPanel nests them)~/public_html/addon.com
~/public_html/blog (subdomain, named after the label)~/public_html/blog
~/dl.example.com (a site edited by hand to sit beside public_html)~/dl.example.com

Only the home directory prefix changes, and only when the account gets a different username here (a name conflict on import). A site provisioned by CorePanel afterwards uses CorePanel’s own layout — ~/domains/<name> — but nothing already imported is rewritten to match it.

This matters because absolute paths are baked into the sites themselves: wp-config.php, compiled caches, .htaccess include paths, and the cron jobs the importer restores alongside them. Moving the tree would break all of those silently. CorePanel instead extends the two things that make a directory servable — its SELinux file context and the PHP pool’s open_basedir — to cover the imported path.

This is a one-shot import, not a two-way sync, and it only reads cPanel archives:

  • Other panels (Plesk, DirectAdmin) — cPanel only.
  • The cPanel reseller tree — you map each account to a CorePanel seller/package yourself.
  • cPanel-specific state with no CorePanel equivalent — cpbackup jobs, Softaculous installs, cPanel API tokens.
  • A mailbox on a domain that has no mail identity on this server (e.g. a mailbox under an alias or a subdomain) — it is reported as dropped, never silently lost.

CorePanel imports the original password hashes verbatim whenever they can be verified later — no plaintext is ever needed or shown.

CredentialPreserved when the hash is…Otherwise
System / SSH / main FTPSHA-512 $6$, SHA-256 $5$, MD5 $1$, bcrypt $2a/2b/2y$, yescrypt $y$Random password set, reset required
Mailbox & extra FTPSame crypt families as aboveRandom password set, reset required
MySQL usersmysql_native_password / caching_sha2_password (re-applied at the MySQL layer)

The system login is the strictest case: RHEL’s crypt(3) verifies the hash at SSH/FTP login, so a scheme it can’t check (e.g. argon2) is treated as non-preservable — the account gets a random password and is flagged for a reset, rather than becoming an account that can never log in. When a credential can’t be preserved, the login still exists — the user just has to set a new password. Those users are listed under Password resets required in the report.

Procedure — Admin panel (live pull over SSH)

Section titled “Procedure — Admin panel (live pull over SSH)”

Open Migration → Import account from cPanel in the panel. The import runs entirely on the CorePanel server, so you can close the browser and reconnect to it later.

Enter the source WHM/cPanel hostname or IP, the SSH port, and root SSH credentials. The password is used only for the connection and is never stored.

Step 1 — connect to the source cPanel/WHM server with root SSH credentials

CorePanel lists every account on the source server with its primary domain, plan and disk usage. Verify the server’s host-key fingerprint matches the real source, search/filter, and tick one or many accounts (Select all acts on the current filter). Suspended accounts are flagged.

Step 2 — pick one or more accounts from the source server inventory

Step 3 — target package, UID/GID preservation, DNS cut-over and conflict policy

  • Target hosting package — its limits (disk, mailboxes, databases…) are applied to the imported account. Leave as Default for unlimited/server defaults.
  • Preserve UID / GID (recommended) — keep the source system user/group ids for a full-fidelity migration.
  • Point DNS to this server — when each account finishes, CorePanel logs into the source server (still authoritative during the switch) and repoints only the A records that pointed at the old IP, so live traffic follows the migration without waiting for a registrar change. Domains whose DNS lives elsewhere are left untouched and flagged as external.
  • If the account or domain already existsAbort (fail) or Skip (do nothing).

Confirm the summary and start. Accounts are imported one at a time on the server.

Step 4 — review the migration summary before starting

Each account shows a phase tracker (Connect → Transfer → Restore → Done), the transfer size, a live count of created / reset / deferred / dropped / failed resources, and the full per-resource log. The import keeps running on the server if you navigate away — reopen the page and pick it up from Recent imports.

Step 5 — live per-account import progress with the resource report

Use the CLI when you already have a cpmove-<user>.tar.gz / backup-*.tar.gz archive (or an extracted account directory). The archive path is resolved on the CorePanel server, so stage it there first — the conventional location is /var/lib/corepanel/import/.

A dry-run parses the archive and prints the plan — resource counts, credential compatibility, conflicts and warnings — without touching the system:

Terminal window
corepanel account import /var/lib/corepanel/import/cpmove-acme.tar.gz --dry-run
cPanel import preview (dry-run)
==============================
Source: cpanel 110.0.5 @ web-oldhost-01.example.net
Account: acme (uid 1042, gid 1042)
Domain: acme-store.com
Plan: business
Contact: admin@acme-store.com
Resources:
domains=3 mailboxes=8 forwarders=4 databases=2 db-users=2
dns-records=27 ftp=3 cron=1 certificates=1
Credentials:
system password: preserved
mailbox/ftp: 9 preserved, 2 reset (of 11)
Domains:
- acme-store.com primary [ssl]
- shop.acme-store.com subdomain
- acme-labs.io addon
Conflicts: none
Terminal window
corepanel account import /var/lib/corepanel/import/cpmove-acme.tar.gz \
--package 3 --preserve-uid --report /root/import-acme.json

Flags:

FlagPurpose
--dry-runParse and validate only; print the plan and touch nothing
--seller <id>Target seller id (default: the primary seller)
--package <id>Target hosting package; its limits drive the account
--preserve-uidKeep the source UID/GID via useradd -u/-g
--on-conflict abort|skipPolicy when the user/domain already exists (default abort)
--report <path>Write the full JSON import report to this path

The command prints the per-resource result and exits non-zero if the job status is failed, so it fits cleanly into migration scripts:

cPanel import
=============
Job: #42
Status: partial
Account: acme (id 17)
Domain: acme-store.com
Resources:
[created ] account:acme — system password preserved ($6$)
[created ] domain:acme-store.com — primary domain, vhost and managed DNS zone
[created ] mailbox:sales@acme-store.com — mailbox password preserved
[reset ] mailbox:old@acme-store.com — mailbox password could not be preserved; a reset is required
[created ] db:acme_shop — database restored
Password resets required (1):
! old@acme-store.com

A running or finished job can also be polled with core.GetImportJob and listed with core.ListImportJobs — the same jobs the panel’s Recent imports shows.

Each resource ends in one of these states:

StatusMeaning
createdImported successfully, credential preserved
reset requiredImported, but the password couldn’t be preserved — the user must set a new one
deferredRecognized and handled in a later phase (not lost)
droppedPermanently not imported (e.g. a package limit was hit, or a mailbox with no mail identity here)
skippedAlready existed, or skipped by the conflict policy
failedAn error occurred provisioning this resource

The overall job is completed only when every resource is created/deferred with no forced resets; any reset, dropped or failed resource makes it partial.

Warnings sit beside those statuses and can also downgrade a job to partial — an unmapped document root (see Where the sites end up) does, because the domain exists but its site is not serving.

  1. Hand out password resets. Everyone listed under Password resets required has a working login but a randomized password — send them a reset.
  2. Check DNS. If you didn’t use Point DNS to this server, update the A records (or the registrar’s nameservers) so the domains resolve to CorePanel. Domains flagged external always need a manual change.
  3. Verify the account. Confirm the site serves over HTTPS, mail authenticates (STARTTLS + IMAP login), and the databases contain their data.
  4. Re-run if needed. Imports are idempotent — re-running against an existing imported account resumes only the missing resources; it never duplicates them.