yeke.io · docs
SQLite to PostgreSQL Migration
Move SQLite data to PostgreSQL with yeke-migrate. The tool runs while core is stopped, supports this direction only and verifies data integrity before marking the migration complete.
Overview
Move to PostgreSQL without throwing away your audit trail.
yeke-migrate copies records from a SQLite file into PostgreSQL, including the audit trail and encrypted columns. It does not delete the source file.
The tool is offline and one-way: it runs while core is stopped, and only moves data SQLite → PostgreSQL. There is no reverse direction (PostgreSQL → SQLite).
Prerequisites
None of the three are enforced by the tool; they are operational discipline.
- Back up first. Before starting, take a copy of the source SQLite file (and the
adjacent
snapshot.keyfile) — that copy is your way back. - Core must be stopped. Nothing should be writing to the source file; the tool does not enforce this itself; stopping the core process before running it is the operator's responsibility.
- The target must be empty. If the target PostgreSQL already has a
schema_migrationstable, the tool refuses to run — recovering from a half-finished attempt means dropping the target schema and starting over from the source's pre-migration backup.
Getting the tool
It is not distributed separately; it ships inside the core image.
yeke-migrate ships inside the core image as a single-file bundle
(/app/tools/yeke-migrate.mjs). For a regular install you can extract it from the
published image and run it on any machine with Node.js ≥ 22:
docker create --name yeke-migrate-extract nairotech/yeke:<version> docker cp yeke-migrate-extract:/app/tools/yeke-migrate.mjs ./yeke-migrate.mjs docker rm yeke-migrate-extract
The air-gap package ships the same tool as a ready bundle
(cli/yeke-migrate-<version>.mjs) — see the
air-gap installation page, step 5.
Usage
Two required flags.
On the installation page's default path, the source file sits inside a Docker volume, so
there's no path to it on the host; take it out first with core stopped
(snapshot.key comes along with it). If you mounted your own directory instead,
skip this step — point --source straight at core.db in that
directory.
docker stop yeke docker cp yeke:/var/lib/yeke ./yeke-data
node yeke-migrate.mjs \
--source ./yeke-data/core.db \
--target postgres://user:pass@host:5432/yekeThe key that opens the envelope-encrypted columns is resolved in the same order as core's
own key resolution: --snapshot-key > --snapshot-key-file >
YEKE_SNAPSHOT_KEY > YEKE_SNAPSHOT_KEY_FILE > the
snapshot.key file next to the source. If you don't supply the same key
that encrypted the source, the envelope-sample-open verification step fails and the tool
leaves the target unmarked as complete.
The target schema is not reinvented by the tool — it derives from core's own current
baseline schema, and the table-copy order follows the same dependency graph.
counters and operation_events.seq values are copied as-is, not
recomputed.
Integrity verification
Part of the tool, not an afterthought.
- Row-count equality. Source and target row counts are compared per table.
- Audit trail integrity.
MAX(seq)inoperation_eventsplus a byte comparison of a random sample. - Envelope sample decryption. A sample of encrypted columns is decrypted with the migrated key to confirm it actually opens.
- SIEM export cursors. If configured, the
chain_head/cursor rows of any audit-export targets are checked for an exact copy.
Until all of these pass, the tool does not write the "complete" row to
schema_migrations on the target.
A half-finished migration
An interrupted migration is never silently assumed to have succeeded.
If migration is interrupted or verification fails, the target’s schema_migrations table has no completion record. Core refuses to start in PostgreSQL mode against that incomplete target.
| Code | Meaning |
|---|---|
0 | Complete, target marked. |
1 | Integrity verification failed — target not marked. |
2 | Usage error (missing/invalid argument). |
3 | Target not empty — the tool's own safety gate. |
Limits
The tool is kept narrow, not a general-purpose migration framework.
- No reverse direction. PostgreSQL → SQLite is not supported. Moving data out of an
HA install back down to a single node uses PostgreSQL's own tools
(
pg_dump). - Back up first. Migration does not corrupt the source, but an interruption or failure with no backup of the source makes going back impossible.
- No live/dual-write migration. Core must not be running while migration happens; expect downtime, the same class of interruption every deploy already causes.
- No resume semantics. Recovering from an interrupted attempt means dropping the target and starting over.
How is the target PostgreSQL set up?
Before migrating, know the target's connection shape and license gate: both are on the PostgreSQL connection page.