Menu

Updates and rollback

A node you installed with the installer keeps itself up to date. This page shows what happens each night, how to update by hand, and how to go back to the version before.

Dassie is early, and releases come often. Most of the time you don't need to do anything: the node checks for a newer release, checks its signature, switches to it, and goes back by itself if the new version doesn't start.

On this page
  1. The nightly update
  2. What the last update did
  3. Update now
  4. Update to one version
  5. If a new version doesn't start
  6. Going back by hand
  7. Choosing the hour
  8. Keeping up with the network
  9. On NixOS and in the desktop app

The nightly update

The installer sets up a systemd timer, dassie-update.timer. It runs dassie update once a day, at a random time in the hour after 03:20 by the server's clock. If the server was off at that time, the timer runs as soon as it is back.

Each run:

  1. asks the mirror, get.dassie.land, for the newest version, and stops there unless it is newer than the one running;
  2. downloads that release's list of checksums and checks its signature against the release key built into your dassie binary, then checks the download against its checksum, before it unpacks anything;
  3. unpacks the new version into /opt/dassie/<version> and asks it to check itself (dassie verify-install);
  4. installs that version's systemd units, points /opt/dassie/current at it, and restarts the node;
  5. waits for the node to say it is ready, for up to five minutes. If it doesn't, the update goes back to the version before (below).

The mirror can hold back a release, but it can't make your node install anything the release key didn't sign, and it can't move your node to an older version. Only you can, by naming one. Releases you can trust explains why.

After an update, the new version and the one before it stay in /opt/dassie. Older ones are removed.

What the last update did

dassie status ends with a line about the last update:

$dassie status
# …
  Updates      checked 2026-10-28 03:41 UTC: up to date

It says whether the node was up to date, which version it updated to, or why an update failed or went back. The update writes this record to /opt/dassie/last-update, and its full output goes to the journal:

$journalctl -u dassie-update

To see when the next run is due:

$systemctl list-timers dassie-update.timer

Update now

To update right away, without waiting for the night:

$sudo dassie update

It runs as root, since it writes to /opt/dassie and to the systemd units. It does exactly what the nightly run does, and prints each step. If the newest version is the one running, it says so and changes nothing.

Only one update runs at a time. If the timer's run is still going, a second one stops with another update is running; try again once it is done. The installer takes the same lock: if an update is running, it stops and asks you to run it again once the update is done.

Update to one version

To install one particular release, newer or older, name it:

$sudo dassie update --target-version <version>

A version is three numbers, such as 0.3.0. The release must be on the mirror, and its signature is checked as for any update. The installer takes the same option under the same name, so a new server can start on the version your others run:

$curl --proto =https --tlsv1.2 -sSf https://sh.dassie.land | sh -s -- --target-version <version>

The other options of dassie update:

Option What it does
-f, --force Installs the mirror's newest version even if it isn't newer, or if it didn't start here before.
-t, --target-version <v> Installs this version instead of the newest.
--mirror <url> Uses another mirror, which must be an https:// URL. Without it, the update uses DASSIE_MIRROR_URL, or else https://get.dassie.land. A mirror of your own may be on a private network; DASSIE_MIRROR_CA_FILE adds a root certificate to trust it by.
--no-restart Installs the version and switches to it, but leaves systemd alone: the new version runs from the node's next start.
--unit <name>.service=<dir> For a host that runs nodes under units of its own: restarts this unit, whose node keeps its data in <dir>, instead of dassie.service, and installs none of the release's units. Repeat it for each node, up to eight.

The dassie command lists them with the rest of the commands.

If a new version doesn't start

A node is ready once it has started its engine on its database. If the new version doesn't get there within five minutes, the update:

  1. removes the systemd units the new version added;
  2. points /opt/dassie/current back at the version before, with that version's units;
  3. puts back the node's database from just before the new version changed it, if it did and the old version can't read it as it is;
  4. starts the old version again.

