Skip to content
Raster
Esc
navigateopen⌘Jpreview
On this page

Secrets

Store values that reach the machine but never come back, and that a captured disk never carries.

Set

await machine.secrets.set("GITHUB_TOKEN", token);
machine.secrets.set("GITHUB_TOKEN", token)

A name must be an uppercase environment variable name — ^[A-Z_][A-Z0-9_]*$. Accepting a name a guest cannot export would store a secret that silently never arrives. Values are up to 64 KB and are stored encrypted.

Setting an existing name replaces the value and bumps its version, so you can tell a change from a no-op.

A stored value is never returned

There is no read method, and the response shape has no field a value could travel in. That is not an omission: a product that can hand a secret back is a product whose secrets are in every response log, error report and browser cache that ever touched one.

for await (const s of machine.secrets.list()) {
  console.log(s.name, s.version, s.delivered_at);
}
for s in machine.secrets.list():
    print(s["name"], s["version"], s["delivered_at"])

delivered_at is null when a secret is stored and not yet delivered — the normal state for one set on a machine that is not running. It lands on the next boot; a running machine takes delivery within seconds.

Reading them inside the machine

Secrets arrive at /run/computer/secrets.env, mode 0600, and a login shell sources them:

const { stdout } = await machine.terminal.execShell("echo $GITHUB_TOKEN");
stdout = machine.terminal.exec_shell("echo $GITHUB_TOKEN")["stdout"]

/run is a tmpfs, which is the entire point: a disk capture cannot contain what was never on the disk. A snapshot, fork or template does not carry a secret, and a machine that restarts takes delivery again from storage.

Delete

await machine.secrets.delete("GITHUB_TOKEN");
machine.secrets.delete("GITHUB_TOKEN")

Removes it from storage and from the running machine. It cannot remove a copy the guest already made — a process that read the value and wrote it elsewhere still holds it. Revoking at the source is this product’s half; rotating at the issuer is yours.

Deployment requirement

Secrets need an encryption keyring configured. Without one the API raises unsupported_operation rather than storing a value in a form it could be read back from.

Secrets versus the browser profile

The two are deliberately opposite, and picking the wrong one is the common mistake:

Carried by a capture? Use for
A browser session yes a login every future machine should inherit
A secret no a credential that must not end up in a captured disk

Was this page helpful?