Migrations

Last updated

/jabali-admin/migrations. M15 (in part) + ongoing pipeline work.

Supported sources

SourceFormatStatus
cPanelcpmove-<user>.tar.gz✅, preserves MySQL users + bcrypt password hashes (so migrated apps keep working); see “preserve cpanel MySQL users + password hashes” commit.
DirectAdminDA backup tarball✅, see docs/user/directadmin-migration.astro (legacy) for source-side prep notes.
PleskLive 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.
HestiaHestia backup🟡, partial. Files + DBs + DNS; mail subset (Stalwart vs. Exim model mismatch).
WHMWHM-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

  1. Upload archive to /jabali-admin/migrations (or scp to /var/lib/jabali/migrations/incoming/).
  2. 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.
  3. 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.astro for the source-side prep (run da backup-all etc.) 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 --list to enumerate subscriptions, then plesk 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_unsupported and imported later by the PostgreSQL-parity milestone. Reseller hierarchies are flattened — every subscription becomes a top-level Jabali user.

WHM

  • Splits into per-cpmove jobs 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.