# Migrate cPanel accounts to CorePanel over SSH, straight from the WHM server

> With root on the cPanel server, CorePanel lists its accounts, packages the ones you pick, copies them across and imports them, one after another, with passwords, mail, databases and DNS. No archive to carry, nothing changed on the source.

Source: https://www.corepanel.net/tutorials/migrate-cpanel-accounts-over-ssh-corepanel
Author: CorePanel Team
Published: 2026-10-06
Track: CorePanel · intermediate · ~30 min
Tested on: AlmaLinux 9.8 · CorePanel 1.9.0 (2026-10-06)
Tested on: AlmaLinux 10.2 · CorePanel 1.9.0 (2026-10-06)
Tested on: Rocky Linux 9.8 · CorePanel 1.9.0 (2026-10-06)
Tested on: Rocky Linux 10.2 · CorePanel 1.9.0 (2026-10-06)
Before you start: https://www.corepanel.net/tutorials/install-corepanel-first-website-ssl-almalinux-rocky
CorePanel edition needed: Personal (free)
Tags: corepanel, cpanel, whm, migration, cpanel-alternative, ssh, wordpress, email, dns, almalinux, rocky-linux
From CorePanel Tutorials — https://www.corepanel.net/tutorials

---

When you run the cPanel server yourself, the quickest way to move accounts off it is to let
CorePanel fetch them. You give it the server's address and root's password; it lists every
account, you tick the ones to move, and it does the rest on its own, one account at a
time: `pkgacct` on the source, the copy, the import, the report. You can close the browser
while it works.

The source server is only read. Its accounts keep serving until you move their DNS, so you
can migrate a few sites a night and leave the rest where they are.

