SynapSynapDocs

Upgrades

Update a self-hosted pod with synap update, choose a release channel, turn on automatic updates, and read the outcome.

For Self-hostersOpen-source podReviewed 2026-10-20

Pods are updated from published releases. Each release has a signed manifest that pins every image by digest, so an update installs exactly what was tested.

Update now

cd /opt/synap/deploy
sudo synap update                     # the default channel: SYNAP_UPDATE_CHANNEL, else stable
sudo synap update --release stable    # the latest tagged release
sudo synap update --release fast      # the latest successful build of main
sudo synap update --release v1.1.3    # one specific release
OptionMeaning
--release <ref>A release ID (vX.Y.Z or main-<sha>) or a channel (stable, fast).
--forceRe-apply the release the pod is already on.
--from-sourceBuild the checkout as images and apply it like a release. For development on a clone.

An update never falls back to building images on the server: without --from-source it only pulls the release's images, and a failed pull stops the update before anything changes.

Options from older versions are still accepted, so scripts keep working: --build, -b, --local and -l mean --from-source; --version <ref>, -v <ref> and a bare <ref> mean --release <ref>; latest means the default channel; --from-image is ignored.

What an update does

Every update runs the same steps:

  1. Takes the update lock, so two updates never run at once.
  2. Fetches the release manifest and checks its signature (see Verifying releases).
  3. Checks free disk space (at least 2 GB by default) and pulls the images by digest. A failed pull stops here, before anything changed.
  4. Takes a verified pre-update dump of every database.
  5. Runs database migrations.
  6. Starts the new backend as a canary and checks it.
  7. Swaps the backend, brings up every other service and verifies that they are healthy.
  8. Records the outcome.

If any step fails, the update rolls back to the previous images, and restores the pre-update dump when the migrations had already changed the database.

The outcome

Every update writes its result to deploy/state/last-update.json. After a rollback (rolled_back, rollback_failed or failed), every pod admin gets an in-app notification.

Automatic updates

Automatic updates on a self-hosted pod run from systemd. Install the units, with automatic updates on:

sudo synap units install --enable-auto-update
sudo synap units status

This installs:

  • synap-heal.timer: every 2 minutes, restarts this pod's unhealthy containers, within a budget (never PostgreSQL).
  • synap-update.path: applies update requests written to deploy/state/requests/update.json.
  • synap-compose.path (releases after v1.1.3): applies service requests from the pod agent, written to deploy/state/requests/compose.json.
  • synap-update.timer (only with --enable-auto-update): once a night, from 03:00, applies the latest release of the pod's channel within the update window.

The automatic run reads deploy/state/update-policy.json: auto (false turns it off), pinned (true holds the pod on its release), channel and window (default 03:00-05:00). Automatic updates always require a valid release signature (SYNAP_RELEASE_VERIFY=enforce).

Without systemd, synap units install prints a cron line for the heal task instead; updates are then manual.

Release channels

ChannelWhat it follows
stableTagged releases (v*). The default.
fastEvery successful build of the main branch.

Set the default channel for synap update with sudo synap config set SYNAP_UPDATE_CHANNEL=fast.

Before a release with upgrade notes

Some releases change something you operate, for example a new setting or a new outbound connection. These are listed in the "Upgrade notes" of deploy/README.md in the backend repository, newest first. Read them before moving across several releases at once.

On this page