Upgrade
Last updated on October 22, 2026
You upgrade by re-running the deploy script. It pulls the Docker images from the stable release channel, applies any database migrations, and restarts the stack. Data and auto-generated secrets in .env are preserved across the upgrade.
Back up your data before upgrading. Downgrades are not supported, so a backup is the only way to roll back. See Backups.
Release channels
TofuPilot cloud releases continuously, and every release publishes a versioned Docker image. Self-hosted instances follow a separate stable channel instead of tracking each release:
- stable is the default. About once a month, a version that has run in production is promoted to the channel. Running the deploy script with no options installs or upgrades to the current stable release. Security fixes and critical bug fixes are promoted out of cycle when needed.
- A pinned version opts out of the channel. Passing
--version <version>installs that exact release, including releases newer than the current stable one. Use--list-versionsto see what is available; the stable release is marked in the listing.
If your instance runs a version newer than the current stable release, for example after pinning a recent version, re-running the script keeps your version and the instance rejoins the channel at the next promotion. Each stable promotion ships with release notes describing what changed for users and what changed operationally.
Upgrade to the stable release
SSH into your server, change to the directory that holds your .env, and run:
curl -fsSL https://www.tofupilot.com/deploy | bashThe script reports the new running version to Orbit once the upgrade finishes. You can also re-deploy or trigger an upgrade from the instance menu in Orbit.
Pin a specific version
To install a fixed version instead of the stable release, for example a newer release that has not been promoted yet, list the available versions:
curl -fsSL https://www.tofupilot.com/deploy | bash -s -- --list-versionsThen pass the version explicitly. Downgrades are rejected; re-running the currently installed version is accepted, which you can use to repair an install:
curl -fsSL https://www.tofupilot.com/deploy | bash -s -- --version <version>Enable realtime views
Realtime updates over WebSocket were added in 2.33. When you upgrade an instance created before that version, add the realtime subdomain so live station status and telemetry, dashboard updates, and streaming build logs work:
- Create a DNS A record for
CENTRIFUGO_DOMAIN_NAMEpointing to your server. It defaults torealtime.<DOMAIN_NAME>(e.g.realtime.tofupilot.yourcompany.com). - Re-run the deploy script. It provisions the
tofupilot-centrifugocontainer and generates theCENTRIFUGO_*secrets in.envautomatically. - Confirm the realtime server is up:
docker compose logs tofupilot-centrifugo --tail 50- Verify the endpoint is reachable over TLS. A
400response is expected — it means the certificate issued and the server is waiting for a WebSocket upgrade:
curl -s -o /dev/null -w '%{http_code}' https://<CENTRIFUGO_DOMAIN_NAME>/connection/websocketThe rest of the application works without the realtime subdomain; only the live views fall back to manual refresh. See Realtime views not updating for troubleshooting.
Upgrade the realtime channels (2.45)
Dashboard 2.45 changes how stations and the dashboard talk over the realtime server: one channel per kind of traffic, commands that only the server may publish, and live cursors on the operator screen. Two things to do, in this order:
- Re-run the deploy script. It rewrites
centrifugo-config.jsonand the compose service with the new channel namespaces and publish proxies, then recreates the realtime server. The new config keeps the channels older dashboards use, so running it while the stable channel still serves an older dashboard is safe: live views keep working before and after the dashboard moves to 2.45. - Update the station CLIs to 2.1.0 or newer. An older station keeps running tests, uploading runs and receiving deployments (within 15 minutes), but has no live view, takes no commands from the dashboard (run, stop, pull now, settings changes), and its deployment status on the dashboard is not updated. Stations with self-update on move by themselves.
Upgrade the server first. Stations on CLI 2.0 and older update to the latest CLI on their own, whatever your server runs, and CLI 2.1.0 has no live view with a server older than 2.45. To keep stations on their current CLI until the server is upgraded, set TOFUPILOT_NO_UPDATE=1 on them. From 2.1.0 on, a station holds such an update by itself (see below).
Station and dashboard compatibility
Stations and the dashboard agree on a realtime protocol version each time a station connects. When they do not speak the same version, the station keeps running tests, uploading runs and receiving deployments (within 15 minutes); its live view, its deployment status and the commands sent from the dashboard (settings changes included) are off, and the station page says which side to upgrade:
| Station page says | Meaning | Fix |
|---|---|---|
| The station CLI is out of date | The station's CLI is older than this dashboard supports | The station updates itself, or run tofupilot update on it |
| This TofuPilot server is out of date | The station's CLI is newer than this dashboard | Upgrade this server: re-run the deploy script |
| The realtime server is not configured for this dashboard | The Centrifugo config predates the dashboard | Re-run the deploy script |
From CLI 2.1.0 on, a station does not install an automatic update that would break a working live link: while your server speaks an older protocol, the station stays on its current CLI and logs Update to vX held. Upgrade the server and the station updates itself within the next update check. tofupilot update installs the newer CLI anyway.
| Realtime protocol | Dashboard | Station CLI |
|---|---|---|
| 1 | up to 2.44 | up to 2.0 |
| 2 | 2.45 and newer | 2.1 and newer |
Verify the upgrade
Check that every container is running and the dashboard reports the new version:
docker compose psdocker compose logs tofupilot-dashboard --tail 100If a container fails to start, inspect its logs with docker compose logs <container> and see Troubleshooting.
How is this guide?