The examples move the account `shop`, with the domain `example.org`: WordPress on PHP 8.1
with its database `shop_wp`, and the mailbox `info@example.org`. The cPanel server is
`cpanel.example.net` (`198.51.100.5`). The CorePanel server comes from
[Install CorePanel and host your first website](https://www.corepanel.net/tutorials/install-corepanel-first-website-ssl-almalinux-rocky):
`203.0.113.10`, with `ns1.example.com` and `ns2.example.com` as its nameservers.

## Let CorePanel log in to the cPanel server

CorePanel connects to the cPanel server over SSH as `root`, **with a password**. Many
cPanel servers only accept keys for root, and that is the better setting, so open password
login for root to the CorePanel server's address only, for the time the migration takes.
On the **cPanel** server, add this at the end of `/etc/ssh/sshd_config`:

```bash
cat >> /etc/ssh/sshd_config <<'EOF'

# CorePanel migration — remove when done
Match Address 203.0.113.10
    PasswordAuthentication yes
    PermitRootLogin yes
EOF
sshd -t
systemctl reload sshd
```

It has to go at the end: everything after a `Match` line belongs to it. `sshd -t` checks the
file before the reload. If the server also runs cPHulk or CSF, allow `203.0.113.10` there
too, so a mistyped password does not get the CorePanel server blocked.

The password is used for the connection only: CorePanel does not store it.

## Connect and pick the accounts

In CorePanel, open **Backup & Transfers → Transfers**. Enter the cPanel server's host name or
IP address, the SSH port (`22`), `root` and its password:

![The Transfers tab with two ways to import from cPanel — cPanel/WHM with root, and cPanel with the account's login — and the four steps Connect, Select account, Options and Confirm, on the Connect step that asks for the source server and its root credentials.](https://www.corepanel.net/_astro/cpanel-import-connect.B3x8yE1t.svg)

CorePanel lists every account on the server, with its domain, plan and disk usage, and
shows the server's **SSH host-key fingerprint**. Compare the fingerprint with the server's
own before going on. On the cPanel server, this prints it:

```bash
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
```

Tick `shop`. To move several accounts, tick them all, or filter the list and use
**Select all**; suspended accounts are marked, and come over suspended.

![The Select account step: the source server's name, cPanel version and SSH host-key fingerprint, a search box and Select all, and a list of accounts with their domain, plan and disk usage, one of them marked Suspended, three of them ticked.](https://www.corepanel.net/_astro/cpanel-import-select.C8jx5m2_.svg)

## Choose the options

![The Options step: a target hosting package selector, a Preserve UID / GID switch, and a Point DNS to this server switch that repoints the account's A records on the source server once its import finishes.](https://www.corepanel.net/_astro/cpanel-import-options.D-B7cPSQ.svg)

- **Target hosting package.** Leave it empty and each account goes to the CorePanel package
  with the same name as its cPanel plan, if there is one. Either way the account keeps the
  limits cPanel recorded for it.
- **Preserve UID / GID.** Switch it on. The files keep their numeric owners, which matters
  for anything that recorded them.
- **Point DNS to this server.** When an account finishes, CorePanel logs in to the cPanel
  server again and changes, in its DNS zones, the `A` records that pointed at the old IP to
  this server's. That moves visitors over within minutes when the cPanel server is still the
  domain's nameserver and you are not ready to change nameservers. In this tutorial the
  domain moves to CorePanel's own nameservers, so leave it off.
- **If the account or domain already exists.** Keep **Abort**: nothing is overwritten.

Review the summary and click **Start**.

## Watch it work

![Live progress of one account at 62%: a phase tracker Connect, Transfer, Restore, Done; a Transfer card with the connection, pkgacct and the downloaded archive; a Restore card counting created, reset, deferred, dropped and failed resources with a Copy the home directory bar; and the list of resources below.](https://www.corepanel.net/_astro/cpanel-import-progress.BAFV1fFY.svg)

For each account, CorePanel runs `pkgacct` on the cPanel server, copies the archive across,
creates the account and restores into it, and writes a report. Accounts go one at a time, so
the cPanel server never packages two at once. The job runs on the CorePanel server: close
the page and pick it up later from **Recent imports**. A 100 MB account takes under a
minute.

When it is done, the account is here:

```bash
corepanel account list
corepanel wp list shop
corepanel mail list example.org
```

```text
| 2  | example.org | shop    | 1      | 1/∞   | 1/∞ | 0/∞        |         | active |
ID  STATUS  VERSION  SITE URL             PATH
1   ok      7.1.2    https://example.org  /home/shop/public_html
info@example.org                  active     quota=1024 MB
```

The report says what came over, resource by resource:

- the account, its password and its FTP logins, with their passwords;
- the site, at the same path as on cPanel, `/home/shop/public_html`;
- the database `shop_wp`, with its user and that user's password, so `wp-config.php`
  works unchanged;
- the mailbox, with its messages and its password;
- the DNS zone, with its custom records, and every record that pointed at `198.51.100.5`
  rewritten to `203.0.113.10`;
- the WordPress site, now in the **WordPress** list.

It also has two warnings. The site ran PHP 8.1 and runs on 8.4 here, the newest version of
the same major release, because 8.1 is not installed on this server. And cPanel's
`default` plan has no package of that name here, so the account is not attached to one.

## Test before the DNS moves

Visitors still reach the cPanel server. Ask the new one directly:

```bash
curl -sk --resolve example.org:443:127.0.0.1 https://example.org/ | grep -o '<title>[^<]*</title>'
curl -sk --resolve mail.example.org:993:127.0.0.1 --url 'imaps://mail.example.org/INBOX' --user 'info@example.org:Info-Shop-2026!' -X 'STATUS INBOX (MESSAGES)'
```

```text
<title>Example Shop</title>
* STATUS INBOX (MESSAGES 1)
```

The page came from the imported database on PHP 8.4, and the mailbox opened with its cPanel
password. `-k` skips the certificate check: the free certificate is only issued once the
domain points here. To browse the site, add `203.0.113.10 example.org www.example.org` to
the hosts file of your own computer and remove it when you are done.

> **A site that breaks on PHP 8.4**
>
> `corepanel php install 8.1`, then `corepanel account update shop --php 8.1`. PHP 8.1 gets
> no security fixes any more: use it to keep the site up while you fix what needs it.
## Switch the DNS

At the registrar, change the nameservers of `example.org` to `ns1.example.com` and
`ns2.example.com`. The zone on CorePanel is already complete.

```bash
dig +short NS example.org
```

```text
ns1.example.com.
ns2.example.com.
```

CorePanel checks every 30 minutes whether a domain waiting for its certificate has been
delegated, then orders a wildcard for `example.org` and `*.example.org`:

```bash
timeout 2400 bash -c 'until echo | openssl s_client -connect example.org:443 -servername example.org 2>/dev/null | openssl x509 -noout -ext subjectAltName 2>/dev/null | grep -q "\*.example.org"; do sleep 10; done'
curl -fsS -o /dev/null -w '%{http_code}\n' https://example.org/
```

```text
200
```

Mail sent while senders still had the old answer cached lands on the cPanel server. Keep the
account there for a few days, then move any late messages across from a mail app connected
to both mailboxes.

## Close the door you opened

When the last account you are moving has landed, remove the `Match` block from
`/etc/ssh/sshd_config` on the cPanel server, then `sshd -t` and `systemctl reload sshd`.
Root is back to keys only. A week after the switch, remove the migrated accounts from
cPanel with `/scripts/removeacct <user>`.

## What you have now

| | On cPanel | On CorePanel |
|---|---|---|
| Site | `public_html`, PHP 8.1 | Same path, PHP 8.4, under **WordPress** |
| Database | `shop_wp` | `shop_wp`, same user and password |
| Mail | `info@example.org` | Same mailbox, same password, its messages |
| DNS | Zone on the cPanel server | Zone on CorePanel, records kept, IPs rewritten |
| Source server | Serving, untouched | — |

The other accounts are still on cPanel, waiting for the next batch. When the last one is
gone, or if you would rather convert the whole server at once, in place and with a way back,
see [Transform](https://www.corepanel.net/docs/cpanel-transform). No root on a cPanel server, only an account's
login? [Move a website off shared cPanel hosting](https://www.corepanel.net/tutorials/move-website-from-shared-cpanel-hosting-corepanel).
