Migration

Move first. Change DNS when you're ready.

KLYRN reads a cPanel or DirectAdmin backup, or connects to the old server over SSH: as root, as the cPanel account, or as any Unix user. Nothing is installed there. The imported site is live on the new server, previewed and verified, before a single record changes.

Nothing is written until you have read the plan. Nothing on the old server is modified, ever.

If the plan looks wrong, you have lost an upload and nothing else. If the preview looks wrong, DNS has not moved.

Supported sources

Five ways in, decided by what your login can do.

You give KLYRN one file or one SSH login. What that login is allowed to do decides the route; you never choose the mechanism yourself.

Migration sources and what each needs
Source What you give KLYRN What KLYRN does on the source Run end to end
cPanel backup archive A pkgacct-layout archive, uploaded with progress. A nested homedir.tar is handled. Nothing. The archive is inspected before it is unpacked; absolute paths and .. are refused. Yes
cPanel over SSH, as root Host, root login, the account name. Confirms it is cPanel, checks free space, runs the server's own pkgacct, streams the archive, deletes the temporary copy. Yes
cPanel over SSH, as the account Host and the cPanel user's own login. No root. Asks cPanel's own API to package that one account, waits for it, streams the result, removes it. Yes
DirectAdmin user backup The user backup archive. The kind is detected from the archive itself. Nothing. Yes
Any server over SSH A domain and an ordinary Unix login. No panel needed. Tars the document root on the source and extracts it here as it arrives; reads wp-config.php or .env for database credentials; dumps the databases; copies the crontab. Yes

Credentials. The SSH password or key exists only for the length of the job and is never written to the database. The host key is accepted on first use unless you pin it with --fingerprint; the fingerprint is printed in the job log so you can pin it next time. Encrypted private keys are not supported yet.

How it works

All five routes converge on one pipeline.

So the review you get is the same whichever way the data arrived, and the same in the panel and from the command line.

klyrn import cpanel /root/backup-acme.tar.gz
klyrn import show 1        # the plan
klyrn import apply 1       # the first thing that writes

Every command and flag

  1. InspectThe archive is read before it is unpacked. An entry with an absolute path or a .. is rejected rather than sanitised.
  2. ExtractAs the destination account, never as root.
  3. AnalyseEach document root identified as WordPress, Laravel, plain PHP or static. The PHP version mapped to one KLYRN has. Every .htaccess directive classified exactly once. Databases, users, grants, cron, DNS zones, certificates and mailbox counts read out.
  4. PlanNothing has been written. Every domain, database, user and cron entry with its conflicts and warnings; you choose what comes across and under which account name. A Unix user called shop already here? The plan proposes shop2, re-prefixes the databases and rewrites the application's configuration to match.
  5. ApplyThe account and its Unix user, the databases with their users recreated from the original password hashes, the files with the right ownership and the access-control entries nginx needs, a PHP-FPM pool, an nginx server block tested with nginx -t, cron entries rewritten to their new paths. A certificate is queued per domain.
  6. PreviewEvery name the site claims fetched from the new server's own nginx, redirects not followed, and the exact curl --resolve and hosts-file lines to do the same from your machine.
  7. VerifyEleven checks with their evidence, copyable as text. The overall result is the worst row.
  8. Cut overA table of exactly which records to change, and where.

Preview before DNS

Look at the migrated site while the old one is still serving the public.

The imported site is live on the new server the moment apply finishes, and nothing points at it yet. The preview asks that server for the site by name, the way a visitor will once DNS points here.

What the preview is not. It is a request to the new server. It does not fetch the old one and cannot tell you the two pages look the same. Comparing them is your job, and it is the step worth doing: a blank page returns HTTP 200.

your machine: the same request, by hand from the report
$ curl -sS -I --resolve example.com:443:203.0.113.10 https://example.com/
  HTTP/2 200 (served by the new server, before DNS moved)

# /etc/hosts, to browse it in a real browser
  203.0.113.10  example.com www.example.com
The report hands you these lines with your own names and address filled in.

Verification

Eleven checks, each with its evidence.

Every check runs against the new server and returns passed, warning or action required. One action required, and the report says action required.

The eleven verification checks
CheckWhat it establishes
FilesThe document root exists, has files, and they belong to the account. Files still owned by root are the classic leftover of an archive unpacked in the wrong place.
DatabasesThe databases are here with their table counts, and the application's own credentials open one. It reads wp-config.php and connects with what it finds.
DomainsEvery name the site claims is in this site's vhost, rather than falling through to the server that answers for anything unclaimed.
RuntimeThe thing that runs the site is running, and ran: PHP serving its own source as text is the failure this catches.
HTTPWhat the primary name returns from this server, with the timing.
SSLWhether there is a certificate and which names are on it. None before the cut-over is normal, and the row says so.
RedirectsEach redirect proved by asking for it, not by reading the configuration that was supposed to create it.
CronThe scheduled tasks that came across, and the ones attached to the account rather than a site.
.htaccessEvery directive accounted for, and whether a conversion has gone stale.
DNSOnly when you ask: where each name resolves today, against this server's address. Otherwise “not checked”, never an implied pass.
MailWhere the MX records point, and an action if one of them points here.

The report checks the new server, not the old one. It cannot tell you the two pages render the same; what “verified” means, precisely.

Cutover

In the order that works.

