Panellicense

How to migrate from cPanel to Plesk without downtime

A production playbook for moving cPanel accounts to Plesk using the Plesk Migrator — pre-flight checks, sync mode, DNS cutover, and the gotchas that stall real migrations.

8 min readUpdated 2026-05-15migration · cpanel · plesk · plesk-migrator
schema: HowToschema: FAQPageschema: BreadcrumbList

The cPanel price hikes since 2019 push more hosts to evaluate Plesk every year, and the calculation gets harder each renewal. The good news: Plesk ships a first-party migration tool that handles roughly 90 % of the work. The bad news: the remaining 10 % is where most migrations stall — PHP version mismatches, custom vhost includes, mail filter rules, and DNS records that nobody documented.

This guide is the production playbook — a tested sequence that moves accounts from a live cPanel server to a fresh Plesk Obsidian box with under a minute of HTTP and mail interruption per domain. If you're still deciding whether the move makes sense, read the cPanel vs Plesk in 2026 breakdown first.

Before you start

You need:

  • A target Plesk server already provisioned (see installing Plesk on Ubuntu 24.04) with enough disk for 1.4× the source data footprint — the migrator copies before it cleans up
  • Root SSH access to both the source cPanel server and the target Plesk server
  • The source cPanel WHM API token (Home → Development → Manage API Tokens) or root SSH
  • An active Plesk license on the target — activate one before starting; the migrator refuses to run on a trial when account counts exceed the trial cap
  • Outbound TCP 22 from target to source, and ideally a private network between them if the data set is large

Lower your DNS TTLs to 300 seconds at least 24 hours before cutover. This is the single biggest mistake in hosting migrations and it cannot be fixed after the fact.

Step 1 — Provision and prep the target

The target Plesk server should be on the same major OS family as the source where possible. AlmaLinux 9 source to AlmaLinux 9 target is the smoothest path; cross-distro migrations work but multiply the PHP version edge cases.

plesk bin server_pref --update -hostname plesk.example.com
plesk bin php_handler --reread
plesk bin repository --update-extensions

Install every PHP version your source cPanel servers run, plus one above. If cPanel has EasyApache built with PHP 7.4, 8.1, and 8.2, install all three on Plesk before migrating — the migrator maps PHP handlers by version and skips domains whose handler is missing.

plesk installer add --components php7.4 php8.1 php8.2 php8.3

Step 2 — Install the Plesk Migrator extension

Plesk Migrator is a free first-party extension. Install from the catalog UI, or via CLI:

plesk bin extension --install-url https://ext.plesk.com/packages/plesk-migrator

Confirm it loaded:

plesk ext migrator --help

If the binary isn't on path, the extension is at /usr/local/psa/admin/plib/modules/panel-migrator.

Step 3 — Run the pre-flight check

The pre-flight is the most important step in this guide. It generates a report of every account, its size, its PHP requirements, and any feature that won't migrate cleanly. Run it before scheduling any cutover window.

plesk ext migrator start-migration \
  --source-host source.example.com \
  --source-login root \
  --source-key /root/.ssh/migration_key \
  --pre-check-only \
  --subscriptions all

Read the resulting report at /usr/local/psa/var/modules/panel-migrator/sessions/<id>/report.txt. Things the pre-flight surfaces that always matter:

  • PHP versions present on source but not target
  • Apache custom includes in /usr/local/apache/conf/userdata/ — these are not migrated and need to be rebuilt as Plesk vhost templates
  • ModSecurity custom rules — Plesk uses its own rule sets; OWASP CRS migrates, custom rules do not
  • Mail filters with sieve syntax — basic rules migrate; complex vacation and pipe filters often don't
  • Domains pointing at unsupported add-on resellers (rarely an issue, but the report will flag them)

Fix what you can on the source side first. Every issue resolved before migration is one fewer ticket the day after.

Step 4 — Migrate accounts in batches

Don't migrate the whole server in a single run. Even with healthy bandwidth, a 500-account server in one shot is 12+ hours of opaque progress and any failure rolls back work you'd rather keep.

Migrate in batches of 20-50 subscriptions, sorted smallest-first. Small accounts shake out config issues cheaply; the big mailboxes go last when you've already proved the path.

plesk ext migrator start-migration \
  --source-host source.example.com \
  --source-login root \
  --source-key /root/.ssh/migration_key \
  --subscriptions site1.com,site2.com,site3.com

At this point the migrator copies files, databases, mail, and DNS zones. DNS on the public internet still points at the source — nothing has cut over yet. Customers continue hitting the cPanel server normally.

