CloudPanel migration: move sites from CloudPanel to Jabali Panel

Last updated

The CloudPanel ingest path. Status: production-supported. SSH pull-based, like Plesk and CyberPanel — no archive to produce on the source.

How it differs from the archive sources

SourceDiscoveryData transfer
cPanelUpload cpmove-<user>.tar.gzArchive
DirectAdminUpload da backup-user tarballArchive
HestiaCPUpload v-backup-user outputArchive
PleskSSH, run plesk binStreamed
CyberPanelSSH, read cyberpanel MySQL DBStreamed
CloudPanelSSH, read SQLite DB via sqlite3 CLIStreamed
WHMUpload cpmove dumpArchive

CloudPanel keeps its entire inventory in a single SQLite database at /home/clp/htdocs/app/data/db.sq3. The pipeline reads that database directly over SSH:

  • SELECT * FROM site — one row per site
  • SELECT * FROM php_settings — per-site PHP overrides
  • SELECT * FROM database — MariaDB / MySQL databases
  • SELECT * FROM user — site users

clpctl is used only for database credentials and mysqldump invocation. No mutating call.

Web-only: no mail server on the source

Unlike CyberPanel and Plesk, CloudPanel has no mail server. The manifest’s mailbox area is always empty; there’s no mail migration phase. Sites that need mail typically use an external provider (Google Workspace, Zoho, Migadu, Fastmail); that flow continues unchanged after DNS.

To add mail on the destination, provision mailboxes in Jabali Panel’s Stalwart after the site migration completes. See Mail setup.

Prerequisites

  • SSH access to the source CloudPanel host. Root or a sudo-capable user with read access to /home/clp/htdocs/app/data/db.sq3.
  • Credentials: SSH password or private key.
  • Source CloudPanel version: any recent CloudPanel (2.x) on Debian 11+ or Ubuntu 22.04+.
  • clpctl available on the source PATH.

Operator workflow

  1. Add the source in /jabali-admin/migrations:
    • Kind: cloudpanel
    • Host: <source-fqdn-or-ip>
    • Port: 22 (or custom)
    • Auth: SSH password or private key
  2. Discover — the panel connects via SSH and reads SELECT domain_name FROM site. Every site becomes an account row.
  3. Select sites — pick one, several, or all.
  4. Analyze — reads site config, PHP settings, databases, site users. No writes.
  5. Restore — synthesizes a cpmove-shape archive on the destination, ingests each asset. Per-phase progress in the UI.
  6. Repoint DNS at the registrar.
  7. Issue SSL via the per-domain SSL toggle.

What gets migrated

AssetSourceBehavior
Sitessite tableBecome panel Domain rows; docroot preserved.
Site usersuser tableRecreated on destination; UID may differ.
PHP settingsphp_settings tableApplied as per-domain PHP overrides.
PHP versionsite.php_versionMapped to the closest available Jabali PHP version.
MariaDB / MySQL databasesdatabase table + mysqldumpRestored with users and hashes preserved where compatible.
Node.js sitessite.type='Reverse Proxy'Translate to Jabali Node.js sites with port + entrypoint preserved.
Python sitessite.type='Python'Translate to Jabali Python sites.
Static sitessite.type='Static'Become nginx static Domain rows with the same docroot.
SSL certificatesReissued via Let’s Encrypt on destination.
Home directory contentsStreamed via SSHCopied to /home/<user>/.

What is not migrated

  • Mail — CloudPanel has no mail server.
  • Cloudflare integration. Apply CDN at Cloudflare directly after DNS repointing.
  • FastCGI cache configuration. Replaced by Jabali Cache for WordPress; nginx fastcgi_cache blocks are re-rendered from the Jabali template.
  • Remote backup jobs (S3, Backblaze). Re-model in Backups with the same destinations.
  • CloudPanel-native WAF. Replaced by AppSec + CrowdSec.

Troubleshooting

Discovery fails with sqlite3: command not found. CloudPanel bundles sqlite3 in its own path. Log into the source and confirm sqlite3 /home/clp/htdocs/app/data/db.sq3 ".tables" runs; if not, apt install sqlite3 on the source.

MySQL restore fails: password mismatch. CloudPanel stores DB credentials in a secret keyring, not in the SQLite DB directly. The pipeline uses clpctl to fetch them. If clpctl is not on PATH, the credential fetch fails and the restore falls back to generated passwords — update the app connection strings on the destination.

A Node.js site restored but fails to start. CloudPanel’s Node.js reverse-proxy port might collide with a panel-managed service on the destination. Check the destination’s /etc/systemd/system/jabali-*.service files for port conflicts; adjust the Node.js site’s port in the panel UI.

Site works but images 404. The site’s docroot includes a symlink to a shared media directory outside the site tree. The archive migration follows symlinks but does not migrate targets outside the site directory. Manually copy the shared media directory after Restore.

Audit

Standard per-phase audit rows.

Frequently asked questions

Can I migrate from CloudPanel to Jabali Panel?
Yes. Jabali Panel's CloudPanel pipeline connects over SSH and reads the source's SQLite config database at `/home/clp/htdocs/app/data/db.sq3` directly. Discovery is strictly read-only — plain `SELECT` statements via the `sqlite3` CLI. Restore synthesizes a cpmove-shape archive on the destination and hands off to the cPanel restore path.
Are mailboxes migrated from CloudPanel?
No — CloudPanel is web-only and has no mail server, so there are no source mailboxes to migrate. If your CloudPanel sites use an external mail provider (Google Workspace, Zoho, Migadu), that mail flow continues unchanged after DNS repointing since MX records are separate from the panel move. If you want first-class mail hosting after migrating, Jabali Panel ships Stalwart — provision mailboxes on the destination after the site migration completes.
What credentials does the CloudPanel pipeline need?
SSH access to the source CloudPanel host. Root or a sudo-capable user works — the pipeline needs read access to `/home/clp/htdocs/app/data/db.sq3` and to invoke `clpctl` for database credentials + dumps. SSH password or private key both work.
What tables does the CloudPanel pipeline read?
site (per-site config: domain, docroot, PHP version, site user), php_settings (per-site PHP-FPM overrides), database (MariaDB / MySQL databases), user (site users). All reads are plain read-only `SELECT` statements via the `sqlite3` CLI over SSH. `clpctl` is used only for DB credentials and dumps; `mysqldump` produces the actual database content. No mutating command runs against the source.
What does CloudPanel's Node.js and Python site type translate to?
Jabali Panel ships panel-native Node.js and Python runtimes with process management. CloudPanel Node.js sites (Reverse Proxy + Node) translate to Jabali Node.js sites; CloudPanel Python sites translate to Jabali Python sites with the equivalent WSGI/ASGI setup. The pipeline preserves the port number, entrypoint, and environment variables where they translate.
What CloudPanel features do not migrate?
CloudPanel's built-in FastCGI cache configuration is replaced by [Jabali Cache](https://wordpress.org/plugins/jabali-cache/) for WordPress. CloudPanel's Cloudflare integration is not migrated — apply CDN configuration directly at Cloudflare after DNS repointing. CloudPanel remote backups (S3, Backblaze) do not migrate as jobs; re-model in the panel's [Backups](./backups.md) with the same destinations.