Plesk migration: move subscriptions from Plesk to Jabali Panel

Last updated

The Plesk ingest path. Status: production-supported. Unique among the panel’s migration sources: SSH pull-based, not archive upload — no pkgacct-style tarball to produce, no manual file transfer.

How it differs from cPanel / DirectAdmin / HestiaCP

SourceDiscoveryData transfer
cPanelUpload cpmove-<user>.tar.gzArchive
DirectAdminUpload da backup-user tarballArchive
HestiaCPUpload v-backup-user outputArchive
PleskSSH into source, run plesk binStreamed on Restore
WHMUpload multi-account cpmove dumpArchive

The Plesk source is enumerated live: the panel opens an SSH session, calls plesk bin subscription --list, and per subscription reads --info for domains, databases, DNS, mail, WordPress. This means:

  • No pkgacct equivalent needed. Nothing to produce, ship, or delete on the source.
  • Discovery is read-only. Every command is a --list / --info / --format json call. The source panel stays fully operational.
  • Freeze writes at restore time, not discovery time. Analyze the source days ahead of cutover; only cut over DNS + freeze writes when you press Restore.

Prerequisites

  • SSH access to the source Plesk host (default port 22). Non-standard ports supported.
  • Principal: root or a sudo-capable admin. Required because plesk bin subscription --list must see every subscription regardless of owner.
  • Credentials: SSH password OR SSH private key (base64-encoded in the migration secret store).
  • Source Plesk version: any Plesk Obsidian (17.x, 18.x) on Linux. Plesk on Windows is not supported (different backend).
  • Network reachability: destination Jabali host must reach the source over SSH. Private-IP sources require the migration_allow_private_hosts server setting enabled.

Operator workflow

  1. Add the source in /jabali-admin/migrations:
    • Kind: plesk
    • Host: <source-plesk-fqdn-or-ip>
    • Port: 22 (or custom)
    • Auth: SSH password or private key
  2. Discover — the panel connects via SSH and lists every subscription.
  3. Select subscriptions — pick one, several, or all. Per-subscription: pick the target Hosting Package.
  4. Analyze — reads domains, DBs, DNS, mail, WordPress from the source. No writes.
  5. Restore — synthesizes the cpmove-shape archive on the destination, ingests each asset. Per-phase progress shown in the UI.
  6. Communicate generated mail passwords to mailbox owners.
  7. Repoint DNS at the registrar.
  8. Issue SSL via the per-domain SSL toggle.

Cutover playbook

Same shape as the cPanel cutover playbook; the only difference is step 3, where you press Restore in the UI instead of running pkgacct + rsync.

  1. T-48h — lower DNS TTLs to 300s at the registrar.
  2. T-1h — freeze writes on the source Plesk subscription (put in maintenance).
  3. T-45min — press Restore on the pre-analyzed subscription in /jabali-admin/migrations.
  4. T-30min — restore completes; verify domains + DBs + mailboxes in the panel.
  5. T-15min — smoke-test the new host with curl --resolve.
  6. T-0 — repoint A/AAAA/MX at the registrar.
  7. T+1h — issue SSL.
  8. T+24h — restore original TTLs.

What gets migrated

AssetBehavior
SubscriptionsBecome panel users. Login name = subscription name (Plesk’s subscription primary key).
Home directoriesCopied over SSH from /var/www/vhosts/<domain>/ on the source.
Domains and subdomainsCreated as panel Domain rows. Plesk’s alias-vs-subdomain distinction is preserved.
DNS zonesRead from plesk bin dns --info <domain>, translated to PowerDNS rows.
MariaDB / MySQL databasesRestored with users and password hashes preserved where compatible.
PostgreSQL databasesRestored into the panel-managed PostgreSQL instance. Plesk is one of only two supported sources for Postgres migration (the other is HestiaCP).
Email accountsRecreated in Stalwart with generated passwords. Cleartext or Courier/Dovecot hashes from Plesk are not portable.
Forwarders, catch-all, autorespondersTranslated to Stalwart equivalents where the semantics map.
WordPress installsDetected via plesk ext wp-toolkit --list -format json. Re-registered with the panel’s WordPress tooling on the destination.
CustomersSurface as suggested user assignments; operator can merge or split.
Service plansSurface as suggested Hosting Package mappings.
SSL certificatesNot migrated — reissued via Let’s Encrypt on the destination.

