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
| Source | Discovery | Data transfer |
|---|---|---|
| cPanel | Upload cpmove-<user>.tar.gz | Archive |
| DirectAdmin | Upload da backup-user tarball | Archive |
| HestiaCP | Upload v-backup-user output | Archive |
| Plesk | SSH, run plesk bin | Streamed |
| CyberPanel | SSH, read cyberpanel MySQL DB | Streamed |
| CloudPanel | SSH, read SQLite DB via sqlite3 CLI | Streamed |
| WHM | Upload cpmove dump | Archive |
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 siteSELECT * FROM php_settings— per-site PHP overridesSELECT * FROM database— MariaDB / MySQL databasesSELECT * 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+.
clpctlavailable on the source PATH.
Operator workflow
- Add the source in
/jabali-admin/migrations:- Kind:
cloudpanel - Host:
<source-fqdn-or-ip> - Port:
22(or custom) - Auth: SSH password or private key
- Kind:
- Discover — the panel connects via SSH and reads
SELECT domain_name FROM site. Every site becomes an account row. - Select sites — pick one, several, or all.
- Analyze — reads site config, PHP settings, databases, site users. No writes.
- Restore — synthesizes a cpmove-shape archive on the destination, ingests each asset. Per-phase progress in the UI.
- Repoint DNS at the registrar.
- Issue SSL via the per-domain SSL toggle.
What gets migrated
| Asset | Source | Behavior |
|---|---|---|
| Sites | site table | Become panel Domain rows; docroot preserved. |
| Site users | user table | Recreated on destination; UID may differ. |
| PHP settings | php_settings table | Applied as per-domain PHP overrides. |
| PHP version | site.php_version | Mapped to the closest available Jabali PHP version. |
| MariaDB / MySQL databases | database table + mysqldump | Restored with users and hashes preserved where compatible. |
| Node.js sites | site.type='Reverse Proxy' | Translate to Jabali Node.js sites with port + entrypoint preserved. |
| Python sites | site.type='Python' | Translate to Jabali Python sites. |
| Static sites | site.type='Static' | Become nginx static Domain rows with the same docroot. |
| SSL certificates | — | Reissued via Let’s Encrypt on destination. |
| Home directory contents | Streamed via SSH | Copied 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_cacheblocks 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.
Related reading
- CyberPanel migration — same SSH-pull model, plus mail migration.
- Plesk migration — SSH-pull with
plesk binscraping. - cPanel migration — archive-upload model.