Summary
One-command upgrade path for anyone self-hosting a legacy Redis-backed EtherCalc:
cp /var/lib/redis/dump.rdb ./legacy-dump.rdb
git clone https://github.com/audreyt/ethercalc && cd ethercalc
./bin/migrate-legacy.sh
Stands up a temporary redis:7-alpine loaded with your dump, builds the new Worker, streams every room across, and writes a dated backup tarball (./backups/ethercalc-*.tar.gz) containing the migrated state, the source dump, and a provenance manifest. Leaves the Worker running on http://localhost:8000 — existing room URLs keep working.
Details
bin/migrate-legacy.sh— bash wrapper orchestrating the three-service compose stack (legacy-redis+ethercalc+migrator) behind amigrateprofile. Pre-flight checks, token minting (openssl → /dev/urandom fallback), quarantine of existing./ethercalc-data/before the run, post-run backup packaging (BSD/GNU-tar portable), and a restart-for-serving step that tears down only the migration-profile services.docker-compose.yml— gains themigrateprofile + anethercalc/_healthhealthcheck so the migrator candepends_onwithcondition: service_healthy. Defaultdocker compose upbehavior unchanged.- README — new "Turnkey (recommended)" section; existing
bin/ethercalc migratereclassified as "Manual (advanced)".
Verified
End-to-end on OrbStack with a 2-room test dump.rdb: rooms land in DO storage, fetch via URL (/_/roomA, /_/roomB) returns seeded snapshots, /_exists/roomA returns true, XLSX export works, backup tarball round-trips (DO state + source dump + manifest.json).
Known self-host limitation (unchanged from 0.20260423.0)
GET /_rooms returns [] on Docker self-host — the standalone workerd bundle doesn't wire D1, so the cross-room enumeration view is empty. Rooms remain accessible by URL; only the admin list is blank. The migration script verifies via the migrator's summary + on-disk DO SQLite count instead.