Updates and release channels
Two things update independently, with two different commands:
- The
tritonadmbinary on your workstation or head node.tritonadm self-updatereplaces it. - The deployed cloud, which is the control-plane zones and the agents
on every node.
tritonadm updatereprovisions the zones and refreshes the agents.
Both commands read the same signed release channel, so this page starts with the channel. For the order to run them in on a live cluster, see Apply an update.
How a channel works
A channel is a minisign-signed JSON manifest published at
https://tritoncloud.nyc3.digitaloceanspaces.com/channels/<NAME>.json. A
detached signature is published at the same URL plus .minisig. Continuous
integration publishes two named channels:
| Channel | Published from |
|---|---|
edge | Builds of main. |
stable | Builds from a v* tag. |
A channel exists only after something is published to it. stable
resolves only after a tagged build has run. No tagged build has been
published yet, so pass --channel edge to genesis.
setup bootstrap and setup apply fall back to stable when you pass
neither --channel nor --channel-url. setup converge with no channel flag
and no --image-dir reads the channel the cluster follows, and falls back to
stable when it cannot read one. Every other command that reads the
channel falls back to the channel the cluster follows, the
channel.upstream_url setting, read through tritond. With no session,
those commands fail with this message:
no --channel given, and the cluster's channel could not be read; pass `--channel edge` (or `stable`, or `--channel-url URL`)
The manifest declares a schema version, the channel name, an updated_at
timestamp, a publisher string, an optional sealed revision, and four
artifact maps: images, agents, services, and tritonadm. Every
artifact entry has a build stamp in YYYYMMDDTHHMMSSZ form, a lowercase hex
sha256, and a size in bytes. Agent, service, and tritonadm entries have
one url. An image entry has a manifest_url and a content_url.
tritonadm understands schema version 1. It refuses a manifest that
declares a higher schema version and does not parse it.
What tritonadm verifies
Every channel fetch that tritonadm performs downloads both the manifest
and its .minisig. It verifies the signature against the publisher public
key compiled into the binary from cli/tritonadm/publisher.pub (minisign
key id 6A95AFF9C8B898E7). A signature that does not verify stops the
command with channel signature did NOT verify against the publisher pubkey.
tritonadm then compares the downloaded artifact bytes against the sha256
in that signed manifest.
The tools/install.sh bootstrap script does not perform this check. It
verifies the sha256 of the tritonadm tarball against the channel JSON it
fetched over TLS, and nothing more. Its trust root is TLS to the channel
host. Every later channel fetch by tritonadm itself, including
self-update --check, enforces the publisher signature. See
Install the tritonadm CLI.
Select a channel
Three flags select the manifest. They appear on install, update, and
self-update. versions and channel revisions accept --channel and
--channel-url.
| Flag | Effect |
|---|---|
--channel <NAME> | Expands to https://tritoncloud.nyc3.digitaloceanspaces.com/channels/<NAME>.json. |
--channel-url <URL> | Uses this manifest URL as given. Takes precedence over --channel. |
--revision <REV> | Points the resolved URL at the frozen snapshot .../channels/<NAME>/<REV>.json. |
The CLI config file does not store the selection. The cluster does, in its
channel.upstream_url setting. A genesis from the channel sets it to the
channel it installed from. tritonadm setup converge sets it when it is
unset. An --image-dir genesis leaves it unset. To change the channel the
cluster follows, on any host with a signed-in tritonadm:
tritonadm config set channel.upstream_url https://tritoncloud.nyc3.digitaloceanspaces.com/channels/edge.json
update, self-update, and self-update --check then need no channel
flag.
tritonadm channel refresh then fetches the upstream and verifies it
against the publisher key. It signs the manifest again with the cluster's
own channel-signing key and publishes it in the cluster. Compute nodes fetch
from the booter's mirror, never from the upstream. --revision <STAMP> pins
the mirror to a sealed revision. --no-wait returns the operation id instead
of waiting.
Check what is installed
The CLI
Run this on any host where tritonadm is installed.
tritonadm self-update --check
The command prints the stamp compiled into the running binary and the stamp that the channel advertises for this binary's target triple.
installed: <INSTALLED_STAMP>
candidate: <CANDIDATE_STAMP> (<BYTES> bytes)
When the two stamps match, the command prints already up to date and exits
zero. When they differ, --check exits non-zero. You can use this exit code
as a gate in automation.
tritonadm --version prints the crate version from Cargo.toml. The
channel identifies builds by stamp, not by that version. self-update --check
is the comparison that matters.
The channel contents and the host
On the head node, in the global zone, as root:
tritonadm install --list
The command prints the channel name and updated_at, then the images,
agents, and tritonadm maps. It reads the installed status from the host:
imgadm list -H -o uuid for images, and /opt/triton/<NAME>/etc/version
for agents.
The deployed components
On the head node, in the global zone, as root:
tritonadm versions
The command shows the control plane's build and image, every other
registered infra zone against the channel's triton-platform image, each
node's agent and sandbox runtime, and each gateway zone against the gateway
image pin, and marks drift. The infra zones are the boot service, ClickHouse,
DNS edge, each FoundationDB member, mantad, notifyd, the portal, and the
MantaFS masters and storage zones, one row each, labeled by kind. A zone of a
kind this build of tritonadm does not know has no target. Its targets come from the cluster's channel unless --channel
or --channel-url names another.
Update the CLI
Run self-update as a user that can write to the install directory. On a
head node that directory is /opt/triton/bin, so run it as root.
tritonadm self-update
The sequence is:
- Resolve the channel URL from
--channel-url,--channel, the cluster'schannel.upstream_url, and--revision. - Fetch the manifest and its
.minisig. Verify the signature against the compiled-in publisher key. - Find the entry for this binary's target triple. The triple is compiled in,
not detected at run time. A channel with no entry for it fails with
channel has no tritonadm entry for target <TARGET>. - Compare the entry's stamp with the compiled-in build stamp. Stop if they match. Any stamp that differs is installed, older or newer.
- Download the tarball. Verify its sha256 against the signed manifest.
Extract the
tritonadmbinary from the top level of the archive. - Run the extracted binary's hidden
api-versioncommand, and send one request carrying that admin API version to the runningtritond.tritondanswers it before authentication. Whentritonddoes not serve that version, or cannot be asked, stop and change nothing, unless--force. A build older than theapi-versioncommand speaks an older version and is not checked. With notritondto ask, the command prints a warning and skips the check.--image-diris not checked. - Replace the binary atomically.
The replacement copies the new binary to <INSTALL_DIR>/tritonadm.new. It
renames the live binary to <INSTALL_DIR>/tritonadm.prev. Then it renames
.new over tritonadm. Both the extracted binary and the staged copy get
mode 0755. A lock on <INSTALL_DIR>/tritonadm.lock keeps two swaps or
rollbacks from running at once. The command prints where the new binary is
and where the previous binary is kept.
tritonadm updated at <INSTALL_DIR>/tritonadm
previous binary preserved at <INSTALL_DIR>/tritonadm.prev; `tritonadm self-update --rollback` puts it back
When tritond does not serve the candidate's admin API, the command fails
and changes nothing:
the candidate speaks admin API <VERSION>, which the running tritond does not serve yet. Update tritond first (`tritonadm update tritond`), then self-update; --force swaps it anyway
| Flag | Effect |
|---|---|
--channel-url <URL> | Override the channel manifest URL. |
--channel <NAME> | Named channel. --channel-url takes precedence. |
--revision <REV> | Update to, or roll back to, the frozen snapshot of a sealed revision. |
--install-dir <DIR> | Override the install directory. Defaults to the directory that contains the running executable. |
--check | Report installed against candidate and exit. Exits non-zero when they differ. |
--image-dir <DIR> | Use the newest local tritonadm-<STAMP>.tar.gz instead of the channel. Conflicts with --channel-url, --channel, and --revision. |
--in-cluster | Use the in-cluster channel. Conflicts with --channel-url, --channel, --revision, and --image-dir. |
--rollback | Put tritonadm.prev back in place of the running binary. Conflicts with the source flags and --check. |
--force | Swap in a build that the running tritond does not serve, or that the command could not check. |
Roll back the CLI
tritonadm.prev survives one update cycle, so you can reverse a bad release
without a download. On the host where the binary is installed, as a user that
can write to its directory:
tritonadm self-update --rollback
Output:
rolled back <INSTALL_DIR>/tritonadm to the previous build
the replaced binary is now <INSTALL_DIR>/tritonadm.prev
A second --rollback undoes the first. With no tritonadm.prev, the
command fails with no <INSTALL_DIR>/tritonadm.prev to roll back to. To go
back further, run tritonadm self-update --revision <REV> with a
known-good sealed revision.
A tritonadm built against a newer admin API version than the running
tritond serves fails every request with
error (ApiVersionUnsupported): server does not support this API version: <VERSION>
and exit status 5. Roll it back, update tritond, then update the CLI
again.
Update the deployed cloud
tritonadm update reprovisions and restarts running control-plane
components. A zone reprovision replaces the immutable zone root and reboots
the zone. NICs, customer_metadata, and a delegated /data dataset
survive. Plan for the control plane to be unavailable while the command
runs.
Run update on the head node, in the global zone, as root. Plan first:
tritonadm update --check
Then apply:
tritonadm update
The whole-fleet run
With no component, or with components drawn only from tritonadm, tritond,
adminui, control-plane, and agents that include at least one of the last
four, update runs one whole-fleet plan. tritonadm update tritonadm on its own
updates the local binary instead, like self-update:
- Print the channel and revision, and a plan for every node.
- Check that each node's agent and the control plane keep a fleet API
version in common. A plan that breaks that is refused unless you pass
--force. - Ask
Proceed?once, unless you pass--yes. - When the run includes
tritonadmand the runningtritondserves the new build's admin API, replace it, then run the new binary with the same arguments, pinned to the planned revision. Whentritonddoes not serve it, or cannot be asked, keep the installed binary for steps 5 to 7 and replace it after step 7. - Refresh the in-cluster channel and wait for the boot service mirrors.
- Snapshot the control-plane zone, then reprovision it from
triton-platform. - Refresh the agent on every selected node, and the sandbox runtime on each node that runs sandboxes or has a bundle.
- Print what each node runs.
tritond, adminui, and control-plane limit the run to the control
plane, and agents limits it to the agents. --check and --dry-run stop
after the plan. The whole-fleet run refuses a --channel or --channel-url
that differs from the cluster's channel.upstream_url, because nodes
update from the in-cluster copy of that channel.
| Flag | Effect |
|---|---|
--cn <CN> | Update the agent on this node only, by hostname or UUID. Repeatable. A named node is attempted even when its agent has gone quiet. |
--hold <CN> | Leave this node's agent and sandbox runtime as they are. Repeatable. |
--force | Run a plan that leaves a node's agent and the control plane with no fleet API version in common. For recovery. Selected agents are refreshed over SSH from the head node, so a node that is cut off still receives its refresh when the run includes agents. Held and unreachable nodes are not refreshed. |
--cn and --hold apply only to the whole-fleet run. With any other
component they fail, and the message names tritonadm update and
tritonadm update agents. Naming a host-local component together with a whole-fleet one fails, and the
message tells you to run them separately.
Host-local components
Every other component updates on the head node, as before. --all walks
them all in this order: tritond, tritonagent, proteusadm, fdb,
clickhouse, booter, dnsedge, portal, mantad, tritonadm. tritonadm runs
last because it replaces the binary that drives the run.
tritonadm update tritonagent proteusadm
| Component | Aliases | What the update does |
|---|---|---|
tritonadm | Delegates to self-update, with this run's channel or --image-dir. | |
tritond | Reprovisions the triton-tritond zone from the triton-platform image. Applies under --all, --image-dir, or --in-cluster. Named on its own, tritond takes the whole-fleet run. | |
adminui | admin-backend, ui | Reprovisions the same triton-tritond zone. Named on its own, adminui takes the whole-fleet run. The aliases stay host-local. |
tritonagent | agent | Extracts the agent bundle again under /opt/triton/tritonagent. Restarts its SMF service when the bundle changed. |
proteusadm | Extracts the bundle again. It has no SMF manifest, so no service is registered or restarted. | |
fdb | triton-fdb, triton-fdb0 | When the registry knows active FoundationDB members, tritond reprovisions each member on its own compute node, one at a time on a quorate cluster. Otherwise it reprovisions the local bootstrap zone from triton-platform. |
clickhouse | triton-clickhouse | Reprovisions the triton-clickhouse zone from the triton-platform image. |
booter | triton-booter, triton-booter0 | Reprovisions the triton-booter0 zone from the triton-platform image. |
dnsedge | triton-dnsedge, triton-dnsedge0 | Reprovisions the triton-dnsedge0 zone from the triton-platform image. Authoritative DNS stops until the zone is back. |
portal | triton-portal, triton-portal0 | Reprovisions the triton-portal0 zone on this head node from the triton-platform image. When the zone's triton:portal_static_dir names a hand-copied UI, it clears that key and reboots the zone, so the portal serves the UI built into the image. Then it records the image in the zone's registration. A portal zone on another node is not updated. |
mantad | triton-mantad | When a managed mantad deployment exists, tritond reprovisions one member at a time. Otherwise it reprovisions every contiguous local triton-mantadN zone from triton-platform. |
How a host-local run behaves
update first plans every component without changes and prints a preview
for each. Then it applies. Consequences of that split:
--checkand--dry-runstop after the preview and change nothing.- An artifact that is missing from the source is reported as a skip that
names the source. It is not an error. An agent reports
not in channel; skipornot in --image-dir; skip. An image prefixes the image name, as intriton-platform not in channel; skip. - A zone that does not exist is reported as
zone <ALIAS> not provisioned; skip.updatenever provisions an absent zone. - For
portal, the preview addsportal: will serve the image's UI instead of <DIR> (clears triton:portal_static_dir, reboots the zone)when the zone serves a hand-copied UI. That step counts as an update and needs the confirmation. It runs only once the zone is on the channel's image, so a run that failed before clearing the key finishes it next time. When the reboot fails after the key is cleared, the error namesvmadm reboot <ZONE_UUID>. Run it, then runupdate portalagain: a second run finds the key empty, does not reboot, and records the zone's image. - An unknown component name logs a warning to stderr, and the command skips it.
- Zone lookup uses
triton-fdb1whentriton-fdb0is absent, andtriton-tritond1whentriton-tritondis absent. - After a zone component's reprovision, and on any run that finds the zone
already on the channel's image,
updaterecords that image in the zone's registration, whichversionsreads. The host-localmantadwalk does not record its zones. Whenupdatehas no session at all (no endpoint, no credential, and no localtritondsocket), it skips that step. A failure to record prints a warning and does not fail the run. - A component that is already on the channel's stamp reports that and does nothing.
- The
tritonadmcomponent is not counted in the--checkand--dry-runtotals. Under--check, its preview prints thetritonadm self-update --checkcommand to run instead. - The managed
fdbandmantadrolls run after the local walk.
One confirmation covers the local walk. It appears only when at least one planned action would modify or remove running state:
Apply the updates above? This reprovisions/restarts running components.
The default answer is No. Pass --yes or --force to skip the prompt in
automation.
| Flag | Effect |
|---|---|
--all | Update every host-local component that is present in both the source and the host. |
--check | Report what is outdated. Changes nothing. |
--dry-run | Print the planned actions. Changes nothing. |
--yes | Skip the confirmation prompt. |
--force | On a host-local run, skip the prompt as --yes does. |
--channel-url <URL> | Override the channel manifest URL. Defaults to the cluster's channel.upstream_url. |
--channel <NAME> | Named channel. --channel-url takes precedence. |
--revision <REV> | Update against the frozen snapshot of a sealed revision. |
--image-dir <DIR> | Use a local directory of built images and agent tarballs. Conflicts with --channel-url, --channel, and --revision. |
--in-cluster | Update from the in-cluster channel that channel refresh or channel import published, with no public egress. Trusts the cluster's DC channel-signing key alongside the publisher key. Conflicts with --channel-url, --channel, --revision, and --image-dir. |
agents cannot take --image-dir or --in-cluster, because agents update
from the channel only.
The FoundationDB data-format gate
A reprovision of the FDB zone is gated on the data_format_min_read of the
incoming image against the zone's on-disk /data/version. The planning pass
evaluates the gate before any change, so the FDB zone is never reprovisioned
across a data-format gap. A gate failure is reported as an error against
that component. The error text names the migration runbook, and the run
exits non-zero. The other components named in the same run still apply.
Pin or roll back to a revision
Every published build is also sealed as an immutable, signed snapshot named after its build stamp. A signed revision index records it next to the moving channel pointer. List the snapshots:
tritonadm channel revisions --channel edge
The listing names the channel. It marks the revision that the moving pointer advertises now. It prints the sealed revisions, newest first.
channel: <CHANNEL>
current: <REVISION>
=== revisions (newest first) ===
<REVISION> sealed=<PUBLISHED_AT> by=<PUBLISHER> <- current
Each of those ids is a valid --revision value for install, update, and
self-update. To pin the fleet to a known-good revision:
tritonadm update --revision <REVISION>
A frozen snapshot is a full manifest signed by the same publisher key as the moving pointer. It goes through the same verification.
Update from local artifacts
--image-dir replaces the signed channel with a directory of locally built
files, for development and air-gapped hosts. It is available on update
and self-update. On both commands it conflicts with --channel-url,
--channel, and --revision.
tritonadm update --all --image-dir /var/tmp/artifacts
In that directory, update reads images from a <STEM>.imgmanifest or
<STEM>.json paired with a <STEM>.zfs.gz next to it. It reads agents from
<NAME>-<STAMP>.tar.gz for the known agent names tritonagent,
proteusadm, and sandbox-runtime. It reads the CLI from the newest tritonadm-<STAMP>.tar.gz.
When several stamps are present, the newest wins. If the directory has no
tritonadm tarball, the self-update step reports not in --image-dir; skip
and does not fail later.
--image-dir bypasses the release channel. It therefore bypasses the
minisign signature check and the sha256 comparison against a signed
manifest. Point it only at artifacts that you built or trust.
Next steps
- Apply an update runs these commands in order on a live cluster.
- Install the tritonadm CLI covers the first
install of the CLI and the trust model of
install.sh. - Genesis on the founder covers
tritonadm setup bootstrap, which provisions the zones thatupdatelater reprovisions. tritonadm self-updatereference lists the command surface.tritonadm installreference covers the install of a single image or agent from the same channel.- Installation overview puts these commands in order.