# Transform changelog

> What changed in each version of corepanel-transform, the tool that converts a cPanel server into a CorePanel server in place — new stages, fixed behaviour, and the notes that matter to a server transformed with an older build.

Source: https://www.corepanel.net/docs/transform-changelog/
Last updated: 2026-09-04
Part of the CorePanel documentation — https://www.corepanel.net/docs

---

This is the release history of **`corepanel-transform`**, the tool that
[turns a cPanel server into a CorePanel server in place](https://www.corepanel.net/docs/cpanel-transform). It is
kept here because the tool is used once per server, and the version you happen to run is
the version your migration behaves like — so what changed between builds is operational
information, not trivia.

> **The tool is in beta**
>
> It runs end to end on real cPanel servers, and the timings published in the documentation
> are measured on one. It is in beta because the set of servers it has met is still small,
> and nearly every new one teaches it something — which is what this page is a record of.
> The design principles that make that acceptable have not changed since the first build:
> every step is written down before the next one starts, an interrupted run resumes where it
> stopped, and the rollback stays one command away until you close the window yourself.
## Which version am I running?

```bash
corepanel-transform version
```

To upgrade, run the installer again — it always fetches the current build, verifies it
against its published checksum and replaces the binary:

```bash
curl -fsSL https://get.corepanel.net/check | sh -s -- --install
```

Do this **before you start**, not in the middle of a run. A run in progress is tied to the
plan it began with, and the tool refuses a plan whose step list does not match the binary
performing it — which is a guard rail, not an inconvenience.

Version numbers are CorePanel's own release numbers, and the tool is only rebuilt in the
releases that changed it, so the list below has gaps. A version that is not here changed
nothing in the transformation.

---

## 1.6.5 — 4 September 2026

- **Your resellers now arrive with the limits they were sold on.** cPanel writes what a
  reseller may sell into `/var/cpanel/reseller-limits.yaml` — an account count, a disk
  total, and whether they may oversell that disk — and until this build nothing read it. A
  reseller was created from the accounts they owned and took CorePanel's defaults, which
  mean *unlimited*: a provider capped at 25 accounts and 50 GB on the old panel woke up
  able to sell without limit, on the very servers that arrived with those two numbers
  already written down. There is a new PREPARE stage, **"File the resellers this server
  sells through"**, and it runs before the accounts on purpose — an account's owner is
  created the moment that account is registered, so a reseller filed afterwards would have
  spent the whole import uncapped. A reseller who had limits but no accounts comes across
  too. Both ceilings are enforced from the first account charged against them.

- **A reseller's own hosting plans are now theirs.** cPanel has no owner column for a
  package: it puts the owner in the *name*, as `acmehost_starter`. Filing a whole server's
  plans under one seller therefore kept the prefix and lost the owner — every reseller's
  plans belonged to the server owner, were not theirs to edit, and the Packages screen
  showed one operator owning a list of `acmehost_*` rows. Each plan whose prefix names a
  reseller this server now has is filed under that reseller, with the prefix removed: it
  becomes their `starter`. Two resellers' `starter` and yours are three different plans,
  because a plan is unique per owner and not per server. A prefix matching no reseller is
  left exactly as it is — `gold_plus` on a server with no reseller called `gold` is a plan
  somebody named with an underscore, and moving it would take one of your own away.

- **What a cPanel reseller carries and CorePanel does not model is printed, per reseller,
  instead of vanishing.** Three things: the per-reseller privilege list, the total
  bandwidth ceiling, and the restriction on which packages they may sell. The privileges
  matter most, and in the opposite direction from everything else on this page — a
  reseller who could not terminate accounts or touch DNS on cPanel *can* here, because a
  CorePanel reseller is all-or-nothing within their own accounts. It is the one thing a
  migration widens rather than narrows, and now it is on screen while you are watching the
  run.

- **And the privilege list is now kept, so it comes back when it can still change your
  mind.** Printing it during the run is not enough on its own: a reseller that arrives has
  no panel login and can do nothing at all, so nothing actually widens until somebody gives
  it one — days later, with the run long scrolled away. The set the source granted is
  stored on the reseller, `corepanel admin create --seller acmehost` answers with it at the
  moment that login is handed over, and `corepanel seller show acmehost` prints it
  afterwards. The administrator is still created: it is a note, not a refusal, because
  widening those privileges may well be what you intend. A reseller cPanel granted
  *everything* is never mentioned — nothing was withheld from them to begin with.

- **A billing system can provision on behalf of a reseller.** WHM's `createacct` takes an
  `owner=`, which is how a provider's own WHMCS creates an account *for* one of their
  resellers, and the compatibility layer used to read every parameter except that one —
  silently landing all of those accounts on the server owner. It is honoured now, it
  counts against that reseller's ceilings, and an `owner` naming nobody on the server is
  refused instead of being quietly reassigned to you.

- **A plan written by an earlier build is refused, as always, and this is one of the times
  it matters.** The new stage means older plans do not list it; re-run `plan` before you
  start. A run already under way is unaffected — the guard only stops a plan whose step
  list is missing something the binary would otherwise skip in silence.

  This build writes plan schema 10.

**If your server was transformed before this:** its resellers are here, with their accounts
and their ownership intact, and with **no ceilings** — they can sell as much as they like.
Their plans are on your own account, still called `acmehost_starter`. Nothing in a newer
build reaches back to fix either, and the source is usually gone by now.

The plans can be left as they are: accounts stay attached to them and keep working, and a
re-run of the import still finds them there. Moving one is a rename in the panel plus a
change of owner, and only worth it if the reseller needs to edit their own plans.

The privilege lists are gone with the source panel and no build can recover them. What is
worth knowing is the rule itself: any reseller on that server whose cPanel privileges were
restricted now has all of them within their own accounts, and the way to check who has a
panel login at all is `corepanel admin list --all`.

The ceilings are the part worth fixing, and it is two commands. Set the numbers from the
figures the old panel had:

```bash
corepanel seller list
corepanel seller update acmehost --max-accounts 25 --max-quota 51200
```

`--max-quota` is in MB, and `0` on either one means unlimited. Add `--overselling` for a
reseller who was allowed to oversell disk on cPanel. `corepanel seller show acmehost` then
prints what they have sold against each ceiling, which is how you check the numbers are the
ones you meant.

## 1.6.4 — 4 September 2026

- **A transformed server keeps talking to the outside world from the IPv4 its licences
  were issued against.** The cutover stands your firewall down — pxf, CSF, whichever one
  is in front of the machine — and on a dual-stack server that quietly changes something
  nothing on the box announces: with no policy in `/etc/gai.conf`, the C library prefers
  IPv6 to IPv4 for every destination that offers both. A server that had been seen at its
  IPv4 for years starts being seen at its IPv6 on the first connection after the window,
  and everything licensed against the address — WHMCS, Softaculous, LiteSpeed, JetBackup,
  Imunify — begins failing its licence check. It does not fail at the cutover, which is
  what made it hard to place: each product runs on a cached verdict for hours, so the
  first symptom arrives in the middle of the night, on a server whose migration went
  perfectly. The cutover now writes that preference back, in a marked block, immediately
  after the firewall goes down and before the PHP pools start — the order matters, because
  the C library reads the file once per process. A server with no IPv6 route out is left
  untouched, and so is one whose `/etc/gai.conf` already says something: if you have set a
  policy of your own, the run tells you what to re-check instead of overruling you. The
  block is delimited, so a rollback takes back exactly what the run wrote — and removes
  the file only if the run is the one that created it.
- *If your server was transformed before this:* it is still preferring IPv6, and any
  licence tied to your IPv4 will fail at its next revalidation if it has not already. Put
  the preference back by hand and restart what is running, which takes a minute:

  ```bash
  echo 'precedence ::ffff:0:0/96  100' >> /etc/gai.conf
  systemctl restart 'php*-php-fpm'
  curl -s https://ifconfig.me   # must answer your IPv4, not an IPv6 address
  ```

  Then make each product check its licence again rather than waiting for it — in WHMCS,
  that is one visit to `/admin/` once the preference is in place. A licence that has
  already been marked invalid comes back on its own when the address it sees matches the
  one it was issued for; you only need your vendor's reissue if the address itself has
  genuinely changed.

- **Applications that send mail unencrypted to their own server go on working.** cPanel's
  Exim offers AUTH on port 587 without asking for TLS first; CorePanel's installer does
  the opposite, because requiring TLS is the right default for a server nobody has
  migrated anything onto. In between sits every application already on the machine — a
  billing system, a WordPress plugin, a shop — configured against Exim's behaviour, and
  from the cutover onwards each one stopped sending mail with "SMTP Error: Could not
  authenticate." Nothing was wrong with the credentials: Postfix simply does not
  advertise AUTH until the session is encrypted, so the client found none and gave up.
  The only trace is a connection that says EHLO and hangs up, which is why the first
  server this happened on went a day without an explanation while its payment
  confirmations failed. The cutover now **reads what your mail server advertises before it
  stops it**, and configures Postfix to match: a server whose Exim allowed AUTH in the
  clear keeps allowing it, and one that already required TLS stays strict. STARTTLS is
  offered either way, so mail clients go on encrypting. A CorePanel server installed from
  scratch is unaffected — the strict default stands there.
- *If your server was transformed before this:* its applications are still failing to
  send. To put it back the way your Exim had it:

  ```bash
  postconf -P 'submission/inet/smtpd_tls_security_level=may'
  systemctl reload postfix
  ```

  The better end state is to move those applications onto STARTTLS and run the same
  command with `encrypt`; this is the switch that buys you the time to do it.

## 1.6.3 — 3 September 2026

A build whose changes are all in the code the tool shares with the panel, and all of them
land on the mail of a server being transformed.

- **A mailbox cPanel had suspended arrives still receiving mail, with only its sign-in
  shut.** cPanel suspends a mailbox by locking its password hash: the address goes on
  accepting mail and nobody can read it until the login is opened again. CorePanel had a
  single switch for both halves, so the import had to pick one — and it picked shut, which
  meant every suspended mailbox answered `550 User doesn't exist` from the moment of the
  cutover. Mail cPanel had been accepting the day before was refused at the door, for
  exactly the addresses whose owner was most likely to be away. A mailbox now carries the
  two halves separately: the import writes delivery open and sign-in closed, `corepanel
  mail list` reports that state as `login_disabled`, and the panel draws it in amber rather
  than as either healthy or suspended.
- *If your server was transformed before this:* those mailboxes are still shut for
  delivery, and still bouncing. `corepanel mail activate <address>` reopens them — **both**
  halves, so the sign-in cPanel had closed comes back with it. If it has to stay closed,
  give the mailbox a new password its owner does not have.

- **A forwarder that also keeps a copy in its own mailbox is imported instead of being
  skipped.** cPanel expresses that arrangement — a role address somebody still reads while
  a manager or an archive gets a copy — by listing the address among its own destinations,
  and CorePanel refused it outright, for the reason any *other* forwarder on a mailbox's
  address is still refused: it would divert every message away from the mailbox. So each
  one was dropped, named in that account's import report as a skipped forwarder and nowhere
  else. The mailbox went on receiving and every other destination quietly stopped getting
  its copy — the kind of loss nobody reports for weeks, because the person who notices is
  the one who was only ever meant to be reading along.
- *If your server was transformed before this:* the forwarders were not created and nothing
  has created them since. `corepanel mail forwarder set <address> <address> <other
  destination>` — the source listed among its own destinations — restores one, or add it in
  the panel with the address itself among the destinations.

- **The zones a transformation publishes carry the account's DKIM key.** The cutover's DNS
  step has been reporting *"published without the account's DKIM key: outbound mail is
  signed and the world cannot verify it"* for every zone on every server, and it was
  telling the truth. Two defects held each other up: sys generated the key under the
  domain's own selector and then read the record back under the service-wide one,
  discarding the resulting error and returning an empty value; and core refused any TXT
  value over 255 characters — which is the limit on a single character-string inside a TXT
  record, not on the record, a sequence of them — while a 2048-bit key is about 400. The
  first made the second invisible.
- *If your server was transformed before this:* the zones are published without the key and
  the mail leaving that server is signed with a key nobody can look up.
  `corepanel mail deliverability` reports the coverage; rotating the key from **Email →
  DKIM** in the panel now publishes the record.

- **Port 465 speaks TLS, and a new sender waits five minutes rather than four hours.** Both
  come from the installer the run drives, and a freshly transformed server is where they
  bite hardest. The submission services were configured by line position, which left every
  option in the `smtps` block commented out — `smtpd_tls_wrappermode` included — so implicit
  TLS failed its handshake while 587 kept working and hid it. Implicit TLS is what cPanel
  hands out, so it is what every migrated mail client on that server is already set to.
  Greylisting, meanwhile, deferred every unknown sender for four hours against Rspamd's own
  five-minute default: measured on a migrated server at 34 soft rejects against 19
  deliveries in the first fifteen hours, with one real sender retrying for exactly 4h00m
  before it got through. cPanel's Exim does not greylist at all, so on the day after a
  migration that reads as *CorePanel is eating our mail*.
- *If your server was transformed before this:* both are server-wide settings the installer
  writes once, so an existing server keeps what it was given. Upgrading the packages does
  not rewrite them.

- **ACME orders stop dialling cPanel's PowerDNS.** The DNS-01 provider is recorded when a
  domain is first handed to the certificate manager and never re-read, and during a
  transformation every domain is registered while `/etc/pdns/pdns.conf` still belongs to
  cPanel — so once the cutover installed our own PowerDNS, every certificate order after it
  kept talking to an API that no longer existed. sys now reconciles the managed domains
  against the nameserver in front of it when it starts, which the cutover makes it do
  exactly once, at the right moment. A related fix stops the *first* transient failure from
  parking a domain in `max_retries_exceeded` with nothing left to revive it.

## 1.6.2 — 3 September 2026

- **Hosting packages are imported, and before the accounts.** The documentation has always
  promised packages among what carries across, and the machinery to import them existed,
  was registered and was tested — but nothing ever called it, so a transformed server
  ended up with no packages and every account attached to none. Two things had to change
  together: the packages are read by the tool, which runs as root and can read cPanel's
  `0700` package directory, and they are filed **before** the accounts, because an account
  is joined to its package by name at the moment it is registered. A server whose accounts
  were all made by hand has no packages, and that is not a failure.
- *If your server was transformed before this:* filing the packages afterwards does not
  attach the accounts that are already there, and re-applying a package would overwrite
  limits that came from the account rather than from its plan. Leave them, or set the
  package per account in the panel.

## 1.6.1 — 2 September 2026

- **The panel's login is handed over before the health gate, not after.** By the time the
  gate asks its questions the server is already CorePanel's — the sites are being served
  and the accounts are registered — so a gate that stopped over one encoded site used to
  end the run with the administrator's password never generated: a transformed server
  nobody could sign in to, with the rollback as the only move left. The step now runs at
  the end of the cutover, and the credentials are printed last on the screen whether the
  run finished or stopped. It sets a password only when there is none, so a second pass
  never locks out an administrator who has already changed it.

## 1.6.0 — 2 September 2026

- **Every site is read before the window opens, and compared afterwards.** A new first
  step of the cutover asks every site for its homepage while cPanel is still serving it
  and writes down what came back. The health gate then asks the better question — *is this
  the same page?* — because "the site answers" is not "the site works": an ionCube-encoded
  application missing its loader answers **HTTP 200** with a notice where the page should
  be, and a gate reading status codes called that a healthy site. It also means a site that
  was **already** broken before the run is named at the start of the window instead of
  being blamed on the transformation.
- **PHP fatals the response cannot show are reported.** With `display_errors` off, a fatal
  error after the output buffer has flushed leaves an HTTP 200 with the page cut short
  mid-sentence — invisible to any check that reads status codes or page sizes. The gate now
  reads the account's own PHP error log across the request and reports what landed there,
  with the file and the line. Always a warning, never a failure: the code is the customer's
  own, unchanged by the run, and it was throwing the same thing on cPanel. It also reports
  a log the account cannot *write*, since an empty log and an unwritable one look
  identical.
- **The PHP versions and extensions your sites actually run are installed during PREPARE.**
  Before, an account was given the PHP version CorePanel happened to have, falling back to
  the newest installed — so sites running cPanel's 8.1 came back on 8.4, three minor
  versions up, with nothing saying so. Now every version in use on the source is installed,
  sites whose vhost says `inherit` are resolved through cPanel's own default, and each
  interpreter's extensions are compared and the difference installed — `imap`, `soap`,
  `bcmath`, `posix` and, above all, the **ionCube Loader**. A version or extension that
  cannot be installed is named, with the sites it affects, while cPanel is still serving
  them.
- **Mailboxes cPanel had suspended no longer fail the cutover.** They were counted as
  mailboxes that failed to log in, which is exactly what a suspended mailbox is supposed
  to do.
- **cPanel's `dnf` exclusion is cleared at the cutover, not at cleanup.** With `php*` still
  excluded, every CorePanel PHP package looks like it does not exist — a broken repository
  that is really a one-line exclusion. The rest of that line, which protects cPanel's own
  mail and FTP builds, stays until the cutover, and a rollback restores all of it.
- **The panel says cPanel is still installed.** After a transformation the dashboard carries
  a card naming how many cPanel packages are left and roughly what they occupy, with the
  cleanup command ready to copy. It disappears by itself once cleanup has run. See
  [Dashboard](https://www.corepanel.net/docs/dashboard#cpanel-is-still-installed).

## 1.4.6 — 31 August 2026

- **The contact address and the nameserver addresses are adopted too.** A green
  transformation still opened the panel's initial configuration assistant, asking for a
  contact address, a hostname and nameservers it had been handed half an hour earlier —
  the panel counts a configuration with a blank administrator email or an unaddressed
  nameserver as incomplete. Both are now taken from the panel being replaced. Each
  nameserver's address is resolved from the delegation the server has been serving all
  along, so a second nameserver that lives on another machine stays there instead of being
  flattened onto this one. The address is **recorded, not acted on**: it does not become
  the ACME contact and it does not rename the administrator until you confirm it in the
  panel.

## 1.4.5 — 31 August 2026

- **A transformed server now has a panel login.** A transformation never passes through
  `corepanel system init`, so the administrator existed with no password at all: a run
  could verify every domain, mailbox, database and zone and finish on a panel nobody could
  sign in to. The run now generates the first password, prints the address, the user and
  the password on screen, and writes the password to `/root/.corepanel_password` (`0600`) —
  the same file a hand-installed CorePanel uses. It never overwrites a password that has
  already been set.
- *If your server was transformed before this:* `corepanel system init --admin-email
  you@example.com --no-interactive` prints the address, the user and a password. Leave
  `--domain` out — the transformation already set the panel domain.

## 1.4.4 — 31 August 2026

- **The clock is on screen while the sites are down.** Steps now say "6/13" rather than
  "6.", the plan's estimate for a step is printed **before** it runs rather than after,
  and from the moment the sites go down the tool shows how long they have been down and
  how much of the booked window is left. Resuming into a half-finished cutover says which
  outage it is measuring instead of restarting the clock at zero.
- **The outage is declared by the step that actually opens it.** "The visible clock starts
  here" was written on the step that stops Apache, which is only true when taking over the
  databases does not restart MariaDB. Where it does, every database-backed site had been
  serving an error since the step before — for around two minutes — while the run said the
  window had not opened yet.

## 1.4.3 — 31 August 2026

- **The published downtime matches the measured downtime.** The tool and the documentation
  said "minutes rather than hours" for a window measured at 28 seconds — ten times worse
  than the truth, told to exactly the reader who is looking for a reason not to migrate.
  Both now say seconds, publish the conditions (45 accounts, 51 domains, a 2-vCPU server)
  and state the scaling law: the window grows with the number of *files*, not with the size
  of the data.

## 1.4.2 — 31 August 2026

- **Pointing the tool at a server that is not running cPanel says so**, instead of
  reporting what it expected to find.

## 1.4.1 — 30 August 2026

- **A rollback gives back mail, FTP and DNS.** Reversing a cutover restored the web and the
  databases but left mail, FTP and DNS with CorePanel's daemons — cPanel's own builds of
  those same services had been removed during the window. They are now reinstalled and
  cPanel rebuilds their configuration itself, so what comes back is a **whole** cPanel.

## 1.4.0 — 30 August 2026

The release that made the transformation a single guided operation rather than a set of
stages an operator drives by hand. It followed the first end-to-end run against a real
cPanel server, and most of it is that run's findings.

- **`corepanel-transform` with no arguments is the whole transformation.** It walks the
  five stages in order, printing what each will do to *this* server — what goes offline,
  for how long, and whether it can be reversed — and waiting for an answer before each one.
  The subcommands are still there for automation.
- **The plan is priced from a measured run.** Every estimate was repriced against real
  timings, and each constant records what it measured. Where the real cost was never
  exercised, the old figure was kept and says so.
- **VERIFY became a record rather than a second gate**, reporting per account against the
  inventory taken before anything happened.
- **The rollback became a command.** `corepanel-transform rollback` works the procedure out
  from the server in front of it rather than replaying a file written a week ago, gives
  cPanel its scheduled work back, and stops the panel last, once cPanel is answering again.
  It refuses — naming the difference — when a mailbox, an FTP login or a password has
  changed under CorePanel since the cutover, rather than discarding it quietly.
- **`cleanup` is the only one-way door, and the guided run never offers it.** It refuses
  unless verification passed and something is answering on ports 80 and 443 right now.
- **The health gate probes the server from outside** — an HTTP request per site, a mailbox
  login, a database login, an SOA query per zone, an FTP login — instead of asking systemd
  whether units are running. It also stopped asking the WAF whether the cutover worked.
- **Certificates carry across**, and a domain with no certificate name of its own is judged
  over HTTP.
- **Where every domain actually points is inventoried before anything runs.**
- **The three decisions the plan makes now fail closed** rather than assuming the
  comfortable answer.
- **The WHM API credentials are carried across as digests**, so the plaintext never leaves
  the billing system that has been sending it for years, and the API is left closed.
- **The host firewall is turned off rather than left to the administrator**, and
  third-party products are judged by who acts on the server rather than by a severity
  rating.

## 1.3.6 — 27 August 2026

The first release in which PREPARE and the cutover ran end to end on a real cPanel server.
Everything here exists because that run found it, and none of it is reproducible from a
test fixture: several of the fixes exist only because there was something else on the
machine — cPanel's own RPMs, its MySQL credentials, a masked unit, an unprivileged uid.

- **Accounts are registered in place**, with their uids, their password hashes and their
  home directories exactly where they are.
- **Database users are adopted rather than re-created**, because the MySQL being taken over
  is still cPanel's, and so is its root login.
- **An account that landed short is repaired** — the run re-examines it and creates only
  what is missing, instead of skipping it or starting again.
- **The DNS zones are published as the cutover's ninth step**, with the same records on the
  same port, and DNS is deferred the way the home directory mode is.
- **The home directories are tightened and the quotas applied inside the window**, because
  doing either earlier would take live sites offline or suspend a live account
  mid-afternoon.
- **The cutover's unit lists were corrected against a real cPanel server**, and a masked
  web server is treated as an instruction rather than as a failed reload.
- **The server's own address, hostname and nameservers are adopted from cPanel**, which is
  why the panel opens on its dashboard rather than on the configuration assistant.

## 1.3.0 – 1.3.5 — 18 to 26 August 2026

- **PREPARE gained its execution engine and its preflight** (1.3.4), and the installer is
  driven from the install step rather than by hand.
- **The check's verdict is colour-coded and agrees with its own numbers** (1.3.2), and the
  build date is stamped into the binary.
- **`plan` gained a verdict**, and names the domains that have no zone file (1.3.4).
- **Hosting packages and the limits accounts actually ran under are read**, and an account
  is attached to its package rather than only to its numbers (1.3.0).
- **An account is imported as closed as the source left it** — a suspended cPanel account
  arrives suspended (1.3.1).
- **The database version is read from the running server** rather than from the stamp in
  the data directory (1.3.0).
- **Disabled FTP is no longer reported as a source the tool could not find** (1.3.3).
- **The end of the check says what happens next** instead of naming a command (1.3.5).

## Before 1.3.0 — 28 July to 10 August 2026

The tool started as the read-only migration check (0.5.0) and grew the `plan` command in
the same release. What is worth recording from that period is mostly what was taken *out*:
the report upload, because the tool is the conversion rather than a lead form, and an
`ELEVATE` phase, because upgrading an operating system is cPanel's own `elevate-cpanel`
job and not this tool's. The rest were scoring corrections — telling ImunifyAV apart from
Imunify360, not charging a server for running JetBackup, warning when one account is split
across PHP versions.

---

## Related

- [Transforming a cPanel server](https://www.corepanel.net/docs/cpanel-transform) — the tutorial, and the detail
  behind every stage
- [The cPanel migration check](https://www.corepanel.net/docs/migration-check) — the read-only stage, and what each
  finding means
- [Coming from cPanel](https://www.corepanel.net/docs/from-cpanel) — this route compared with importing onto a new
  server