What is not migrated

  • Plesk extensions. Kaspersky Anti-Virus, Fail2Ban configs, JetBackup, Node.js extension, Grafana extension — none translate. Equivalent capability: AppSec, CrowdSec, the panel’s built-in backups, Docker Apps.
  • Plesk on Windows. Different backend (IIS + MSSQL + Exchange). Jabali is nginx + PHP-FPM + MariaDB + Stalwart. Migrate Windows Plesk with per-service exports and hand-import.
  • Reseller structure. Flattened; no reseller construct exists in Jabali.
  • Plesk firewall rules. Re-implement as UFW + CrowdSec.

Troubleshooting

Discovery fails with plesk: command not found. The SSH principal is unprivileged and /usr/local/psa/bin/ is not in PATH. Log into the source, verify sudo plesk bin subscription --list works, and use a sudo-capable admin for the migration credentials.

Discovery fails with subscription "root" not found. The panel probes plesk bin subscription --info <ssh-principal> to see if the login name matches a subscription. When you connect as root, this probe returns nothing — the panel then falls back to ListAccounts and prompts you to pick one. If the source has zero subscriptions, this errors out because there’s nothing to migrate.

PostgreSQL restore fails: role "<db-user>" does not exist. Plesk stores Postgres role names case-sensitively; the panel restores them as-is. If your app connects with a lowercased role name, either fix the app connection string or CREATE ROLE "<original-case>" WITH LOGIN ENCRYPTED PASSWORD 'x' on the destination.

WordPress install detected but shows the “hello world” page after restore. wp-config.php was pointing at the source’s DB_HOST=localhost:/var/run/mysqld/mysqld.sock; the panel-managed socket lives at a different path. Update DB_HOST in wp-config.php to 127.0.0.1 or the panel’s socket, then reload.

“SSH connect: dial tcp: i/o timeout” against a private-IP source. The migration_allow_private_hosts server setting defaults to false to block SSRF-style abuse. Enable under Server Settings → Migration → Allow private hosts, then retry.

Audit

Standard per-phase audit rows. Per-domain creation writes domain.create; per-database restore writes database.restore. The SSH session origin (host + user) is recorded on every audit row for post-migration forensics.

Frequently asked questions

Can I migrate from Plesk to Jabali Panel?
Yes. Jabali Panel's Plesk pipeline connects to the source Plesk host over SSH and enumerates every subscription via `plesk bin subscription --list`. The discovery step is strictly read-only — every command is a `--list`, `--info`, or `-format json` variant. Restore synthesizes a cpmove-style archive on the destination and hands off to the existing cPanel restore path, so files, MariaDB / MySQL / PostgreSQL databases, DNS zones, mailboxes, and WordPress installs land under Jabali-native storage.
What credentials does the Plesk pipeline need?
SSH access to the source Plesk host — either SSH password or SSH private key (base64-encoded). The principal must be `root` or a sudo-capable admin so `plesk bin` can enumerate every subscription regardless of owner. If you supply a non-root principal, the discovery step auto-pivots to the sole subscription on a single-tenant source; a multi-tenant source errors with the subscription list so you can pick one.
Does the migration touch the source Plesk server?
No. Every command shelled out to the source is a list / info / json-export variant (`plesk bin subscription --list`, `plesk bin domain --info`, `plesk bin database --list`, `plesk bin dns --info`, `plesk bin mail -l -json`, `plesk ext wp-toolkit --list -format json`). No create, delete, or modify calls run against the source. Source Plesk stays fully operational during discovery — repoint DNS only after you've validated the destination.
What Plesk features migrate to Jabali Panel?
Subscriptions become panel users; domains and subdomains become Domain rows; MariaDB, MySQL, and PostgreSQL databases restore with users and hashes preserved where the format is compatible; DNS zones translate from Plesk BIND to PowerDNS; mailboxes recreate in Stalwart (passwords are reset because Plesk's Courier/Dovecot hashes don't port); WordPress installs found via `plesk ext wp-toolkit` re-register with the panel's WordPress tooling. Customers and service plans surface as suggested Hosting Package mappings the operator confirms.
Is Plesk on Windows supported?
No. The Plesk pipeline supports Plesk on Linux only (Debian, Ubuntu, CentOS/AlmaLinux, RHEL). Plesk for Windows Server uses a different backend (IIS, MSSQL, Microsoft Exchange integration) that Jabali does not host — Jabali is nginx + PHP-FPM + MariaDB + Stalwart. For a Plesk Windows source you would need to export databases and files manually, then use per-service migration paths.
Does the Plesk pipeline handle resellers?
Resellers on the source are flattened — reseller-owned customers migrate as individual panel users with no parent-child relationship, since Jabali has no reseller construct. Reseller branding (custom logos, white-label themes) does not carry over. Re-model reseller billing in FOSSBilling, WHMCS, or Blesta instead of the panel.