cPanel Cutover
This runbook is the step-by-step procedure for moving one customer account from cPanel to HostCraft. It mirrors the Migrating from cPanel overview page but is written for the operator carrying out the migration, with exact commands and checkpoints.
Run this procedure once per account. Large-scale migrations execute this runbook for each account in dependency order.
Pre-conditions
Section titled “Pre-conditions”Before starting, confirm all of the following:
- You have a
cpmove-<user>.tar.gzbackup downloaded from the cPanel server. Generate it via:Terminal window # On the cPanel server/scripts/pkgacct <username># Then download from /home/<username>/cpmove-<username>.tar.gz - The target plan on HostCraft exists with sufficient disk quota, mailbox limit, and DB limit for this account.
- No domain collision: the account's primary domain and addon domains are not already present on the HostCraft server. Check:
Terminal window hostcraftd domain list | grep example.com - You have at least 2x the account's disk size free on the HostCraft server.
Step 1: Upload the backup
Section titled “Step 1: Upload the backup”Via the panel: Admin -> Restore -> Upload backup -> select the cpmove-*.tar.gz file.
Via the API:
curl -X POST https://panel.example.com/api/v1/restore/upload \ -H "Authorization: Bearer $HOSTCRAFT_TOKEN" \ -F "file=@/path/to/cpmove-username.tar.gz"The API returns a restore_id you will use in subsequent steps. Note it down.
Step 2: Probe (no apply)
Section titled “Step 2: Probe (no apply)”Run the restore in probe mode first. This parses the archive, maps cPanel concepts to HostCraft entities, and returns a preview with any flags raised. Nothing is applied to the system.
curl -X POST https://panel.example.com/api/v1/restore/probe \ -H "Authorization: Bearer $HOSTCRAFT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"restore_id": "<restore-id>"}'Review the probe output carefully. The daemon flags 14 categories of edge cases. For each flag, decide the handling option:
| Edge case | What it means | Common option |
|---|---|---|
| PHP version unavailable | The account used PHP 5.6 or 7.0-7.3 | Enable legacy mode on the plan, or snap to nearest supported version |
Complex .htaccess directives |
Rules the nginx translator could not convert | Review flagged rules manually after restore |
| Custom MX (Google Workspace, etc.) | MX records point elsewhere | Preserve exactly as-is, confirm with customer |
| mbox mailbox format | Dovecot uses Maildir; mbox will be converted | Conversion is automatic; no action needed |
| Incompatible password hashes | Hash algorithm not portable | A password-reset email will be sent to mailbox owners |
| External DNS (NS diverge) | Domain resolves through Cloudflare, etc. | Record export only; do not take DNS authority |
| Custom SSL certificate | Uploaded cert (not AutoSSL) | Import or re-request from Let's Encrypt |
Apache Include directives |
Included config files | Best-effort translate; complex ones are flagged for manual review |
| mod_security custom rules | Custom WAF rules | Default OWASP CRS only in v1; flag for customer notification |
| Per-account php.ini | Custom PHP settings | Translated to per-pool php_admin_value automatically |
| Quota exceeds plan | Account disk use is over the target plan's limit | Upgrade the plan or clean up data before restoring |
| Catch-all email | cPanel catch-all mailbox | Mapped to HostCraft catch-all automatically |
| Nested subdomain on addon | Complex subdomain hierarchy | Flattened; original hierarchy recorded in metadata |
| MariaDB vs MySQL collation mismatch | Collation differences | Imported with explicit charset and collation; log diffs reviewed |
Set your chosen options as JSON flags to pass to the restore step.
Step 3: Run the restore
Section titled “Step 3: Run the restore”Once the probe looks clean:
curl -X POST https://panel.example.com/api/v1/restore/run \ -H "Authorization: Bearer $HOSTCRAFT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "restore_id": "<restore-id>", "options": { "php_fallback": "snap", "ssl": "letsencrypt", "mail_password_reset": true } }'This starts a workflow saga in the background. Watch progress in the panel:
Admin -> Restore -> the restore job -> workflow steps.
Or tail the daemon log:
journalctl -u hostcraftd -f | grep "restore"The workflow covers: account creation, unix user, PHP-FPM pool, nginx vhost, file extraction, database import, DNS zone import, mailbox creation, SSL issuance, cron jobs, and per-site validation probes. Compensations run automatically if any step fails.
Do not cut DNS yet. The account is now on HostCraft but DNS still points to cPanel. This is intentional.
Step 4: Side-by-side comparison
Section titled “Step 4: Side-by-side comparison”With both servers live, compare the output of the old and new server on the same URLs.
Run a curl comparison on the homepage and five key pages:
# Replace OLD_IP and NEW_IP with the actual IPs; send Host header to target the right vhostOLD_IP="203.0.113.10"NEW_IP="198.51.100.20"DOMAIN="example.com"
for path in "/" "/about/" "/contact/" "/products/" "/shop/"; do echo "--- $path ---" echo "OLD:" curl -s -o /dev/null -w "%{http_code} %{size_download} bytes" \ --resolve "${DOMAIN}:80:${OLD_IP}" "http://${DOMAIN}${path}" echo "" echo "NEW:" curl -s -o /dev/null -w "%{http_code} %{size_download} bytes" \ --resolve "${DOMAIN}:80:${NEW_IP}" "http://${DOMAIN}${path}" echo ""doneAccept the restore as correct when:
- HTTP status codes match.
- Response sizes are within 10% (differences in minification are acceptable; large discrepancies need investigation).
- No 5xx errors on the new server.
Also confirm:
- Database-driven pages load correctly (product listing, user login if applicable).
- SSL works:
curl -v --resolve "${DOMAIN}:443:${NEW_IP}" "https://${DOMAIN}/"shows a valid chain. - Mail send works from a test mailbox on the new server (use
hostcraftd mail test --account=<id>).
Step 5: Lower DNS TTL
Section titled “Step 5: Lower DNS TTL”Once you are satisfied the new server is correct, lower the TTL on the domain's DNS records to 5 minutes. Do this on the source DNS (wherever the domain currently resolves, usually the cPanel server's DNS or an external registrar).
Wait for the existing high TTL to expire before proceeding. If the current TTL is 3600 seconds (1 hour), wait 1 hour after lowering it before cutting DNS.
Step 6: Cut DNS to HostCraft
Section titled “Step 6: Cut DNS to HostCraft”Update the A record (and AAAA if applicable) to point to the HostCraft server's IP.
If the domain's DNS is managed by HostCraft after the restore (i.e., NS records point here), the panel manages this automatically. Otherwise, update the records at the external DNS provider.
Confirm propagation:
dig example.com A +short# Should return the HostCraft IPStep 7: Monitor mail flow for 24 hours
Section titled “Step 7: Monitor mail flow for 24 hours”Mail in transit at cutover time may deliver to the old server. Monitor both:
# Postfix queue on the new serverpostqueue -phostcraftd mail queue
# Watch for bounces or deferralsjournalctl -u postfix -f | grep -E "bounce|deferred|reject"Alert on:
- Any hard bounces from the new server (configuration problem).
- Sustained deferrals from a specific receiving domain (reputation issue on the new IP, see IP Warmup).
- Missing mail that should have arrived (check if the old server is still receiving; that is normal for up to 24 hours while DNS propagates).
Step 8: Keep the cPanel source live for 7 days
Section titled “Step 8: Keep the cPanel source live for 7 days”Do not decommission the cPanel source immediately. Leave it running for 7 days as a fallback. Reasons:
- Some DNS resolvers cache longer than the TTL.
- If the customer reports a critical issue on HostCraft that cannot be fixed quickly, you can cut DNS back to cPanel while you investigate.
- Mail that queued before cutover may arrive at the old server for up to 24 hours.
During the 7-day window, check the old server's mail queue periodically to ensure it empties cleanly.
Step 9: Decommission the cPanel source
Section titled “Step 9: Decommission the cPanel source”After 7 clean days (no reported issues, old mail queue empty, DNS fully propagated):
- Disable the cPanel account on the source server (suspend, do not delete yet).
- Take a final backup of the cPanel account for archival.
- Delete the account from cPanel after confirming the backup was taken.
The account is now fully on HostCraft.
Rollback
Section titled “Rollback”If a critical problem is found after DNS cutover and it cannot be fixed quickly:
- Change DNS back to the old cPanel IP. Because the TTL is already at 5 minutes, most users will see the change within 5 minutes.
- Diagnose and fix the issue on the HostCraft side.
- Re-run the side-by-side comparison (Step 4) before cutting over again.
The cPanel account is safe for 7 days specifically to enable this rollback. After that window closes, rollback is not possible without restoring from the archival backup.