Skip to main content

tritonadm self-update and channel

tritonadm self-update replaces the running tritonadm binary with the one the signed release channel advertises for this binary's target triple. tritonadm channel lists a channel's sealed revisions, which are the identifiers --revision accepts, and publishes the in-cluster channel that compute nodes install from.

tritonadm self-update​

Replace this tritonadm binary from the signed release channel. The command takes no positional arguments.

Options​

OptionDefaultEffect
--channel-url <URL>the cluster's channel.upstream_urlUse this manifest URL verbatim. Wins over --channel.
--channel <NAME>the cluster's channel.upstream_urlExpand a channel name to https://tritoncloud.nyc3.digitaloceanspaces.com/channels/<NAME>.json.
--revision <REV>noneRetarget the resolved URL to that revision's frozen snapshot.
--install-dir <DIR>directory of the running executableDirectory the binary is swapped into.
--checkoffReport installed against candidate and exit. Downloads and replaces nothing.
--image-dir <DIR>noneSelf-update from a local tritonadm-<STAMP>.tar.gz instead of the channel. Conflicts with --channel-url, --channel, and --revision.
--in-clusteroffSelf-update from the in-cluster channel that channel refresh or channel import published. Trusts the cluster's DC channel-signing key alongside the publisher key. Conflicts with --channel-url, --channel, --revision, and --image-dir.
--rollbackoffPut tritonadm.prev back in place of the running binary. Reads no channel. Conflicts with --channel-url, --channel, --revision, --image-dir, --in-cluster, and --check.
--forceoffSwap in a candidate that the running tritond does not serve, or that could not be checked.

All options are long form. There are no short forms.

What the command does​

On the channel path, in this order:

  1. Resolves the channel URL from --channel-url, --channel, the cluster's channel.upstream_url, and --revision. See Channel URL resolution.
  2. Fetches the manifest and its detached signature at <CHANNEL_URL>.minisig.
  3. Verifies the signature against the publisher public key compiled into the binary. With --in-cluster, the cluster's DC channel-signing key is also accepted.
  4. Parses the manifest, refusing any manifest whose schema field is above 1.
  5. Looks up the manifest's tritonadm entry for this binary's target triple. The triple is baked in at compile time as TRITONADM_TARGET, not detected at run time.
  6. Prints the installed stamp and the candidate stamp and size. Equal stamps end the run here.
  7. Downloads the candidate tarball and verifies its SHA-256 against the signed manifest entry.
  8. Extracts the tarball, requires a tritonadm binary at its top level, and sets mode 0755.
  9. Checks the candidate against the running tritond. See API version check.
  10. Swaps the binary into the install directory.

The stamp comparison is equality, not ordering. Any candidate stamp that differs from the installed one is installed, whether it is older or newer. Pinning --revision to an older sealed revision installs the older binary.

Output​

The two status lines are printed on every run before any download starts:

installed: <INSTALLED_STAMP>
candidate: <CANDIDATE_STAMP> (<SIZE> bytes)

When the stamps match, one further line is printed and the command exits without touching the disk:

already up to date

After a successful swap:

tritonadm updated at <INSTALL_DIR>/tritonadm
previous binary preserved at <INSTALL_DIR>/tritonadm.prev; `tritonadm self-update --rollback` puts it back

After --rollback:

rolled back <INSTALL_DIR>/tritonadm to the previous build
the replaced binary is now <INSTALL_DIR>/tritonadm.prev

The second line is omitted when no live binary existed.

Exit status​

--check exits zero when the installed stamp equals the candidate stamp, and non-zero otherwise, with this message:

tritonadm is outdated (installed <INSTALLED_STAMP>, candidate <CANDIDATE_STAMP>)

--check still fetches the manifest and verifies its signature, so it fails on an unreachable channel or a signature that does not verify.

API version check​

tritond serves one admin API version and refuses a request that names a newer one, before it authenticates the request. Before the swap, the command asks whether the running tritond serves the candidate:

  1. Runs the extracted binary with the hidden api-version subcommand, which prints the admin API version that build speaks as JSON.
  2. Sends GET /v1/health with that version in the api-version header to the tritond the session would reach, with no credential and a 30-second timeout.
  3. A success status means tritond serves it, and the swap proceeds. A 400 whose message starts with server does not support this API version means it does not.
