1# Clover Source of Truth migration
2
3The existing preview can take a consistent copy of Zenith's live SQLite index without stopping the old service:
4
5```sh
6sh tools/import-source-index.sh clover-source-of-truth-preview-6311ec97
7```
8
9The script stops only that preview, snapshots its ZFS dataset, imports a SQLite `.backup`, checks integrity and checksums, then stages and checks the HTTP route. It retains the pre-import snapshot for recovery. It leaves the preview's own API key in place; the old key must be preserved for the production endpoint because existing clients send it as their authorization header.
10
11On 2026-09-26, Zenith's live index contained 2,592 media files, 136,842 derived file records, and 15,635 derived references. The imported preview passed SQLite integrity, reported the same counts, returned HTTP 200 at `clover-source-of-truth-preview-6311ec97.studio.test`, and had one healthy Nomad allocation. A nonexistent file returned 404. One indexed public raw file and its derived asset were copied from Zenith into the isolated preview, served over HTTPS with HTTP 200, and matched their source SHA-256 hashes; the test files were then removed. The full Published and `derived` trees remain absent from the VM. Zenith's derived tree holds 143,547 files totaling 39,684,661,494 bytes, beyond the demo pool's capacity.
12
13The `clo` account used by the stream importer had zero unreadable files and zero untraversable directories in the source tree at inspection.
14
15For the real cutover, keep `storage1/clover` mounted at `/srv/clover` and point the service's `/published` mount at `/srv/clover/Published`. That avoids copying Published at all. Stop the old source-of-truth container and the new Nomad job, then run `bash tools/import-source-data.sh` with `STUDIO_DEPLOY_HOST` and `STUDIO_DEPLOY_PORT` set for the new host while Zenith remains reachable over SSH. The importer checks both jobs, streams `Documents/Config/paper clover/` into the service's managed ZFS dataset without storing 40 GB on the Mac, compares content digests and SQLite integrity, and leaves Snow Globe stopped with its pre-import snapshot available. A small cross-host fixture verified the stream, including a symlink and hardlink; the full 40 GB transfer remains a production cutover operation. Later staging clones the managed service dataset with ZFS.
16
17If NixOS replaces Zenith on the same machine, stop the old service and take a named `storage1/clover` snapshot before reinstalling. After the pool is mounted at `/srv/clover`, set `STUDIO_MIGRATION_SNAPSHOT=<name>` when running the same importer. It reads the immutable `/srv/clover/.zfs/snapshot/<name>/Documents/Config/paper clover/` tree on the new host and streams directly into the service dataset; no old Docker daemon or second machine is required. The importer rejects a missing or malformed snapshot name before changing the destination.
18
19Run `bash tools/import-legacy-secrets.sh clover-source-of-truth CLOVER_SOT_KEY` during cutover to transfer the old key directly from Zenith's `.env` into Snow Globe's Nomad secret, then deploy the service so its environment receives the imported value. This command changes the production service key; do not run it against the VM while its generated key is in use. Check a representative public raw and derived file over the new hostname before changing the public route. The old container and dataset snapshots remain available until this check passes.