Skip to content

Blog ·

Migrate cPanel to Virtualmin: what transfers, and what does not

What Virtualmin's own cPanel import takes over, and the two traps that land in the first week: the username it keeps, and the quota it cannot see.

By Provibr

If you want to migrate cPanel to Virtualmin, the good news is that Virtualmin ships the import itself: there is a documented command that reads a cPanel backup and creates a virtual server from it. The rest of this page is the part the command does not cover. The vocabulary changes underneath you, your billing system is holding a username that may not survive the trip, and there is a disk-quota problem on both sides of the move, for two different reasons.

Provibr connects to cPanel and to Virtualmin, and a customer on either pays us the same. We have no reason to talk you into this move. We also have not run your data migration, and nothing below claims to have tested anyone's conversion tooling. What we did measure is how both panels behave through their APIs, because we built integrations against them.

Virtualmin's import, in its own words

Virtualmin distinguishes two operations, and picking the wrong one wastes an afternoon.

Virtualmin's own FAQ for cPanel users separates Migrate Virtual Server from Transfer Virtual Server: migrate is for importing a backup file produced by another panel, transfer is for pushing a virtual server from one Virtualmin system to another. It also maps the vocabulary: what cPanel calls a domain is a Virtual Server, an add-on domain is roughly a sub-server, and a parked domain is comparable to an alias.

The command-line form is migrate-domain, and its documented surface tells you most of what you need to plan around.

migrate-domain takes a --type of cpanel, plesk or directadmin and a --source that can be a local file, an FTP or SSH destination, or an S3 bucket. The original username and password are used unless overridden with --user and --pass; the documentation notes that some migration formats do not contain the password, in which case --pass must be given or an error is displayed. A --template selects which Virtualmin template the new virtual server is created from, and the default settings template is used when none is given.

Read that last sentence slowly. The template is a parameter, not something the backup carries, so the shape of the destination account is a decision you make per import. It is also the decision that determines the limits the account ends up with. There is also a --test flag: use it on a real customer's backup before you plan the batch, not on a fresh account you made to try the tool.

The flag that rejects the migration outright

The one documented failure mode worth putting on a checklist is about addresses.

If the original server had a private IP address, the documentation states that either --ip or --allocate-ip should be used to create an IP for the new virtual server, and that failing to do so may cause the migration attempt to be rejected, or features of the migrated server such as its SSL virtual website not to work properly.

A partial failure is worse than a rejection here: "the site is up but HTTPS is broken" is a state you can migrate a hundred accounts into without noticing.

The username: both panels agree, your records may not

Both panels enforce a shape for the Linux user behind an account. We measured both while building integrations, and the shapes are not the same size.

cPanel / WHMVirtualmin
Pattern^[a-z][a-z0-9]{0,15}$^[a-z_][a-z0-9._-]{0,31}$
Length1 to 161 to 32
Hyphenrefusedallowed, and normal
Dotrefusedallowed
Where the name comes fromyou choose itderived from the domain
Capitalssilently lowercasedlowercased before use

Virtualmin's rule is the wider of the two, so every legal cPanel username is also a legal Virtualmin username. That is the reassuring half. The other half is that the two panels disagree about where a username comes from at all. cPanel treats it as an independent handle you pick; Virtualmin derives the Unix user from the domain, so my-client.example.com becomes my-client, which is exactly why hyphens are ordinary there and refused on cPanel.

For a migration that matters in a specific way. migrate-domain keeps the original username unless you tell it otherwise, so imported accounts arrive carrying their cPanel names. Anything you create afterwards through the panel's normal flow gets a domain-derived name instead. So a year from now your fleet has two naming conventions in it, split by whether the account predates the move, and any script that assumes it can work out the username from the domain will be wrong for exactly the older half.

A related trap on the way out, measured on WHM: it accepts a username containing capitals, creates it in lowercase, and reports success without mentioning the change. Build the inventory for your migration by reading the source server, not by exporting your own records.

The quota problem exists on both sides, for different reasons

This is the one that turns into tickets in week one.

On cPanel, a server only enforces disk quotas when the filesystem the accounts live on carries quota support. Without it WHM accepts the package, accepts the number and enforces nothing. We measured that on a running WHM 11.136 server: an account moved onto a package with a 2 GB quota kept reporting its limit as unlimited, and the per-account disk figures came back empty. If that is the state of your fleet, some accounts have grown well past what you sold them.

On Virtualmin, the same underlying dependency shows up as missing data instead of missing enforcement. Virtualmin reports quota and usage fields only when the administrator has enabled filesystem quotas; on a fresh install they are off (quotaon -p / reported off on the box we measured), and then list-domains returns no quota field at all. Our agent treats those fields as optional for exactly that reason: it reports what is there and does not invent zeros, so a usage graph shows nothing rather than showing a flat line that reads as "no usage".

So the sequence that avoids a bad fortnight is: check whether quotas are enforced on the cPanel side before you plan the move, decide what to do about the accounts that are over, and turn filesystem quotas on at the destination before the first import rather than after the first complaint.

What is not in any backup file

Beyond the data, four things move by hand or not at all.

  • Whatever your billing system stores as the account identifier. After the move it is still a username, but if any of them changed, the reference is dead. And a dead reference in a dunning run does not throw an error: it suspends nothing.
  • Anything that called cPanel's API. Customer-facing scripts, hooks and third-party plugins have no Virtualmin equivalent by default.
  • Bandwidth counters. Monthly totals the server resets itself. The first month after a migration reads low on the new panel and high on the old one.
  • Suspension reasons. Plan to re-record why anything currently suspended is suspended.

And one operational fact about the destination that surprises people: Virtualmin's hosting capability is not Webmin. Plain Webmin manages a Linux machine (users, services, packages) and has no notion of a hosting account at all. The module that knows about domains, plans and quotas is Virtualmin, and on a box without it the remote endpoint answers exactly like a made-up module name: 404.

Running it as a product afterwards

The migration ends the day the last account is off cPanel. Selling on the new panel starts then and does not.

Provibr's Webmin and Virtualmin integration is live. An agent inside your own network dials outward to us and talks to Virtualmin's remote API, so nothing is installed on the panel and no Webmin port faces the internet. Accounts are created with a domain, a contact address and one of the plans defined on your own server; they can be suspended, resumed, moved to another plan and removed, and existing accounts are imported only when you tick them, so a server with four hundred accounts on it becomes something you adopt rather than something you rebuild.

Three limits, stated plainly because they are the ones people ask about after the move. There is no console, no reinstall and no OS catalogue: those are properties of a machine, and the machine here is the panel itself. Usage graphs exist but depend on the quota situation above. And the TLS fingerprint field is required rather than optional for this panel, because a standard Webmin install presents a self-signed certificate and the credential involved is a full Webmin password over Basic auth. Making the pin optional would mean the normal installation is either unpinned or unconnectable.

Virtualmin's documented behaviour was read from virtualmin.com on 1 September 2026 and is quoted with its source above. The username patterns, the WHM capitalisation behaviour and the quota findings were measured against running cPanel and Virtualmin servers while building the Provibr integrations. No claim is made about the results of anyone's data migration, which we have not run.

Start with one host and one agent

Create an account, install the agent with a single command and connect your first Proxmox host. The trial runs for 14 days and asks for no payment details.