SituationResult
tritond serves the candidateSwap.
tritond does not serve it, or answers anything else, or cannot be reachedFail and change nothing. With --force, print a warning and swap.
The candidate rejects api-version as an unrecognized subcommandSwap. The build predates the check and speaks an older version.
The candidate fails api-version any other wayFail.
No endpoint is configured and no local socket answersPrint warning: no tritond to check the candidate against (...) and swap.
--image-dirNot checked.

The endpoint follows the same rules as a signed-in session: --endpoint or TRITONADM_ENDPOINT first, then the head node's local socket when no endpoint and no credential is given explicitly, then the configured endpoint. No credential is sent.

Binary swap and rollback​

Three paths inside the install directory take part in the swap.

PathRole
<INSTALL_DIR>/tritonadm.newStaging copy of the new binary, mode 0755.
<INSTALL_DIR>/tritonadm.prevThe binary that was live before this run. A stale .prev is deleted first.
<INSTALL_DIR>/tritonadmThe live binary. Replaced by renaming tritonadm.new over it.

tritonadm.prev survives until the next self-update overwrites it. Nothing deletes it automatically. --rollback renames it back over tritonadm without re-fetching anything, and keeps the replaced binary as the new tritonadm.prev, so a second rollback undoes the first. It passes through <INSTALL_DIR>/tritonadm.rollback while it swaps.

A swap and a rollback each hold an exclusive lock on <INSTALL_DIR>/tritonadm.lock, so two of them in the same directory run one after the other.

When no binary exists at <INSTALL_DIR>/tritonadm, the swap logs a warning and installs the new binary fresh.

Local artifacts with --image-dir​

--image-dir <DIR> reads the newest tritonadm-<STAMP>.tar.gz in DIR. Stamps sort chronologically, so the highest stamp wins. Files that do not match that exact prefix and suffix are ignored, including sibling agent tarballs such as tritonagent-<STAMP>.tar.gz.

This path performs no signature check and no SHA-256 check. It compares the filename's stamp against the running binary's build stamp, then extracts and swaps. The candidate line names the file instead of a byte count:

candidate: <CANDIDATE_STAMP> (<PATH_TO_TARBALL>)

When the directory holds no matching tarball, the command fails:

no tritonadm-<stamp>.tar.gz in --image-dir <DIR>

With --in-cluster​

--in-cluster reads three things from tritond: the image object-store binding, the channel.upstream_url setting, and the cluster's DC channel-signing public key. The manifest URL is <ENDPOINT>/<BUCKET>/channel/channels/<NAME>.json, where <NAME> is the channel name taken from channel.upstream_url. The command prints using in-cluster channel <URL> and then runs the channel path above.

When the cluster has no image object store configured, the command fails with a message that begins no in-cluster channel: the cluster has no image object store configured.

tritonadm channel revisions​

List a channel's sealed revisions, newest first, and mark the one the moving channel pointer currently advertises.

Options​

OptionDefaultEffect
--channel-url <URL>the cluster's channel.upstream_urlUse this manifest URL verbatim. Wins over --channel.
--channel <NAME>the cluster's channel.upstream_urlExpand a channel name to its canonical manifest URL.

The command reads the revision index that sits beside the channel pointer, then reads the pointer itself to learn which revision is current. Reading the pointer is best effort: a channel that has never been sealed still lists its index, without a current line.

Output​

The listing is printed in this shape. One line per sealed revision, oldest last:

channel: <CHANNEL_NAME>
current: <REVISION>

=== revisions (newest first) ===
<REVISION> sealed=<PUBLISHED_AT> by=<PUBLISHER> <- current
<REVISION> sealed=<PUBLISHED_AT> by=<PUBLISHER>
FieldSource
channelThe channel field of the revision index.
currentThe revision field of the channel pointer manifest. Omitted when the pointer carries none.
<REVISION>A revision id, equal to the build stamp it was sealed under. This is the value --revision takes.
sealed=The revision's published_at timestamp.
by=The revision's publisher string.
<- currentMarks the revision the pointer advertises.

tritonadm channel refresh​

Ask tritond to mirror the channel named by channel.upstream_url into the in-cluster channel. tritond fetches the upstream, verifies it against the publisher key, and signs the manifest again with the cluster's DC channel-signing key. The command starts that operation and waits for it, for up to one hour.

OptionDefaultEffect
--revision <STAMP>the moving pointerPublish one sealed revision, a stamp from channel revisions.
--no-waitoffPrint the operation id and return instead of waiting.

Output:

publishing channel <CHANNEL> in-cluster from <UPSTREAM_URL> (operation <OPERATION_ID>)
channel publish: <STATE>
channel <CHANNEL> published in-cluster; booter mirrors refresh within ~2 minutes and CNs fetch from their booter.

