Migrations
Last updated
/jabali-admin/migrations. M15 (in part) + ongoing pipeline work.
Supported sources
| Source | Format | Status |
|---|---|---|
| cPanel | cpmove-<user>.tar.gz | ✅, preserves MySQL users + bcrypt password hashes (so migrated apps keep working); see “preserve cpanel MySQL users + password hashes” commit. |
| DirectAdmin | DA backup tarball | ✅, see docs/user/directadmin-migration.astro (legacy) for source-side prep notes. |
| Plesk | Live SSH pull | ✅, subscriptions + domains + MySQL DBs + DNS + mailboxes + WordPress + cron. Read-only on the source (plesk bin --list / --info only). PostgreSQL databases skipped in v1. |
| Hestia | Hestia backup | 🟡, partial. Files + DBs + DNS; mail subset (Stalwart vs. Exim model mismatch). |
| WHM | WHM-level dump (multiple cpmoves in one) | 🟡, same caveats as cPanel per-user. |
| IMAP (Gmail, M365, generic) | Live IMAP over TLS | ✅, per-mailbox. Messages + folders + flags via FETCH into staging Maildir, then JMAP import into Stalwart. Requires an app-password (or OAuth once phase B lands). |
Workflow
- Upload archive to
/jabali-admin/migrations(orscpto/var/lib/jabali/migrations/incoming/). - The pipeline runs four phases:
- Analyze: inspect the archive, list users / domains / DBs / mailboxes / DNS zones / cron jobs.
- Fix-perms: apply chown / chmod normalisations expected by Jabali’s per-user pool layout.
- Validate: DB password hashes parseable, DNS zone files valid, mail accounts consistent.
- Restore: create the panel user, ingest each domain / DB / mailbox / cron, hand off to the reconciler.
- Watch progress at
/jabali-admin/migrations/<id>.
Per-source notes
cPanel
- MySQL passwords are bcrypt in cPanel ≥ 11.96; Jabali stores the bcrypt hash directly in MariaDB so user apps keep authenticating without password reset.
- Email accounts: cPanel uses Dovecot+Exim, Jabali uses Stalwart. Passwords reset to a generated value (printed in the migration report): operator must communicate the new passwords to mailbox owners, or set “force first-login password reset” so users self-serve.
- DKIM keys: imported.
- DNSSEC: not migrated automatically (key formats differ); re-enable per-domain in Jabali.
DirectAdmin
- See
docs/user/directadmin-migration.astrofor the source-side prep (runda backup-alletc.) before upload.
Hestia
- Bind zones translated to PowerDNS schema rows.
- Exim → Stalwart routing rules: forwards + autoresponders ported; complex Exim acl rules need manual re-implementation.
Plesk
- Live SSH pull — no backup tarball required. Jabali runs
plesk bin subscription --listto enumerate subscriptions, thenplesk bin domain --info,database --info,dns --info,mail --info, and reads WordPress installs via WP Toolkit for each one. - Read-only on the source: every command Jabali executes on the Plesk host is
--list/--info/-format json. Nothing is created, modified, or deleted on the source panel — you can safely dual-run until you cut DNS over. - What imports: subscriptions → panel users, domains, MySQL databases (dumped over SSH), DNS zone records, mailboxes (via IMAP APPEND / Maildir where reachable), WordPress installs (with detected wp-config credentials rewritten), and per-subscription cron jobs.
- What is deferred: PostgreSQL databases are recorded in the manifest with
skipped: postgres_unsupportedand imported later by the PostgreSQL-parity milestone. Reseller hierarchies are flattened — every subscription becomes a top-level Jabali user.
WHM
- Splits into per-
cpmovejobs internally; each runs through the cPanel pipeline.
IMAP (Gmail / Microsoft 365 / generic)
- Per-mailbox, not per-account. A single job carries one or more
(remote_host, remote_port, remote_username, remote_secret)tuples plus the local target mailbox. Bulk moves come as a CSV upload. - Credentials: Gmail and M365 both require an app-password (or an OAuth2/XOAUTH2 token once phase B ships) — a plain password with 2FA on will fail at LOGIN. The secret is stored in the encrypted migration-secrets vault, never in a DB row.
- Folder mapping is automatic for INBOX / Sent / Drafts / Trash / Junk / Archive via IMAP SPECIAL-USE. Custom folders are recreated with the same name.
- Resumable: last-seen UID is tracked per folder, guarded by UIDVALIDITY, so a re-run continues instead of restarting. Message-ID dedup is performed at JMAP import time.
- What migrates in phase A: messages + folders + flags + INTERNALDATE. Aliases, contacts (CardDAV), calendars (CalDAV), and shared-mailbox ACLs land in subsequent phases.
- CLI:
jabali migrate imap --host imap.gmail.com --port 993 --user alice@example.com --target-mailbox alice@panelhost. Runs the same 4-stage pipeline (connect+validate → fetch → import → verify).
Limitations
- No live migration for panel-account sources (cPanel / DA / Hestia / WHM / Plesk restore stage). IMAP is the exception — the source stays live throughout.
- No CSF/LFS rule translation. CrowdSec is the IP-trust source on Jabali; carry over allowlists manually.
- No PostgreSQL data import in v1. cPanel / WHM / Plesk tarballs may include PostgreSQL dumps; those are recorded in the migration manifest and imported later once PostgreSQL parity ships.