-
Notifications
You must be signed in to change notification settings - Fork 0
features updates
Active contributors: elwina
Capto ships self-updates through the Tauri updater plugin (tauri-plugin-updater) with minisign signature verification. In-app checks hit the Cloudflare Worker mirror first and fall back to the raw GitHub release manifest, so the app updates reliably even when a single host is down. Releases are signed by the maintainer and verified locally against a pinned public key.
Installed users need a way to move to new versions without downloading installers by hand. The updater gives the desktop app a check-and-install loop: it fetches a latest.json manifest, compares it to the running version, downloads the signed installer, installs passively, and relaunches. The whole flow is local-first in the sense that nothing is required to work, if both endpoints fail, the app simply keeps running and the user checks again later.
The updater config lives in apps/desktop/src-tauri/tauri.conf.json under plugins.updater. It declares a minisign public key and an ordered list of check endpoints:
-
https://capto-update-proxy.elwina-vardal.workers.dev/updates/latest.json(Cloudflare Worker) -
https://github.com/elwina/Capto/releases/download/updater/latest.json(GitHub)
The Tauri updater tries endpoints in order and only falls through on a non-2XX response. Listing the worker first means updates ride Cloudflare's CDN by default; the GitHub URL is the fallback if the worker is down. Each manifest's installer urls point at the versioned v* release assets on GitHub. The Cloudflare worker itself is covered on Updater mirror.
Every latest.json is signed with minisign. The public key is baked into apps/desktop/src-tauri/tauri.conf.json (plugins.updater.pubkey). The matching private key is the GitHub Actions secret TAURI_SIGNING_PRIVATE_KEY (with an optional empty TAURI_SIGNING_PRIVATE_KEY_PASSWORD); a gitignored local copy lives at .secrets/capto.key and must never be committed. The desktop refuses an unsigned or wrongly signed update, which is what makes the whole channel safe to mirror through a third-party CDN.
The Release workflow mirrors each release's latest.json onto a rolling Git tag named updater. Only the manifest is published to that tag, so the in-app check URL stays stable across releases: users always ask the same endpoint and get whatever the newest published version is. This is described in docs/CI.md under "In-app updates (GitHub)".
New versions can be rolled out in stages before hitting all users. The procedure, documented in docs/CI.md, is:
- Publish an experimental build to a rolling
canaryrelease tag with its ownlatest.json(gh release create canary --prereleaseplus uploadlatest.json). - Point testers or pilot agents at
https://capto-update-proxy.elwina-vardal.workers.dev/updates/canary.json, which the worker serves from thecanarytag. - Validate the canary (record/QA round trips plus crash reports), then promote: publish that same version's
latest.jsonto theupdatertag so stable users move off canary automatically, and close the canary tag once superseded.
A bad canary never reaches stable users and can be pulled by deleting the canary tag or manifest.
Current version is 1.0.0 (stable). v1.* releases are stable; v0.* were prerelease. The updater targets the same versions, canary and stable builds follow the versioning rules set out in Deployment.
The relevant keys in apps/desktop/src-tauri/tauri.conf.json:
| Key | Value |
|---|---|
plugins.updater.pubkey |
Minisign public key (line-based key body) |
plugins.updater.endpoints[0] |
Cloudflare Worker latest.json
|
plugins.updater.endpoints[1] |
GitHub updater tag latest.json
|
plugins.updater.windows.installMode |
passive (installs without interactive prompts), then relaunch |
The About tab exposes the update flow in the React UI:
-
apps/desktop/src/components/UpdateSettings.tsx, a manual "check for updates" button plus an install button when an update is available. It reports checking / up-to-date / available / downloading (with percent) / installing / error phases, and callsrelaunch()after download-and-install. -
apps/desktop/src/components/AboutPanel.tsx, embedsUpdateSettings, shows the app version via the Tauri app API, and displays the bundled FFmpeg bundle version (from theget_ffmpeg_infocommand) plus the FFmpeg binary version, path, and source repository link. It also links the project source, license, and developer pages.
Settings UI: the About tab shows version, a manual update check, the bundled FFmpeg version, and developer links (per docs/CI.md).
If the minisign private key is lost or leaked, the public key in apps/desktop/src-tauri/tauri.conf.json must be rotated in the same release. After a public-key change, existing installs cannot verify new signatures unless you also ship a bridge release, so rotations should be rare and deliberate. The full guidance lives in docs/CI.md.
-
Updater mirror, the Cloudflare Worker that serves the worker endpoint and mirrors the
canary.jsonroute. -
Deployment, the Release workflow that produces signed updater artifacts and the rolling
updatermanifest. - The About panel and update settings both live in
apps/desktop/src/and call the Tauri updater andget_ffmpeg_infocommands.
- To change check endpoints, edit
plugins.updater.endpointsinapps/desktop/src-tauri/tauri.conf.json. - To change the update UI, edit
apps/desktop/src/components/UpdateSettings.tsxandapps/desktop/src/components/AboutPanel.tsx. - To change the rollout procedure or signing steps, edit
docs/CI.mdand.github/workflows/release.yml.
| File | Purpose |
|---|---|
apps/desktop/src-tauri/tauri.conf.json |
Updater plugin: pubkey, ordered endpoints, Windows install mode |
apps/desktop/src/components/UpdateSettings.tsx |
Manual check + install/relaunch UI with progress states |
apps/desktop/src/components/AboutPanel.tsx |
App version, FFmpeg bundle info, developer links, embeds UpdateSettings |
.github/workflows/release.yml |
Builds signed updater artifacts and mirrors latest.json onto the rolling updater tag |
.secrets/capto.key |
Gitignored local minisign private key (never committed) |
docs/CI.md |
Updater, canary staged rollout, and key-rotation guidance |