1 Updating
Miko edited this page 2026-10-31 00:30:48 +00:00

Updating

How releases are published

Every release is published on the project's Forgejo, GitHub, and GitLab, with builds for ARM64 and AMD64. Each build comes with a small manifest (the version and the build's SHA-256 checksum) and that manifest's signature. Each published release is then mirrored to the project's static mirror: the version's files, the channel's binaries, and the channel's signed pointer manifests last.

A release is one edit: internal/app/version.txt. Nothing else in the repository repeats the version. Versions are four plain numbers, stable.major.feature.fix: a fix or a small addition bumps the last number, a feature the third, a major version the second. The first number stays 0 until there is a feature-complete stable release. A development build adds a suffix (0.4.2.0-dev).

Updating a running install

sudo /opt/evesynapse/evesynapse -update          # right build for this machine
sudo /opt/evesynapse/evesynapse -update -arm64   # ARM build explicitly
sudo /opt/evesynapse/evesynapse -update -amd64   # Intel/AMD build (-x86, -x64 also work)

The updater first checks the latest release's signature and refuses a release that is not signed with the project's release key. Then it compares versions. If they are the same, it says so and stops. If the release is newer, it downloads the build, verifies it against the checksum in the signed manifest, checks it is built for the right kind of computer, swaps it into place, restarts the running server onto it, and reports the new version.

The updater reads releases from the sources EVESYNAPSE_UPDATE_PROVIDER lists, in the order listed: no source is preferred beyond that order. The newest signed release across the sources wins, a tie goes to the earlier-listed source, and the manifest, its signature, and the build all come from that one source's release, verified by the same signatures and checksums whichever source serves them. An update run reads out each source it checks and the version it found there, then the download:

github    https://api.github.com/repos/natemsz/evesynapse          v0.7.0.10
gitlab    https://gitlab.com/api/v4/projects/natemsz%2Fevesynapse  v0.7.0.10
forgejo   https://natems.dev/api/v1/repos/EveSynapse/evesynapse    v0.7.0.10
mirror    https://cdn.synap6.io                                    v0.7.0.10
A new version is available: v0.7.0.10.
Signature verified: [email protected] / natemsz, SHA256:...

Total download size: 54.0 MiB
Get: evesynapse-amd64 from github [54.0 MiB]

With the setting unset, the updater walks a built-in fallback list (github, gitlab, forgejo) and asks the mirror only when no forge produced a signed release.

There is also a manual form that installs a specific build, from an address with the checksum published for it, or from a local file. The manual form checks what you give it and no signature: it is your own word for that build.

sudo /opt/evesynapse/evesynapse -update <url> <sha256>
sudo /opt/evesynapse/evesynapse -update <file> [sha256]

Development builds

Builds from the evesynapse-dev branch carry a version ending in -dev and are published as prereleases, which a plain -update never installs. To follow them on a test box:

sudo /opt/evesynapse/evesynapse -update -dev

A plain -update from a development build goes back to the latest release once that release's number catches up.

Release signing

Every release is signed, and the updater installs nothing that is not.

  • What is signed. Each build's manifest, latest-<arch>.json: the version, the kind of computer, and the build's SHA-256. Its signature sits beside it as latest-<arch>.json.sig. Because the checksum is inside what is signed, the signature covers every byte of the build.
  • With what. An Ed25519 key. Its private half exists only as the project's RELEASE_SIGNING_KEY CI secret, which the release job signs with. Its public half is internal/releasesig/trusted_keys.pem, compiled into every build.
  • What the updater does with it. It fetches the manifest and the signature, checks the signature against the keys it was built with, and only then reads the manifest. A release that is unsigned, signed with another key, or changed after signing is refused and nothing is downloaded. An older release offered again is still genuinely signed, and is turned down by the version comparison instead.
  • What it proves, and what it does not. That the release was published by this repository's release job. Someone who can replace the files of a release, but cannot run that job with the key, can no longer get a build installed. It is no protection against someone who controls the repository itself, since they control what the job signs.

To check a release by hand:

go run ./cmd/releasesign verify latest-arm64.json
sha256sum evesynapse-arm64   # must match the "sha256" in latest-arm64.json

The README's Release signing section covers making the key, replacing it, and recovering when it is lost.

Forks

By default the updater checks the mainline project's releases. To have it check your fork instead, set EVESYNAPSE_UPDATE_PROJECT (the setup script writes it for you when you install from a fork). The pipelines are already in the repository: the mainline publishes through the Forgejo release workflow, and .gitlab-ci.yml carries the same release contract for a GitLab-hosted fork.

A fork signs its releases with its own key, and a mainline build refuses a fork's releases, since they are not signed with the key it trusts. Install the fork's build first (its setup script does that), and it updates from the fork from then on.