The old server keeps serving throughout. The one step people skip, and then wait a day for, is the TTL.

  1. Preview and verifyRead the report. Fix what it names.
  2. Lower the TTL at your DNS providerHours before the cut-over, not at it.
  3. Change the recordsThe cut-over table names them. If Cloudflare holds the zone, klyrn dns point writes them.
  4. Let the certificate arriveklyrn site ssl example.com, or wait: the scheduler retries every ten minutes once the name resolves here.
  5. Re-run the verification, asking for DNS this timeNow the DNS row means something, and SSL should have gone from expected to passed.
  6. Keep the old server for a weekLong enough for every cached record to expire and for anything you missed to surface while you can still look it up.

What happens to mail: nothing.

KLYRN does not host mail, by decision. Mailboxes, forwarders, autoresponders and filters stay with the provider that holds them today, and your MX records are never touched. The plan tells you how many mailboxes it found so the number is in front of you before you move, not after; the verification report marks an MX record pointing at the new server as action required, because KLYRN would refuse every message sent to it.

Why there is no mail server, and what else is deliberately absent

Corpus status

What is proven, and against what.

Tested against archives KLYRN wrote itself. No archive produced by a real cPanel or DirectAdmin server has been fed to it yet; that is the next step, and it has not happened. Each row below is a real run on the test server; the sources for the SSH routes were stand-ins that produce a genuine archive layout and answer the same commands cPanel documents.

Migration routes and the evidence for each
Route What was run
cPanel archive A 21 MB archive in pkgacct layout built from a live WordPress site: 3,343 files, 90.8 MB, detected as WordPress on PHP 8.3 with a RewriteRule found. After apply, the database user logged in with its original password and the site answered over HTTPS.
DirectAdmin archive Account and plan recognised, database imported with its hash preserved, cron rewritten, site answering over HTTPS with a Let's Encrypt certificate.
cPanel over SSH, as root Host-key fingerprint recorded, cPanel version detected, free space checked, pkgacct run, 21.2 MB streamed with progress, temporary archive removed from the source. A working WordPress site under a renamed account.
cPanel over SSH, as the account cPanel's own full-backup API started, packaging awaited, 21.2 MB streamed and removed from the source. A working site with a Let's Encrypt certificate.
Any server over SSH 100.7 MB of files copied (26.0 MB on the wire), the database discovered in wp-config.php and dumped, the crontab copied. Apply: 3,343 files, database user restored with the discovered password, site on HTTPS minutes later.
.htaccess translation 22 directives classified; the generated nginx passed nginx -t; a deliberately broken sibling file proved the rollback.

How long the site is down

A migration used to be one pass: everything copied while the old site was already switched off. Now the files and databases are copied while the old server keeps serving, and a second pass moves only what changed since. The downtime is that second pass.

These are measured, on one disposable VPS (3 vCPU, 5.9 GB, Ubuntu 24.04, MariaDB 10.11) with bash scripts/migrate-bench-suite.sh, every figure rendered from the run’s own JSON rather than typed in. Source and destination are the same machine, over an SSH connection to 127.0.0.1: that removes network time entirely, so these measure KLYRN’s CPU, disk and engine overhead and not a real move between two servers. On a real link the first pass takes longer and the second pass (the part you are down for) changes least, because it is mostly the database.

Downtime before and after the two-phase engine, per fixture
What was moved One pass, all downtime Two passes, downtime Change
4 × 1 GB files 83.54 s0.36 s232× faster
5.1 GB mixed site + 198 MB database 112.68 s6.21 s18× faster
200,000 small files (781 MB) 46.64 s3.17 s15× faster
WordPress, 1.64 GB + 157 MB database 38.87 s4.75 s8× faster
1.05 GB mixed site + 198 MB database 27.80 s6.42 s4× faster
Five small databases (99 MB) 4.61 s4.54 sno material change
One 1.59 GB InnoDB database 54.27 s52.94 sno material change

The last two rows are the honest limit of the feature and they are printed here for the same reason they are in our own report: a database has no safe incremental copy without access to the source’s binary log, which a migration does not get. So the second pass takes a fresh consistent dump and re-imports it: 41 of that 53 seconds is the import. If your site is mostly one large database, the two-phase engine moves your files early and your cutover is still about as long as your database takes. It is not “zero downtime”, and we will not call it that.

If you run cPanel or DirectAdmin and are willing to send a real backup of a test account through this, say so on the waitlist. One real archive is the most useful thing anyone outside this project can do for it.

Questions

Before you type a password.

Does KLYRN install anything on my old server?
No. It connects over SSH, runs the tools the server already has, streams the result, and deletes any temporary archive it created. Nothing is installed and nothing is left behind.
Do I need root on the old server?
No. Root lets KLYRN use cPanel's pkgacct. Without it, a cPanel account can package itself through cPanel's own API, and on any other server an ordinary Unix login is enough for the files, the databases and the crontab.
Will my database passwords change?
No. Users are recreated from the original password hash, so the credentials in your application's configuration still work.
What about .htaccess?
nginx does not read it. KLYRN reads it for you: every directive line is classified exactly once as converted, needs review, or not possible, and the converted nginx is shown to you and tested with nginx -t before you apply it. A WordPress front-controller block needs no equivalent; forced HTTPS is recognised as already done.
How large an account can it move?
Files are streamed rather than buffered, and the destination's free disk is checked before the copy starts. The largest single transfer exercised so far was a 1.1 GB backup archive copied to object storage in parts, each part checksummed. There is no configured ceiling.
What if the SSH session drops halfway?
Today the copy starts again from the beginning; there is no checkpoint. The old server is untouched either way, so a dropped session costs time and nothing else. A resumable, two-phase copy is being built and measured; this page will state the numbers when they exist, not before.

Not moving yet?

Hear when the first stable release is signed.

Migration is in the free beta today. If you would rather wait for a stable release, leave an email and you will get exactly one message when it and its prices are announced.

One email when pricing and the first release are announced. Nothing else.