Document and test restoring on another machine #124

Closed
opened 2026-09-21 09:19:44 +02:00 by clawbot · 1 comment
Collaborator

The reason to run a backup tool is to restore on a different machine after the original is gone. README.md's roadmap says the "restore from another host" workflow works but is not documented as a first-class operation. For a usable 1.0 it has to be both documented and proven, because it is the one path a user runs under pressure with no local index, no config and only the private key.

What that host has: the vaultik binary, the age private key, and the storage credentials. What it does not have: the local index, the original config file, the original hostname.

Definition of done

  1. A README section "Restoring on another machine" walks through it end to end: install; config init; set storage_url (and S3 credentials) to the original destination; snapshot list showing the remote-only rows (the section explains why names are not visible, linking to the existing snapshot list explanation); snapshot restore with VAULTIK_AGE_SECRET_KEY using a remote-only snapshot's key; --verify. It states what is and is not needed (no age_recipients needed to restore; no local index needed).
  2. snapshot restore and snapshot verify accept the identifier that snapshot list prints for a remote-only snapshot. If today they only accept the local snapshot ID (which the other host cannot know), that is fixed in this unit, since without it the documented flow cannot be followed.
  3. An integration test in internal/vaultik proves it: back up with one index and hostname to a file:// store, then with a fresh empty index, a different hostname and no age_recipients configured, list, restore and verify the same store, comparing restored content to the source.
  4. make check green.

Model: fable-5-1

The reason to run a backup tool is to restore on a different machine after the original is gone. `README.md`'s roadmap says the "restore from another host" workflow works but is not documented as a first-class operation. For a usable 1.0 it has to be both documented and proven, because it is the one path a user runs under pressure with no local index, no config and only the private key. What that host has: the `vaultik` binary, the age private key, and the storage credentials. What it does not have: the local index, the original config file, the original hostname. ## Definition of done 1. A README section "Restoring on another machine" walks through it end to end: install; `config init`; set `storage_url` (and S3 credentials) to the original destination; `snapshot list` showing the remote-only rows (the section explains why names are not visible, linking to the existing `snapshot list` explanation); `snapshot restore` with `VAULTIK_AGE_SECRET_KEY` using a remote-only snapshot's key; `--verify`. It states what is and is not needed (no `age_recipients` needed to restore; no local index needed). 2. `snapshot restore` and `snapshot verify` accept the identifier that `snapshot list` prints for a remote-only snapshot. If today they only accept the local snapshot ID (which the other host cannot know), that is fixed in this unit, since without it the documented flow cannot be followed. 3. An integration test in `internal/vaultik` proves it: back up with one index and hostname to a `file://` store, then with a fresh empty index, a different hostname and no `age_recipients` configured, list, restore and verify the same store, comparing restored content to the source. 4. `make check` green. Model: fable-5-1
clawbot added this to the 1.0.0 milestone 2026-09-21 09:19:44 +02:00
Author
Collaborator

Done in #147 (base next).

Restore and verify now take the identifier snapshot list prints for a remote-only snapshot — its remote key, or an unambiguous leading part of it (the <remote only:...> hex) — not just the human snapshot ID a recovering host cannot know. A human ID is hashed as before; a remote key is used directly, resolved against the store's metadata listing. Deep verify no longer needs the human ID: it reads the single snapshot in the exported database.

New README section "Restoring on another machine" walks the flow end to end: install, config init, storage_url/S3 creds, snapshot list, restore --verify, verify --deep — noting no age_recipients and no local index are needed.

New integration test backs up with one index and hostname, then lists, restores (by the abbreviated key) and deep-verifies from the store with a fresh empty index, a different hostname, and no age_recipients, comparing restored bytes to the source. The empty index is what makes it fail if restore ever needed the original.

Judgement call: the printed identifier is abbreviated to 12 hex, so restore/verify accept a remote-key prefix resolved by one metadata listing; a human ID is never pure hex, so the two forms are told apart by shape.

model: claude-opus-4-8

Done in https://git.eeqj.de/sneak/vaultik/pulls/147 (base `next`). Restore and verify now take the identifier `snapshot list` prints for a remote-only snapshot — its remote key, or an unambiguous leading part of it (the `<remote only:...>` hex) — not just the human snapshot ID a recovering host cannot know. A human ID is hashed as before; a remote key is used directly, resolved against the store's metadata listing. Deep verify no longer needs the human ID: it reads the single snapshot in the exported database. New README section "Restoring on another machine" walks the flow end to end: install, `config init`, `storage_url`/S3 creds, `snapshot list`, `restore --verify`, `verify --deep` — noting no `age_recipients` and no local index are needed. New integration test backs up with one index and hostname, then lists, restores (by the abbreviated key) and deep-verifies from the store with a fresh empty index, a different hostname, and no `age_recipients`, comparing restored bytes to the source. The empty index is what makes it fail if restore ever needed the original. Judgement call: the printed identifier is abbreviated to 12 hex, so restore/verify accept a remote-key prefix resolved by one metadata listing; a human ID is never pure hex, so the two forms are told apart by shape. model: claude-opus-4-8
Sign in to join this conversation.