When a publish is already running, the first line reads channel <CHANNEL> is already publishing from <UPSTREAM_URL>; attaching to operation <OPERATION_ID>. A refusal from tritond is printed as the server refused the channel refresh (<STATUS>): <MESSAGE>. An operation that ends failed, unwound, or stuck fails the command with channel publish operation ended <STATE>.

tritonadm channel import​

Publish a locally built release, the same directory tree that setup --image-dir installs from, into the in-cluster channel. tritonadm hashes and uploads each artifact in the booter mirror's layout, and tritond signs the manifest with the cluster's DC channel-signing key. This is the air-gapped path. A connected cluster uses channel refresh.

OptionDefaultEffect
--image-dir <DIR>requiredDirectory of built artifacts: images, agent tarballs, install.sh, and the tritonadm tarball.
--channel <NAME>dcChannel name. Must match the booter's [ur.setup] channel.
--publisher <TEXT>dc-operatorPublisher string recorded in the manifest.
--s3-endpoint <URL>requiredIn-cluster S3 endpoint, the mantad zone.
--bucket <NAME>triton-imagesBucket holding the channel.
--prefix <PREFIX>channelKey prefix inside the bucket.
--region <NAME>us-east-1S3 region name.
--access-key <KEY>TRITONADM_S3_ACCESS_KEYS3 access key.
--secret-key <KEY>TRITONADM_S3_SECRET_KEYS3 secret key.

Without an access key the command fails with no S3 access key: pass --access-key or set TRITONADM_S3_ACCESS_KEY, and the secret key fails the same way. The tritond session is resolved before any upload starts.

Channel URL resolution​

self-update and channel revisions resolve the manifest URL the same way, highest priority first:

  1. --channel-url <URL>, used verbatim.
  2. --channel <NAME>, expanded to https://tritoncloud.nyc3.digitaloceanspaces.com/channels/<NAME>.json.
  3. The cluster's channel.upstream_url setting, read through tritond. The command prints channel <NAME> (from channel.upstream_url).

There is no built-in default channel. When neither flag is given and no tritond session resolves, the command fails with this message:

no --channel given, and the cluster's channel could not be read; pass `--channel edge` (or `stable`, or `--channel-url URL`)

When the session resolves but channel.upstream_url is unset, the command fails with this message:

no release channel: pass `--channel edge` (or `stable`, or `--channel-url URL`), or set the cluster's with `tritonadm config set channel.upstream_url URL`

self-update --image-dir reads no channel and needs no session.

--revision <REV> then rewrites the resolved URL by replacing the trailing .json with /<REV>.json. A base URL that does not end in .json is returned unchanged. channel revisions does not accept --revision.

The resulting URLs follow this scheme, where <BASE> is https://tritoncloud.nyc3.digitaloceanspaces.com/channels:

ObjectURL
Channel pointer<BASE>/<CHANNEL>.json
Pointer signature<BASE>/<CHANNEL>.json.minisig
Frozen revision snapshot<BASE>/<CHANNEL>/<REVISION>.json
Snapshot signature<BASE>/<CHANNEL>/<REVISION>.json.minisig
Revision index<BASE>/<CHANNEL>/index.json
Index signature<BASE>/<CHANNEL>/index.json.minisig

A frozen snapshot is a complete manifest, signed by the same key as the pointer, so pinning to a revision changes no other behavior.

Channel names​

--channel accepts any name and expands it to a URL. Two names are published by CI.

ChannelPublished fromContents
edgepushes to mainRolling pre-release.
stabletags matching v*Released builds. Present only after a tagged build.

Each CI publish seals its build stamp as a revision, writing the frozen snapshot, updating the pointer, and recording the revision in the index.

CI publishes one tritonadm entry per build, for the x86_64-unknown-illumos target. A binary built for another target triple finds no entry and fails.

Signature and integrity verification​

Every channel fetch in tritonadm performs two independent checks.

CheckApplies toMechanism
minisign signatureThe channel manifest and the revision indexVerified against the publisher public key compiled into the binary with include_str! from cli/tritonadm/publisher.pub. An --in-cluster manifest may instead verify against the cluster's DC channel-signing key. The revision index accepts only the publisher key.
SHA-256The downloaded tritonadm tarballCompared against the sha256 field of the already-verified manifest entry.

The committed publisher key is a minisign public key with key id 6A95AFF9C8B898E7.

