The cPanel migration check
Before moving anything, you can find out what a move would involve. The migration check is a single command you run on your cPanel server. It reads that server’s configuration and prints an inventory, a score, and the specific list of things that would need attention — then deletes itself.
curl -fsSL https://get.corepanel.net/check | shIt must run as root, because the things worth reporting on — accounts, mailbox hashes, per-domain PHP versions — live in files only root can read.
What it tells you
Section titled “What it tells you”CorePanel migration check=========================
Server: cp.example.comOS: AlmaLinux 9.8cPanel: 11.136.0.35Database: 10.11.19-MariaDBPHP: ea-php81, ea-php82DNS: powerdnsFTP: pure-ftpd
Inventory: 5 accounts, 11 domains, 4 mailboxes, 3 databases, 8 DNS zones, 9 certificatesPackages: 2 (default, starter)
Score: 100/100 — ready to transform
NOTES (3) • JetBackup is installed on this server → account backups carry over as a capability: CorePanel has its own backup system…
──────────────────────────────────────────────────────────────────── ✔ READY TO TRANSFORM score 100/100 · nothing on this server stands in the way────────────────────────────────────────────────────────────────────
WHAT COMES NEXT
PLAN the ordered list of steps, with how long each service is offline. Read-only, like this check.
PREPARE installs CorePanel beside cPanel, with nothing going offline: cPanel keeps serving every site throughout.
CUTOVER is the only offline window — seconds rather than hours, because nothing is copied.
VERIFY checks that every domain, mailbox, database and zone answers.
'rollback' gives the server back to cPanel at any point until 'cleanup'.
Nothing on this server was modified.Add -v to list every account individually, with its domains, mailboxes, databases,
cron jobs, certificates and its own findings:
curl -fsSL https://get.corepanel.net/check | sh -s -- -vThe verdict
Section titled “The verdict”The last thing the check prints is its answer, in one of three states:
| Banner | What it means | |
|---|---|---|
| 🟢 | READY TO TRANSFORM | Nothing on this server stands in the way |
| 🟡 | READY TO TRANSFORM, WITH ITEMS TO REVIEW | It works, but some items degrade or need manual work — they are listed above the banner |
| 🔴 | CANNOT BE TRANSFORMED IN PLACE | One or more blockers have to be resolved first. The banner deliberately offers no next command |
The same answer appears next to the score at the top of the report; it is repeated at the end because on a server with dozens of findings the top has long scrolled away.
Colour is a convenience of the terminal, not part of the report: it is used only when
the output is a terminal, so a run redirected into a file or pasted into a ticket is
plain text. NO_COLOR turns it off, and --color=always forces it on.
Reading the findings
Section titled “Reading the findings”Every finding carries one of three severities, and they mean genuinely different things.
| Meaning | What to do | |
|---|---|---|
| Blocker | This server cannot be migrated as it stands | Each blocker names its way out. The common one is the operating system: CorePanel runs on RHEL 8–10 and its rebuilds |
| Warning | The migration works, but something specific degrades | Read it before you schedule anything. Most warnings are per-domain and name the file and the line |
| Note | Reported for completeness, costs no score | Nothing to do. A note is there so nothing arrives as a surprise later |
Handled by the cutover
Section titled “Handled by the cutover”Below the findings, the check prints a section of its own: HANDLED BY THE CUTOVER. Your server is probably not just cPanel — it carries a WAF, a firewall, a backup product, maybe a proxy in front of Apache — and those are not problems to solve. CorePanel brings what each of them was doing, and the transformation stops them for you.
| Product | What takes over |
|---|---|
| NGINX (cPanel’s NGINX Manager), Engintron, Varnish, LiteSpeed | corehttpd, which serves every site and caches pages itself |
| Imunify360 / ImunifyAV, BitNinja, cPGuard | CorePanel’s WAF — included in every edition — and Pyxsoft Anti Malware for scanning |
| Bought ModSecurity rule sets (Comodo, Atomicorp, …) | the same WAF. There is nothing to buy and nothing to install |
| JetBackup | CorePanel’s own backups. Existing archives are not adopted — keep them reachable until the rollback window closes |
| Softaculous | CorePanel’s application installer. Installed applications keep working: they are just files |
CSF/LFD, or PyxSoft’s pxf | corepanel-auth takes over brute-force protection. The firewall itself is turned off rather than kept — see below |
Nothing on that list is uninstalled, and nothing on it needs doing before you start. Each is stopped, disabled and — for the ones that restart themselves — masked, so a rollback puts every one of them back.
The host firewall is turned off
Section titled “The host firewall is turned off”CSF/LFD, or PyxSoft’s pxf, is disabled during the cutover — with csf -x and
pxf disable, their own commands, because stopping the unit leaves every rule
in the kernel. This is not offered as a choice, for two reasons: it opens
cPanel’s ports and not CorePanel’s, so a server that keeps it is a server whose
passive FTP does not work; and ConfigServer closed in August 2025, so CSF has no
upstream — what is on the machine is unmaintained software configured for a
panel that is about to be gone.
That leaves the server without a firewall until you put one back. The check
and the cutover both say so in those words. firewalld is the one CorePanel
manages, from the panel or the CLI, and it is what should be in front of the
server before it is left to itself. If you roll the transformation back, csf -e
and pxf enable are the exact reverse and rollback runs them for you.
It has one consequence that is worth knowing about, because nothing on the
server announces it: on a dual-stack machine, taking the firewall down can
change which of the server’s two addresses its outbound connections leave
from. With no policy in /etc/gai.conf, the C library prefers IPv6 to IPv4 for
every destination that offers both — so a server that had been seen at its IPv4
for years starts being seen at its IPv6, and everything licensed against the
address (WHMCS, Softaculous, LiteSpeed, JetBackup) starts failing its licence
check. Not at the cutover: each product runs on a cached verdict for hours, so
the first symptom is a licence error in the middle of the night on a server whose
migration went perfectly. The cutover pins the preference back to IPv4 for you,
right after the firewall goes down. If you have written your own policy into
/etc/gai.conf the run leaves it alone and tells you to re-check those licences
yourself.
Mail your applications send stays working
Section titled “Mail your applications send stays working”cPanel’s Exim offers authentication on port 587 without requiring TLS first, and CorePanel installs Postfix the other way round, because requiring it is the right default for a server nobody has migrated anything onto. That difference is invisible until it isn’t: an application on the server configured to send mail unencrypted to its own host — a billing system, a WordPress plugin, a shop — simply stops sending, with an authentication error that has nothing to do with its credentials.
The cutover reads what your mail server advertises before it stops it, and configures Postfix to match. A server whose Exim allowed it keeps allowing it; one that already required TLS stays strict. Either way STARTTLS is offered, so mail clients go on encrypting, and a CorePanel server installed from scratch is unaffected.
It is a compatibility setting, not a target state. Once those applications are moved onto STARTTLS, this puts the strict default back:
postconf -P 'submission/inet/smtpd_tls_security_level=encrypt'systemctl reload postfixThe short list that does need you
Section titled “The short list that does need you”Three things the transformation deliberately does not decide for you, because each would cost something silently:
- MailScanner holds mail in a spool of its own, and the cutover flushes Exim’s queue rather than that one. Let it drain and stop it before the window.
- MailChannels relays your outbound mail by configuring Exim. Postfix takes the mail at the cutover, so from that moment the server sends directly from its own address — check your SPF and your reputation first.
- A block-level backup agent (R1Soft, Acronis) keeps running, but its policy names cPanel’s paths. Repoint it, or the first backup after the cutover silently protects nothing.
A site that is already broken
Section titled “A site that is already broken”The check asks each of this server’s own sites for its homepage, the way a visitor would, and tells you about the ones that are not working right now, before anything has been transformed:
• billing.example.com is not working right now, before anything has been transformed: the ionCube loader is missing… → fix it before the cutover or accept that it stays broken afterwardsIt is not scored. Nothing about a customer’s broken site makes this server harder to move, and the transformation neither causes it nor repairs it. It is reported because of what happens if nobody says it out loud: the site is still broken afterwards, the health gate at the end of the cutover finds it, and it reads as a fresh failure — over a page that was an error message before the run started.
Two kinds turn up:
- A page that announces its own failure with HTTP 200. Encoded software — WHMCS and most billing systems — prints “the ionCube Loader needs to be installed” and stops, and PHP calls that a successful request. Nothing about the status code shows it.
- A homepage that is a PHP error and nothing else. cPanel runs suPHP with
display_errorson, so the error is the page and it is served as a 200. CorePanel runs PHP-FPM with it off, so the same fault becomes an honest 500. The site is no worse afterwards — it stops pretending to work, which is worth knowing before you see the 500 and reach for the rollback.
--no-dns turns this pass off along with the domain lookups, for when you are scanning a
copy of a server rather than the live one.
CloudLinux
Section titled “CloudLinux”CloudLinux is a blocker, and the check gives you the removal command. It is not
a capability problem: the limit people buy LVE for is the entry process, and
that is what corehttpd does per account — with the same 508 — alongside
per-request memory and time ceilings and a global one that protects the box.
See PHP Isolation and Limits.
It has to come off first for two reasons that have nothing to do with what CorePanel can host: removing it swaps the kernel and needs a reboot, so it cannot happen inside the cutover window; and CageFS shows each user a different filesystem, which makes every measurement taken under it a measurement of a server nobody serves.
Run CloudLinux’s own procedure while cPanel is still installed, then run the
check again. It moves your sites off alt-php, so check each domain’s PHP
version afterwards — and on CloudLinux 7 you will land on CentOS 7, which needs
one more step: cPanel’s elevate, as far as AlmaLinux 9.
The score is the weighted result of those findings. It is not a marketing number: it is computed from a versioned rule set built into the binary, so it always reflects what the current CorePanel actually supports rather than what a brochure claims.
Databases
Section titled “Databases”The check reports which database engine the server runs and what a transformation would do with it. There are three answers, and which one applies is decided by the engine itself:
| Engine | What happens | Cost |
|---|---|---|
| MariaDB 10.11 or newer | adopted exactly where it is — same data directory, same server, same version | seconds, whatever the data size |
| MariaDB older than 10.11 | upgraded in place with mariadb-upgrade over the same data directory | minutes; nothing is copied |
| MySQL (any version) | dumped and restored onto MariaDB | the only step whose downtime grows with the amount of data |
10.11 is a minimum, not a target. CorePanel keeps its own data in SQLite and never uses MySQL — the database on a hosting server belongs to the sites. So a server already running MariaDB 11.4 or 11.8 is left on it: nothing is reinstalled, no repository is swapped, and no downgrade is ever performed. You get a note saying so, which costs no score, and the server transforms like any other.
The one direction that does not exist is backwards. MariaDB upgrades in place but never downgrades, and nothing in a transformation asks it to.
Resellers
Section titled “Resellers”A server whose accounts belong to resellers gets a note saying so, naming each reseller and how many accounts it owns. This is not a warning, because nothing is lost: cPanel resolves an account’s direct owner and stops, so one level is the source, and each reseller becomes a CorePanel seller owning the same accounts.
Two things are worth knowing before the transformation runs:
- The seller is created from the reseller’s name alone. It arrives with no contact email and no login — the reseller’s own contact details live in their own account’s metadata, which is not the migrating account’s to read. Give the seller both once the transformation is done.
- If a reseller is itself owned by another reseller, a second note says the ownership is read as one level. cPanel allows that shape but does not treat it as a hierarchy anywhere, so nothing is being simplified away.
The billing system that provisions this server
Section titled “The billing system that provisions this server”If a WHMCS has been provisioning this server over the WHM API, the check reports the credentials it finds under CARRIED OVER — and carried over is exactly what happens to them.
cPanel stores a WHM API token as its SHA-512 and never the token itself: the plaintext was shown once, at creation, and the only party that still holds it is the billing system sending it in every request. That digest is all CorePanel needs to accept the same token, so the transformation carries it across and nothing changes on the WHMCS side — no new token, no server entry to edit, and nobody here ever learns it.
The old access hash is carried too, but only where the server still honours it. cPanel
turned it off by default; where allow_deprecated_accesshash is off, WHM answers
Access denied to it, and importing it would mean CorePanel accepting a credential the
old server refused.
The WHM API itself stays closed. Port 2087 is the most attacked port in shared hosting, so nothing opens it as a side effect — not the installer, not the transformation. When you are ready:
corepanel whmcompat enable # serve the WHM API on :2087 (Business)corepanel whmcompat selftest # drive a real WHM API request and report what came backMore websites than the free edition allows
Section titled “More websites than the free edition allows”CorePanel Personal — the free edition — hosts 20 websites. Primary and addon domains count; subdomains, parked names and aliases do not. If the check finds more than 20 it says so, and it says so here rather than as a blocker, because the way out is free and takes one command.
It matters that you see it before you start. The import registers accounts until the cap and refuses every one after it with “website limit reached for this edition” — which happens during PREPARE, with cPanel still serving and nothing lost, but it stops the transformation halfway through an evening you set aside for it.
Pro and Business have no website cap, and a 14-day trial of either is free: no card, no key. Once PREPARE has installed CorePanel and before the import runs:
corepanel license trial --edition business --email you@example.comThe most useful thing the check does is the .htaccess audit. CorePanel does not run
Apache, so every .htaccess on the server is read and classified: rules that are compiled
and applied (the WordPress and standard-CMS shapes, redirects, access rules, Basic auth),
rules that are deliberately not applied and are panel settings in CorePanel instead
(Header, ErrorDocument, DirectoryIndex, SetEnv, the Expires* family), and the
handful that genuinely need a human — mod_security, RewriteMap, SetHandler,
Action, SetEnvIf, SSI. Only the last group costs score.
Keeping the tool
Section titled “Keeping the tool”The one-liner downloads the binary, runs it and removes it — that is what “leaves nothing behind” means, and it applies to the tool itself. To go further than the check, ask the same one-liner to keep it:
curl -fsSL https://get.corepanel.net/check | sh -s -- --installThat installs /usr/local/bin/corepanel-transform from the copy it has already
downloaded and verified. --keep does the same thing and prints the check first.
Running the transformation
Section titled “Running the transformation”Run the installed tool with no arguments and it walks the whole transformation as one guided sitting, stopping to ask before every stage:
corepanel-transform| Stage | ||
|---|---|---|
| 1 | CHECK | reads this server and says whether it can be transformed — read-only |
| 2 | PLAN | writes the ordered steps and the offline window — read-only |
| 3 | PREPARE | installs CorePanel beside cPanel; nothing goes offline |
| 4 | CUTOVER | the offline window: cPanel stops, CorePanel takes over |
| 5 | VERIFY | proves every domain, mailbox, database and zone answers |
Before each stage it prints what that stage does to this server — what goes offline and for roughly how long, the steps it runs, whether it can be reversed — and then asks. Enter goes on, q stops.
Stopping costs nothing. Every step records its outcome before the next one starts,
so corepanel-transform again picks up exactly where it stopped, and a stage
already finished is skipped rather than offered again. That is also what survives a
dropped SSH session or a reboot.
Two stages still ask for a word to be typed, after the prompt and before anything
in them runs: I-HAVE-A-BACKUP for PREPARE and TRANSFORM for CUTOVER.
The guided flow never offers to remove cPanel. cPanel stays installed and disabled
after VERIFY — that is what keeps corepanel-transform rollback available — and
removing it is corepanel-transform cleanup, a separate command for another day.
If you would rather drive it yourself, every stage is its own subcommand:
check, plan, run --phase prepare|cutover|verify, resume, status,
rollback, cleanup. The guided form refuses to run without a terminal and names
those instead, so a pipeline gets the subcommands rather than a wizard answering
its own questions.
Keeping the report
Section titled “Keeping the report”By default nothing is written. To keep a copy — to read later, or to send to us with a question — ask the binary for the file:
corepanel-transform check --report /root/migration-report.jsonreport.json is written owner-only and carries counts, finding codes and domain names.
It contains no password hashes, no keys, no secrets and no file contents — by
construction, and there is a test in the build that fails if that ever stops being true.
Reporting, and turning it off
Section titled “Reporting, and turning it off”Every command of the tool — the check, and each stage of a transformation — sends an
anonymous summary of what it did. --no-telemetry on any of them, or
COREPANEL_NO_TELEMETRY=1 in the environment, stops it:
corepanel-transform check --no-telemetrycorepanel-transform --no-telemetry # the whole guided transformationCOREPANEL_NO_TELEMETRY=1 corepanel-transform # the same, for a scriptWhat is sent, in full, is on the Anonymous usage statistics page. The short version: versions, counts, finding codes, which stage ran, how long it took and which step stopped it if one did — and no hostname, domain, account name or error message, because there is no field for any of them.
Exit status
Section titled “Exit status”The check answers with its status too, so it can be run from a script:
0 | The server can be transformed |
2 | It carries a blocker; the report names it and its way out |
1 | The check itself could not run |
Verifying what you are about to run
Section titled “Verifying what you are about to run”The shim you pipe into sh carries the SHA-256 of each published binary and checks the
download against it before running anything; a mismatch aborts without executing the
file. If you would rather verify by hand, read the script first — it is short, and this
is exactly the kind of thing worth reading before running it as root:
curl -fsSL https://get.corepanel.net/check | lessWhat comes after the check
Section titled “What comes after the check”Today the check answers one question: what would moving this server involve?
For moving accounts onto a CorePanel server you already have, the answer is the
cPanel importer: it pulls accounts over SSH from the live WHM, or
takes a staged cpmove archive, and recreates them natively while preserving passwords.
That is available now, and the check’s inventory is a good way to see what it would find.
Transforming a cPanel server into a CorePanel server in place — same machine, same IPs, no data copied, seconds of downtime instead of hours — is in development. The check is the first part of it and is useful on its own: the score, the inventory and the findings are the same ones that work will act on.