Site cloning & in-host migration

Two Aegir tasks duplicate or relocate a site without leaving the host:

  • Clone — create a new site as a copy of an existing one (same host, often same platform, new machine-name).
  • Migrate — move a site from one platform to another on the same host. The classic Drupal-version-upgrade path: add drupal-10.5-pro via octopus up-lts platforms, then migrate the site onto it.

Both are Provision backup/restore operations under the hood — a full site backup followed by a restore on the new platform or machine-name, plus a Hostmaster node rewrite. BOA layers two control files on top that trade safety for speed when you trust the source.

The two accelerators

Control file Path Effect Scope
FastTrack.info ~/static/control/FastTrack.info skip the pre-clone/pre-migrate verify tasks clone + migrate
MyQuick.info ~/static/control/MyQuick.info per-table parallel mydumper/myloader instead of single-stream dump backup, clone, migrate, delete

They are independent — either, both, or neither. Both are empty control files in the Octopus instance's ~/static/control/ directory (their presence is the switch; contents are irrelevant), so an instance owner without root can toggle them.

Mind the BOA defaults — these are not a neutral opt-in. A periodic barracuda pass maintains the default state per instance, and it is not "off for both":

  • MyQuick is ON by default. Each pass writes MyQuick.info (unless a MyClassic.info opt-out file exists), so parallel dump/restore — and its Restore-task caveat below — is the default behaviour, not something you opt into.
  • FastTrack is OFF by default. The same pass deletes any FastTrack.info once and writes ClassicTrack.info, so the defensive verifies run by default.

FastTrack — skip the defensive verifies

By default Clone and Migrate queue a set of verify tasks first: verify source platform, verify target platform, verify source site. With FastTrack.info present:

  1. Both source and target platforms are no longer verified.
  2. The site is no longer verified before clone or migrate.

Those verifies normally catch ownership drift, missing modules, and broken settings.php — issues that, if uncaught, surface mid-clone and can leave the new site in a state that is hard to recover without root. The legitimate reason to skip them is mass migration: verifying every platform and site for each clone in a batch of 200 is duplicated work once you have verified at the start of the batch.

Restore the default (verifying) behaviour:

touch ~/static/control/ClassicTrack.info
rm ~/static/control/FastTrack.info

ClassicTrack.info is the explicit opt-back-in — create it and delete FastTrack.info to force classic Aegir behaviour.

MyQuick — parallel dump/restore