A new version may change the database's layout when it starts. An older version refuses a database newer than it knows, so the node keeps a copy from just before the change, dassie.sqlite3.pre-migration, in its data directory. The node makes that copy before it talks to anyone, so nothing the copy lacks has reached a peer. When a rollback puts it back, the database the new version left stays beside it as dassie.sqlite3.rolled-back, for you to look at.

dassie status then says which version didn't start and why. The node doesn't try that version again: the nightly update waits until the mirror offers a newer one. If you think the problem is gone, try it again yourself:

$sudo dassie update --force

Why it works this way and what the updater trusts.

Going back by hand

If a new version starts but misbehaves, go back to the version you ran before by naming it:

$sudo dassie update --target-version <version before>

Then stop the nightly update, or it moves the node forward again the next night:

$sudo systemctl disable --now dassie-update.timer

This works when the older version can read the database. If the newer version changed the database's layout, the older one refuses it and doesn't start, and the update returns to the newer version, as it does whenever a version doesn't come up. The copy from before the change, dassie.sqlite3.pre-migration, is still in the data directory, but it lacks everything the node did since. Putting it back by hand makes the node forget payments and settlements its peers remember, so ask for help before you do.

When you're ready to follow releases again:

$sudo systemctl enable --now dassie-update.timer
$sudo dassie update

Choosing the hour

If you run several nodes, you may want them to update at different times, so that only one restarts at once. Change the timer in a drop-in, which updates leave alone:

$sudo systemctl edit dassie-update.timer
/etc/systemd/system/dassie-update.timer.d/override.conf
[Timer]
# Clear the release's time, then set your own.
OnCalendar=
OnCalendar=*-*-* 05:00:00
RandomizedDelaySec=30min

Keeping up with the network

Nodes talk to each other in a protocol with a version, which the two agree on when they connect. When a release brings a new version of the protocol, it still speaks the one before, for one release cycle, so updated nodes and nodes that haven't updated yet keep talking while the network updates. The release after that drops the old version.

0.3.0 is the one exception. It speaks version 2, dassie/2, and nothing else, so a node on 0.3.0 doesn't talk to a node on a 0.2 release at all. The test network moved to version 2 all at once, when it was reset (below).

So a node that misses a whole release cycle, because it was down or its updates were off or kept failing, can't reach updated nodes any more. Its peerings end, and it peers again only once it updates. The nightly update keeps this from happening; if you turn it off, update by hand at least once per release.

Protocol versions explains more, and Release notes says what each release changed.

Why it works this way

A node from the 0.2 releases

A node still on a release before 0.3.0, a 0.2 one or a 0.1 one, can't update to 0.3.0 in place. Those releases ran the early test network, and 0.3.0 reads neither their database nor their recovery phrases. If the old updater installs it, the new version refuses the database and doesn't start, and the update goes back to the old release.

Staying on the old release doesn't work either. The test network was reset for 0.3.0: its bootstrap nodes have new IDs, and nodes on 0.3.0 don't speak the protocol of the earlier releases, so the old node finds no one to peer with. The notes for 0.3.0 say what else changed.

Set the node up again instead, with a new phrase. It starts with a new node ID and empty books; nothing carries over from the old node. Its data was test money only.

  1. Stop the node, its sockets and the updater, and move the node's data aside:

    $sudo systemctl stop dassie-update.timer dassie.service dassie-http.socket dassie-https.socket dassie-ipc.socket dassie-quic.socket dassie-feed.socket
    $sudo mv /var/lib/private/dassie /var/lib/private/dassie-0.2
  2. Install the newest release, which starts the node on an empty data directory:

    $curl --proto =https --tlsv1.2 -sSf https://sh.dassie.land | sh
  3. Set the node up with a new phrase, as for a new node (Quick Start).

Why nothing carries over

On NixOS and in the desktop app

dassie update updates only a node the installer put in /opt/dassie. On NixOS, the flake's version is the node's: you update by changing the flake input, and go back by going back a generation. Dassie on NixOS shows how.

The desktop app doesn't update itself yet. What's next

A kopje of granite blocks against the sun, in veld grass; one dassie climbs its slab, one keeps lookout on top inside the sun, and one sleeps on the next rock; on a wide screen, a pair sits on a kopje to the left