Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Updating a deployed .erebus (SISR)

A .erebus built with --enable-sisr can update itself in place from a signed delta: it downloads only the chunks that changed, verifies every byte, and atomically swaps in the new binary. No toolchain, no erebus CLI, no extraction on the target machine — the update runs inside the binary itself.

DEV MACHINE                        TARGET MACHINE

erebus build ./app -o app.erebus \
  --enable-sisr --key …           ./app.erebus --erebus-update
  --update-url https://…            │  fetch manifest (HTTPS)
   │                                │  verify signature + Merkle root
   └─ publish to update server ───► │  download changed chunks
        app.erebus.manifest          │  SHA-256-verify every chunk
        chunks/<sha256>            │  atomic in-place swap
                                   ▼
                               app.erebus is now the new version

1. Build an updatable binary

erebus build ./my_app -o my_app.erebus \
    --enable-sisr \
    --key $XDG_DATA_HOME/erebus/keys/<fingerprint>.key \
    --update-url https://updates.example.com/my_app

Two artifacts are produced:

ArtifactPurpose
my_app.erebusSelf-extracting binary; self-updates against the channel
my_app.erebus.manifestSigned XBMR manifest, published to the server

2. Publish a release

Publish the manifest and the content-addressed chunks. Each chunk is served at <hash> = the 64-hex SHA-256 of its bytes, so a fetched chunk can be verified before use:

https://updates.example.com/my_app/
  manifest                     ← the .erebus.manifest (XBMR, signed)
  chunks/
    <64-hex-sha256>            ← one file per chunk
    <64-hex-sha256>
    …

Any HTTP server works (nginx, S3, a static CDN). HTTPS is recommended — the launcher uses TLS, though the trust anchor is the manifest signature and the content hashes, not the transport.

The publisher is responsible for keeping manifest and the chunks/ files in sync for the newest release.

3. Update on the target

# Uses the URL embedded at build time
./my_app.erebus --erebus-update

# Or point at a specific channel
./my_app.erebus --erebus-update https://updates.example.com/my_app

# Or override per-run via the environment
EREBUS_UPDATE_URL=https://updates.example.com/my_app ./my_app.erebus --erebus-update

Progress and statistics are printed on stderr (stdout is reserved for the app):

[erebus] update: fetching manifest from https://updates.example.com/my_app/manifest
[erebus] update: manifest verified (247 chunks)
[erebus]   fetched chunk 1/247 (65536 bytes)
[erebus]   fetched chunk 2/247 (65536 bytes)
…
[erebus] update applied: 203 chunks reused (12.7 MiB), 44 chunks fetched (2.8 MiB), total 247
[erebus] updated binary: /home/alice/app.erebus

The reused number is the bandwidth you saved: those chunks were already present in the running binary and were copied in place, never downloaded.

Other runtime flags

FlagEffect
--erebus-update [URL]Check the channel, verify, apply the delta, print stats, exit
--erebus-versionPrint the erebus stub and app versions, then exit

Both are reserved by erebus: they are intercepted by the launcher and are never forwarded to the application.

Security model

Nothing is trusted from the network:

  1. The manifest is verified with Ed25519 against the trusted keys in ~/.erebus/trusted-keys/ (same keys the binary signature uses) before a single byte is written.
  2. The Merkle root must match the manifest’s own chunk table.
  3. Every chunk — reused or downloaded — must SHA-256 to its manifest entry; wrong length or hash is rejected on the spot.
  4. The swap is atomic: any failure (bad signature, missing chunk, power loss) leaves the previous binary intact and runnable.
  5. The first run of the new version is supervised (mission 8): if it crashes during the startup window, the previous version is restored automatically and a failing release is quarantined so it is not re-installed.

Failure behavior

SituationOutcome
Manifest missing / bad magic / bad URLupdate refused, binary untouched
Signature fails (key not trusted)update refused before any write
Merkle root mismatchupdate refused before any write
Chunk wrong length or SHA-256engine errors, binary untouched
Chunk 404s on the serverengine errors, binary untouched
Interruption mid-updateprevious binary intact
New version crashes at startup.bak restored, previous version runs
Release fails EREBUS_HEALTH_MAX_ATTEMPTS timesquarantined, installs refused
Re-install of a quarantined releaserefused before any write

The running binary is always the last valid version — there is no “half-updated” state, and a broken release cannot wedge a target machine.

More