With MyQuick.info present, the DB phase of backup, clone, migrate and delete tasks switches to a per-table parallel mydumper dump and myloader import, collapsing the hours-long single-stream dump of a large database to minutes (BOA's own figure: tasks that normally take 1–2 hours down to 3–6 minutes).

The trade-off — restore task breaks. With MyQuick active, Aegir does not leave a conventional complete .sql dump inside the site archive tarball. The split per-table dump is not what Aegir's Restore task expects, so Restore will not work for any site whose last archive was produced under MyQuick. Because MyQuick is on by default (see above), this caveat applies on a stock BOA host unless you have deliberately turned it off.

Mitigations:

  • The system still maintains nightly backups of every site using the split-dump format. You can find the per-table SQL dump in the backups directory under a timestamped subdirectory and reconstruct/restore manually.
  • If you specifically need Aegir's Restore task to work, opt out of MyQuick by creating ~/static/control/MyClassic.info and removing ~/static/control/MyQuick.info. MyClassic.info stops the periodic barracuda pass from re-writing MyQuick.info, so the slower single-stream dump (which Restore can read) becomes the default again.

Where the speed difference comes from

Phase Default FastTrack MyQuick
Verify source platform queued skipped n/a
Verify target platform queued skipped n/a
Verify source site queued skipped n/a
Backup source DB single-stream (slow) (no change) parallel (fast)
Copy site files unchanged (no change) (no change)
Restore DB on new name/platform single-stream (slow) (no change) parallel (fast)
Install / verify new site unchanged (no change) (no change)

FastTrack removes the verify overhead; MyQuick parallelises the two DB phases. Combined on a large DB-heavy site they are transformative; on a small site FastTrack alone is the bigger win.

Clone — Provision backend

The Aegir Clone task wraps Provision's provision-clone. Its first argument is the Drush alias of the new site as generated by provision-save, not a bare domain:

# provision-save the new site first, then:
drush @site provision-clone @new_site @platform_name

Passing a bare domain as the first argument fails — the new site must already have a saved Drush alias. The Hostmaster-side task that registers the clone in the front-end DB takes positional name=value task arguments (the clone task reads new_uri and target_platform):

drush @hostmaster hosting-task @source-site clone \
  new_uri=clone-of-foo.example.com target_platform=@target-platform-alias

In practice operators drive one-offs from the Aegir UI (source site node → Tasks → Clone) and use Drush only for scripted bulk operations.

Migrate — Provision backend

The Aegir Migrate task wraps Provision's provision-migrate:

drush @site-alias provision-migrate @target-platform-alias

The task verifies the target platform supports the site's modules, briefly disables the site, moves sites/<domain>/ from the old platform to the new, updates the codebase references, runs drush updatedb -y on the new platform, rewrites the nginx vhost to the new platform path, and re-enables the site. Total downtime is typically 30 s to a few minutes depending on DB size.

hosting_migrate also ships hosting_migrate.batch.inc for migrating many sites in one job — the common shape during a Drupal-version upgrade, where every site on the old platform moves to the new one. The Hostmaster-side hosting-task uses the same positional new_uri= / target_platform= argument form as Clone.

A Migrate can also cross installation profiles when the target platform uses a different profile — moving a site from, say, a distribution profile to plain drupal.

Site Verify must run clean first

Migrate (and Clone, without FastTrack) depend on the source site verifying cleanly. A site that fails Verify on the source will fail the relocation; fix the verify error before relocating, or accept the FastTrack risk knowingly.

Upgrade safety: how a target platform is judged

Migrate and Clone are the Aegir-preferred way to apply core and module updates — build a new platform with the newer code, then move sites onto it — and the front end will not let you move a site somewhere that would corrupt it. When you open the Migrate or Clone form, each candidate target platform is classified from a per-package comparison of the site's current platform against the target, and the result is shown under each target as Upgrades / Warnings / Errors (hosting_package_comparison(), hosting_package.instance.inc:334-395).

The comparison keys every module and theme by its installed schema version and a computed version code, and sorts each into:

  • Error — an enabled package whose schema on the current platform is newer than on the target. Moving there would be a schema downgrade, which Drupal cannot do. A target with any Error count is disabled on the form — you cannot select it (hosting_migrate.module:204-206).
  • Warning — a package missing from the target (it would be disabled by Drupal's update logic), or a straight downgrade of a non-blocking package.
  • Upgrade — the target has a newer version/schema; the move runs the module's updates.

The Compare platforms link on the form (hosting/migrate/compare/…) opens a per-package table tagging each module downgrade / missing / upgrade / same, so you can see exactly why a target is flagged before committing.

Because the comparison reads each platform's package registry, it is only as current as the last Verify of the platforms involved: if you have just added modules to a target platform, re-Verify it so the newly available versions are registered before you rely on the Migrate form's judgement.

Drupal 10+ / Composer platforms. This registry is not a Drupal-7-only relic — Provision populates each package's schema version from \Drupal::service('update.update_hook_registry')->getInstalledVersion() on D10+ (and drupal_get_installed_schema_version() below that), so the upgrade/warning/ error gating and the Compare view keep working for Composer-built platforms. The one difference is that module/theme detection reads *.info.yml on modern cores, so the exact set of packages compared is core-version dependent.

TLS / Encryption auto-disable

Neither a clone nor a name-changing migrate carries the source's TLS certificate. The key and certificate are bound to the source machine-name and must never be reused by the new node, so BOA auto-disables Encryption on the new node before it is saved.

On clonehosting_clone resets the new node unconditionally (guarded only by HOSTING_SSL_DISABLED being defined):

$clone->ssl_enabled = HOSTING_SSL_DISABLED;
$clone->ssl_key      = 0;

This mirrors the existing safety where a clone also starts with cron disabled.

On migrate — only when the machine-name actually changes. hosting_migrate compares the source domain against new_uri; if they differ (and the node is not the Hostmaster site), it sets ssl_enabled = HOSTING_SSL_DISABLED and ssl_key = 0 on the front end, and the Provision backend forces ssl_enabled = 0 / unsets ssl_key before the final verify. Stale per-site Let's Encrypt control/pid files are unlinked automatically; the immutable manual-cert flag is preserved. A same-name platform-to-platform migrate (machine-name unchanged) leaves Encryption enabled in its persisted end-state, but the Provision backend still transiently disables SSL (ssl_enabled = 0 / unset ssl_key) around the migrate to avoid vhost/key race edge cases, then re-enables it afterwards from the saved encryption_was_enabled state — so the certificate is not carried across a name change but is not permanently dropped on a same-name move. The Hostmaster site is exempt.

In every case the operator re-enables Encryption deliberately for the new hostname — issue a fresh Let's Encrypt certificate for the clone's real domain rather than carrying the source's over.

Files symlinking on clone and migrate/rename

Both tasks deploy the new site from a backup that preserves symlinks, and on a native-symlinked BOA host a site's files/private dirs are symlinks into the per-account store. Left alone, the freshly deployed copy would keep pointing at the source site's store. Provision re-homes it automatically:

  • Clone — after the clone's post-deploy verify, the clone task runs the hardened NOPASSWD sudo wrapper /usr/local/bin/fix-drupal-site-symlinks.sh, which drives autosymlink's narrow single-site --force-unshare apply mode: the source's files are copied into the clone's own /data/disk/<account>/static/files/<clone>/ store and the in-site symlinks repointed. --force-unshare breaks the inherited link even when a static/control/share.files.<site>.info sharing file exists — a fresh clone never opted into sharing.
  • Migrate / rename — the Migrate task (also the RENAME path, e.g. promoting staging to live) mirrors the clone flow right after the target verify: the inherited old-name link is broken, the data copied into the target's own static/files/<uri> store, and the symlinks repointed. A store already sitting at the target name is archived aside first. The old-name store then becomes a normal reported orphan, archived to .archived/ by the nightly sweep — never auto-deleted. A same-name platform-to-platform migrate simply re-verifies idempotently.

Warn-not-fail. The symlink step never fails the clone or migrate. Operator signals:

Outcome Where you see it
Success Aegir task log: [native-symlink] <site>: files/private moved into the per-account store and symlinked
Wrapper run failed / returned non-zero Aegir task log: [native-symlink] <site>: could not move files into the store (non-fatal); left as plain dirs - manual review if symlinking was expected — the task still succeeds
Unshare not completed — deferred by the nightly maintenance pause (/etc/boa/.pause_tasks_maint.cnf), per-site dry-run not clean, or the unshare could not be applied (missing source / no space / rsync fail) /var/log/boa/autosymlink.log: [ALERT] Clone unshare for <site> not completed ...; files may still be shared with the source - manual review required
Wrapper absent, kill-switch control file present, or account not under /data/disk Silent skip — no warning, no ALERT

Recovery once space is available (or the pause has lifted):

sudo /usr/local/bin/fix-drupal-site-symlinks.sh --site=<clone> --force-unshare

Caveat: a cross-account clone under low disk may keep a link into the source store until the manual rerun; a same-account shared link is harmless. See Files symlinking for the subsystem overview, kill-switches and store layout, and Orphans & archiving for how the old-name store is archived.

Backups produced by these tasks

Provision writes its task backups to the server's flat backup directory (~/backups, i.e. aegir_root/backups) as a single hyphenated tarball per archive:

~/backups/<uri>-<timestamp>.tar.gz

for example ~/backups/foo.example.com-20260623.143501.tar.gz. There is no per-site subdirectory — the file is flat in ~/backups, named <uri>-<date>. Under MyQuick, the split per-table SQL dump for the same archive sits in a timestamped directory alongside (<uri>_sql_dump_backup_<timestamp>), which is the dump you reconstruct from when the Aegir Restore task cannot read a MyQuick archive.

Clone vs cross-host move

Clone and Migrate stay on one host. To duplicate or relocate an account onto a different BOA host, use the root-side toolchain — xcopy to duplicate, xoct to move a single account, xmass for the whole server. See Cross-host migration.

Related