Skip to content

Nine Lives v1.6.0

Choose a tag to compare

@jakemorgangit jakemorgangit released this 11 Aug 16:16
· 81 commits to main since this release
3b4d934

Two things in this release are not increments: a second front end and a second storage provider. Both have been documented in the README for a while and existed in no downloadable build until now.

S3-compatible object storage (#51)

An s3:// container is just another entry in the containers list. AWS S3, Wasabi, Backblaze B2, Cloudflare R2, and appliances speaking the S3 API.

The URL's own scheme picks the provider, so nothing else has to be kept in sync and every existing config migrates by doing nothing. The credential is the pair AccessKeyId:SecretKey - which is literally the engine's own CREATE CREDENTIAL secret format - so it rides the existing credential pipeline unchanged, with a shape check at entry rather than an authentication failure at restore time.

Browsing a bucket uses a hand-rolled SigV4 signer and a minimal ListObjectsV2 client, pinned stage by stage against AWS's published test vectors. No SDK: the alternative was the largest package in the application in exchange for one HMAC chain.

Restoring from S3 needs SQL Server 2022 or later and is not available on Express. The app refuses before anything is dropped rather than erroring on the server afterwards.

Not yet exercised against a live bucket. Everything is verified offline - published signature vectors, a scripted endpoint, and a large set of tests - but the first real-world report will be the interesting one. The failure explainer turns the provider's own error codes into the next move, which should make that report a short one.

The CLI: 9lives.exe

9lives.exe ships beside the app. The same engine from a terminal, against the same configured containers, servers and credentials: read verbs (list, points, script, validate, exposure), execution verbs (restore, rehearse, backup), and provisioning verbs (add-server, add-container) so a freshly built VM can be configured with nobody at a screen.

--ephemeral resolves an estate entirely from environment variables, persisting nothing, for service accounts and CI agents. --json makes the endings machine-shaped. The full reference lives in 9lives help VERB, held to the parser by tests so it cannot drift.

A front door (#343)

Choosing a mode now lands on Home: what the application is, the three get-going steps as buttons, and pointers to the rest of what the chosen mode offers. Reachable any time from the sidebar, or Ctrl+0.

Correctness fixes worth naming

A code review before this release found several defects that could each have cost somebody a restore. All are fixed here:

  • A striped backup read from an instance's own history was declared corrupt and the restore refused. msdb records a backup's size once per set rather than per stripe, and zero was being read as "failed upload" - so this fired at DR time, on precisely the large databases that get striped.
  • A restore chain could take one server's full backup and another server's logs. Two servers backing up a same-named database to one container is the everyday DR pair; chains are now built per database and instance.
  • Restore receipts could destroy each other. A writer that could not take the history lock wrote anyway, dropping whatever the other process had committed in between.
  • A backup set id could break out of the comment naming it, leaving the remainder of the line standing as an executable statement.
  • restore and rehearse never created the server-side credential they authenticate with, so the documented provisioning template failed on its last line.
  • rehearse ran no preflights, so a misconfigured rehearsal host reported NOT PROVEN - which reads as "this backup is bad" when the backup was never in question. Blocked and disproven are now different answers.
  • A backup destination longer than SQL Server's 259-character limit is refused before the run rather than discovered mid-backup.

Also

The screens no longer assume Azure: a saved container is a saved container, whichever provider answers it. Failures in the early restore steps are shown rather than reaching only a grey status line. Editing a container can no longer save over a different one. The CLI's exit codes stopped contradicting their own documentation, and --keep-sessions exists for restores that must leave other connections alone.

The full list is in CHANGELOG.md.

Downloads

NineLives.exe and 9lives.exe for x64, -arm64 variants for Windows on ARM, zips of each pair, and SHA256SUMS.txt. Every asset carries build provenance:

gh attestation verify NineLives.exe --repo jakemorgangit/NineLives

The binaries are unsigned, so SmartScreen will warn on first run - see the README for what that is and how to check what you have downloaded.