Step 5 — Sync mode for the catch-up

After the initial batch, the source keeps receiving mail and file changes until you cut over. Sync mode picks up the delta — only the files modified since the last sync — and is fast enough to run every 15 minutes for the final hours before cutover.

plesk ext migrator resume-migration \
  --session <session-id> \
  --sync

Run sync at least three times: once after the initial migration, once a few hours later, and once immediately before flipping DNS. The last sync is what bounds your data-loss window — if it completes at 02:14 and you flip DNS at 02:15, customer mail received during that one-minute gap is on the source server and won't appear on the target until the next post-cutover sync.

Step 6 — DNS cutover

With TTLs already at 300 seconds (you did this on day one, right?), update the A and MX records to point at the Plesk server. The cleanest order:

  1. Update DNS at the registrar or DNS provider
  2. Wait for the TTL window to expire (5 minutes plus your slowest resolver)
  3. Run a final sync — --sync once more to grab the last mail that landed on the source

For domains where you control the authoritative nameservers, switch the nameservers on the domain itself rather than editing records, and pre-stage the Plesk-side zones so they answer correctly the moment they're queried.

Step 7 — Final sync and decommission

Run one last sync after DNS has fully propagated (give it 24 hours to be safe). At this point both servers are accepting mail for the migrated domains — the source because old caching resolvers still point there, the target because DNS now resolves to it. Forward the source's catch-all to the target's MX for another 7 days as a safety net:

# on the source cPanel server, per domain
echo ":fail: moved" > /etc/vfilters/example.com
# then set up SMTP forwarding via /etc/exim.conf.local

After two weeks of zero hits in the source access logs, you can decommission. Keep a full backup of the source for at least 90 days — there is always one customer who discovers a missing file three weeks after cutover.

Common gotchas

PHP open_basedir differences. Plesk locks open_basedir to the vhost root by default; cPanel is more permissive. Sites that read from /home/<user>/ paths outside their vhost break on the first request. Either widen open_basedir in the Plesk domain settings or fix the application.

Mail filter syntax. cPanel uses Exim filters; Plesk uses Dovecot Sieve. The migrator translates common rules — server-side forwards, autoresponders, simple "move to folder" rules. Anything involving pipe, vacation with custom intervals, or per-header regex is silently dropped. The pre-flight flags these; check before the cutover, not after.

AWStats / Webalizer history. Historical stats don't migrate. If customers care about stats continuity, snapshot the cPanel /home/<user>/tmp/awstats directory and tell them where to find the archive. Plesk's stats start from zero on day one.

ModSecurity custom rules. cPanel's ModSecurity rule manager exports OWASP CRS rules cleanly; custom rules ship as .conf files in /etc/apache2/conf.d/modsec_vendor_configs/ and do not transfer. If you've added any rule to block specific bots or vulnerabilities, re-apply them through Plesk's Web Application Firewall after migration.

.htaccess files using mod_ruid2. Plesk uses PHP-FPM with FastCGI by default; mod_ruid2 directives are silently ignored. Most sites don't notice, but anything relying on per-user file ownership for writes will break — switch to PHP-FPM running as the subscription's system user, which Plesk does by default.

Can I migrate from cPanel to Plesk without downtime?+
Yes, near-zero downtime is achievable using the Plesk Migrator's sync mode and pre-lowered DNS TTLs. Expect 30-60 seconds of mail and HTTP interruption per domain during the DNS cutover window — not minutes or hours.
Does Plesk Migrator cost anything?+
No. Plesk Migrator is a free first-party extension and does not require a separate license. The target server needs an active Plesk license sized for the migrated subscription count.
How long does a cPanel to Plesk migration take?+
For a server with 100 accounts averaging 2 GB each, plan on 6-8 hours for the initial batch plus 30 minutes per sync run. Total project time including pre-flight, batches, and cutover is typically 2-3 days, with the customer-visible cutover under a minute per domain.
Will customer passwords work after migration?+
Mail and FTP passwords migrate intact because the migrator transfers password hashes directly. Customer panel passwords are reset — Plesk sends each customer a password-reset email when their subscription is activated.
Can I migrate selected accounts and leave others on cPanel?+
Yes, the migrator's --subscriptions flag accepts a list of specific domains. This is the normal way to run a migration — small batches first, big accounts last, and you can stop at any point if you want to keep some customers on the source server.

Next steps

Switch in an afternoon

Switch from your current reseller — free.

We migrate active cPanel, Plesk, LiteSpeed and CloudLinux licenses from any reseller. We prorate the first month so you never pay twice, and your customers see zero downtime during the swap.