WHM migration: move a whole cPanel/WHM server to Jabali Panel
Last updated
The WHM ingest path. Status: production-supported; effectively a batch of cPanel restores.
Source archive
A WHM-level dump produced by:
/scripts/pkgacct <user>
# or whole-server (one cpmove per account):
/scripts/cpbackup
The output is one or more cpmove-<user>.tar.gz files plus a WHM manifest that maps accounts to packages and resellers.
How the pipeline runs
The WHM ingest:
- Reads the manifest.
- Maps each WHM “package” to the closest existing Hosting Package (matching by disk quota and bandwidth quota). Operator confirms or overrides the mapping.
- For each user, runs the cPanel pipeline with the chosen target package.
- Reports per-user success / failure plus a server-wide summary.
Resellers are flattened: each reseller-owned account becomes a panel user with no parent-child relationship (the panel has no reseller construct).
Operator workflow
- Generate the WHM dump on the source server.
- Upload to the destination, large dumps go via SCP into
/var/lib/jabali/migrations/incoming/. - Analyze the dump. Review the package mapping; create new panel packages if the suggested mapping is wrong.
- Restore. The pipeline iterates per-account, sequential by default. Pass
--parallel Nto run N accounts at a time on a beefy destination host. - After completion, review the per-account failures (if any) and re-run individual cPanel pipelines for them.
Bandwidth-staging notes
- Producing a multi-GiB WHM dump and shipping it over a slow link is the slowest part of the migration. Stage the dump on a local NVMe disk first; transfer with
rsync --partial --progressfor resumability. - For very large estates (dozens of GiB), consider migrating in waves: produce + transfer + restore one batch of accounts, repeat. Avoids holding the source under cutover load for hours.
Limitations
Inherits all cPanel pipeline limitations, plus:
- Reseller branding (white-label themes, custom logos) does not carry over.
- WHM-level cron jobs (
/etc/cron.d/*outside per-user crontabs) are not migrated. - WHM “Tweak Settings” do not map to panel server settings; review and re-apply manually under Server Settings.
Audit
One per-user restore audit row plus per-phase rows per user.
Frequently asked questions
Can I migrate an entire WHM server to Jabali Panel?
Yes. Produce a WHM-level dump on the source (`/scripts/pkgacct` per account or `/scripts/cpbackup` for the whole server) and drop it into Jabali Panel's Migrations section. The pipeline reads the WHM manifest, maps each cPanel `package` to a Jabali Hosting Package, and iterates the cPanel pipeline per account. Per-account failures do not abort the whole run.
How are WHM packages mapped to Jabali Hosting Packages?
The Analyze step matches each WHM package to the closest existing Hosting Package by disk quota and bandwidth quota. If no close match exists, the operator can create a new panel package before Restore. Resellers are flattened — reseller-owned accounts become individual users with no parent-child relationship because Jabali has no reseller construct.
How many accounts can I migrate in parallel?
Sequential by default. Pass `--parallel N` on `jabali migration restore-all` to run N accounts at a time. A safe upper bound is `min(CPU cores / 2, 8)` — MySQL import is the CPU hotspot. Very large estates should stage in waves rather than max out parallelism, so the source doesn't hold cutover load for hours.
What happens to WHM 'Tweak Settings' during migration?
They are not translated to panel server settings. Review the WHM Tweak Settings screen on the source and re-apply the equivalents manually under Jabali's [Server Settings](./server-settings.md). Reseller branding (white-label themes, custom logos) does not carry over.
Are WHM-level cron jobs (/etc/cron.d/*) migrated?
No. Only per-user crontabs migrate. WHM-level `/etc/cron.d/*` entries outside of per-user crontabs need to be re-created manually. Review them against the [Cron allowlist](../cron.md) and translate to systemd-user timers where possible; site-level cron on Jabali runs under the tenant, not root.
How do I retry a single failed account from a WHM restore?
Use `jabali migration retry ` — the panel keeps the source archive on disk under `/var/lib/jabali/migrations/incoming/` until the batch completes cleanly. Individual retries reuse the same cpmove file and update state in place; no need to re-upload.