Expected SHA-256 values must be exactly 64 lowercase hexadecimal characters. Uppercase or mixed case is rejected as malformed rather than normalized, so a comparison failure always means the bytes differ.

The bootstrap script install.sh verifies the artifact's SHA-256 against the manifest it fetched over TLS, and does not check the minisign signature. Running tritonadm self-update --check after a bootstrap install is the path that enforces the publisher signature.

self-update fetches the manifest and the tarball through the triton-tls client. That client trusts native system certificates first, then the platform certificate paths, then the bundled Mozilla roots, and adds the PEM file named by TRITON_DC_ANCHORS. The channel fetch used by install, update, and channel revisions goes through the host-resources client, which trusts the bundled Mozilla roots only, disables the whole-request timeout, and sets a 30-second connect timeout.

Channel manifest fields​

The manifest schema version this release understands is 1.

FieldMeaning
channelChannel name, for example edge or stable.
schemaSchema version. A manifest above 1 is refused.
updated_atWhen this snapshot was published.
publisherIdentifier of the operator or pipeline that signed the snapshot.
revisionRevision id this snapshot was sealed under. Absent on a channel that has never been sealed.
imagesZone images, keyed by image name.
agentsGlobal-zone tarball artifacts, keyed by agent name.
servicesZone-resident service binaries, keyed by service name.
tritonadmtritonadm tarballs, keyed by Rust target triple.

Each entry under tritonadm carries four fields.

FieldMeaning
stampBuild stamp in YYYYMMDDTHHMMSSZ form, compared against the running binary's compile-time stamp.
urlURL of the tarball.
sha256Lowercase hex SHA-256 of the tarball.
size_bytesSize of the tarball, printed on the candidate: line.

The revision index carries channel, schema, updated_at, and a revisions array sorted oldest first. Each element carries revision, published_at, and publisher.

Error messages​

MessageCondition
channel signature did NOT verify against the publisher pubkeyThe manifest's detached signature failed verification. With --in-cluster, the message ends or the cluster's DC channel-signing key.
revision index signature did NOT verify against publisher pubkeyThe revision index's signature failed verification.
channel manifest schema is <N>, this client only understands up to 1; update your client and retryThe manifest declares a newer schema.
channel has no tritonadm entry for target <TARGET>The manifest carries no entry for this binary's compile-time target triple.
tritonadm is outdated (installed <A>, candidate <B>)--check found differing stamps.
downloaded tarball sha256 does NOT match channel manifestThe downloaded bytes do not match the signed manifest entry.
tarball did not contain a `tritonadm` binary at the top levelThe extracted archive has no top-level tritonadm.
no tritonadm-<stamp>.tar.gz in --image-dir <DIR>--image-dir holds no matching tarball.
the candidate speaks admin API <VERSION>, which the running tritond does not serve yet. Update tritond first (...), then self-update; --force swaps it anywayThe API version check found tritond older than the candidate.
could not ask tritond whether it serves admin API <VERSION>: <CAUSE>. Update tritond first (...), then self-update; --force swaps it anywayThe check got no clear answer from tritond.
no <INSTALL_DIR>/tritonadm.prev to roll back to--rollback found no previous binary.
GET <URL> -> <STATUS>An HTTP fetch returned a non-success status.
no --channel given, and the cluster's channel could not be read; ...No channel flag, and no tritond session resolved.
no release channel: pass `--channel edge` ...No channel flag, and channel.upstream_url is unset.

Relationship to tritonadm update​

tritonadm update tritonadm and tritonadm update --all delegate to the same self-update code, passing the run's resolved channel URL or --image-dir and leaving --install-dir at its default. Both apply the API version check without --force. A bare tritonadm update replaces the binary as the first step of the whole-fleet run, then runs the replaced binary again with the same arguments, when the running tritond serves the new build. When it does not, or cannot be asked, the run prints <WHY>; it is installed after tritond is updated, updates the control plane and agents with the installed binary, and replaces the binary after the agents. tritonadm is last in the --all order because it replaces the running binary.

Two behaviors differ inside an update run. The self-update action is not counted in the "updates available" total, and it does not trigger the confirmation prompt, because the swap is reversible through tritonadm.prev. Under tritonadm update --check, the tritonadm component is reported as an instruction rather than being checked:

tritonadm: run `tritonadm self-update --check` (self-update replaces the running binary)

With --image-dir, that instruction carries the directory. An --image-dir run whose directory holds no tritonadm tarball reports not in --image-dir; skip.

See also​