jail = directive *( ";" directive )
directive = "open" | "deny" | "record" # namespace default (default: open)
| host ":" mount ":" mode # docker -v grant; mount absolute
| "@" path # argument file (read-only grant)
mode = "ro" | "rw"
REFERENCE · 06
Every variable, one table.
This page is the whole TEBAKO_* surface: what each variable does, who reads it, and what a bad value costs. A value that cannot be parsed is never silently ignored.
Three roles.
- Inputs
-
The operator sets these: the store root, mirrors, offline and signing modes, the jail policy, version pins, and diagnostics. They shape resolution and the run.
- Channels
-
The loader or the driver sets these for the runtime process — the env image, the mount table, the exec cache. Payload code may read the discovery ones; a channel the operator sets is overwritten or stripped.
- Sentinels
-
These are internal handshakes between a process and its own re-exec. Setting one can only lie about work that never happened.
The consolidated table.
The store and the fetch
Operator inputs: the operator sets these, and they shape where artifacts live and where they come from.
| Variable | Readers | Grammar | Default | What it does | A malformed value costs |
|---|---|---|---|---|---|
|
bootstrap · shim · CLI · signer · tfs journal |
directory path |
$HOME/.tebako on POSIX · %LOCALAPPDATA%\tebako on windows · fallbacks reach %USERPROFILE% |
The variable names the machine store, which holds the runtimes, payloads, shims, registries, keys, trust material, and the audit journal. |
The value is used verbatim. When no home resolves at all, the bootstrap fails closed naming TEBAKO_HOME (exit 74, EX_TEBAKO_IO). |
|
bootstrap · shim · tebako-resolve |
flag (truthiness differs by reader — see below) |
unset (online) |
The run is a cache hit or a named error (exit 69, EX_TEBAKO_UNAVAILABLE) — never a fetch. |
The value is not parsed — see the truthiness note below. |
|
bootstrap · CLI (press) |
base URL — https or file:// |
https://github.com/tamatebako/tebako-runtime-ruby/releases/download |
The variable names where runtime artifacts (exe + env image + index) are fetched from. |
No named error at read time; an unreachable mirror surfaces as exit 69. |
|
tebako-http (every downloading surface) |
presence flag — set at all, any value |
unset (bundled webpki-roots) |
The variable opts the fetch into the OS trust store instead of the bundled roots (corporate machine-in-the-middle (MITM) proxies). |
n/a — presence, not value. |
|
bootstrap |
flag — set, non-empty, ≠ 0 |
unset (unsigned runs with a loud warning + audit journal entry) |
The loader fails closed on unsigned packages, and on signed ones when verification is unavailable. |
The cost is exit 71 (EX_TEBAKO_SIGNATURE) for an unsigned or unverifiable package. |
|
bootstrap (builds with OpenPGP verification) |
a root fingerprint, or a path to an armored public key |
the embedded root fingerprint (EMBEDDED_ROOT_FINGERPRINT) |
The variable is the developer override for the root of trust. A fingerprint alone never suffices — the public key must still reach the trusted keyring; the trailer signature is always cryptographically verified. |
No named error — a value that is not a file is treated as a fingerprint. |
|
every surface (tebako-term) |
flag — set, non-empty, ≠ 0 |
unset |
The variable forces plain progress output: the start + done single lines, no bar, and no escape sequences. |
n/a. |
|
CLI (publish) |
a GitHub token string |
falls back to GITHUB_TOKEN |
The variable authenticates the release upload. |
With both unset, publish answers a named packaging error. |
Policy and dispatch
Operator inputs: the operator sets these, and they shape what the run may touch and which version answers. Press-time settings resolve through the settings registry — the CLI wins, then the environment, then the compose document, then the default.
| Variable | Readers | Grammar | Default | What it does | A malformed value costs |
|---|---|---|---|---|---|
|
bootstrap (parses, composes manifest ∩ user, re-exports) · driver + preload shim (enforce) |
open | deny | record, then ;host:mount:ro|rw grants and ;@file argument files — grammar below |
unset (no policy — the host is fully visible) |
The variable is the run’s host-access policy. record allows everything and journals each access (event=jail-allow) — the discovery mode. Spawned children inherit and re-bind it. |
The cost is exit 73 (EX_TEBAKO_JAIL) at the bootstrap and the driver, and exit 78 (EX_CONFIG) at preload-shim init — always fail-closed. |
|
driver (reads) · bootstrap, shim (set) |
audit label: manifest | user | manifest+user, or the exporting surface’s name |
"TEBAKO_JAIL" when unset |
The variable records the provenance of the bound policy, journaled with every denial. |
n/a. |
|
tfs journal (reads) · bootstrap, shim (set) |
file path |
$TEBAKO_HOME/journal.log |
The variable names where jail denials (and record-mode allows) append; the journal is best-effort by design. |
With an unopenable file, journaling stays silent; the jail’s answers are unaffected. |
|
tebako-shim |
an installed payload version; the var name is the uppercased command name, non-alphanumerics → _ |
unset — the chain falls through to .tebako-tools.yaml, then config defaults, then the registry default |
The variable pins the version per invocation — the first link of the dispatch chain. On a runtime-own reference ( |
A pin naming a version that is not installed costs exit 65, which names the source and the installed set. |
|
tebako-shim · bootstrap |
1 | true | yes | on, or 0 | false | no | off |
on (lazy) |
The variable is the machine’s lazy-install policy for runtime env images: a lazy install seeds the image’s 4 MiB block groups on demand and seals in the background into the same bytes a whole-image install produces, while the block-checksum sidecar is fetched and pinned at install so a run touches only the groups it reads. The store config carries the same policy as |
A value outside the grammar costs exit 65, which names the variable and the value. |
|
tfs owns the grammar; driver consumption is planned |
<mount>=<store> pairs, ;-separated, split on the FIRST =; mounts VFS-absolute, stores host-absolute |
unset |
The variable binds copy-on-write (COW) overlay stores to mounts; spawned children inherit and re-bind identically. |
The cost is exit 68 (EX_TEBAKO_OVERLAY), quoting the offending entry. |
|
tfs owns the grammar; driver consumption is planned |
<mount>=pgp:<keyid> pairs, ;-separated; the keyid is 16 lowercase hex |
unset |
The variable binds decrypt recipients to mounts; the value is a reference, never key material, resolved against $TEBAKO_HOME/keys/ at the driver’s mount. |
The cost is exit 68 (EX_TEBAKO_OVERLAY), quoting the offending entry. |
The handoff
Channels: the loader (bootstrap/shim) or the driver sets these for the runtime process, and the runtime and payload code read them. A channel the operator sets on a managed run is overwritten or stripped.
| Variable | Readers | Grammar | Default | What it does | A malformed value costs |
|---|---|---|---|---|---|
|
driver (reads) · bootstrap, shim (set) |
absolute path of the runtime’s env .tfs |
none |
The variable carries the env image, mounted whole at the runtime root — stdlib, gems, everything the load paths expect. |
When unset, the cost is a loud stderr note and a bare boot with an empty runtime root (a handoff bug unless deliberate). |
|
driver |
absolute path — /… or drive-qualified X:/…; no trailing slash, no .. |
the runtime’s baked root (ruby: /tfs, A:/t on windows) |
The variable redirects the env-image mount; the io-routing patches and era-2 rbconfig follow. |
A malformed value costs exit 65 naming the variable; an env image without the mount_root_override grant costs exit 78 (EX_TEBAKO_LAYOUT). |
|
preload shim at init (reads) · driver, the spawn hook (set) |
image:mount,… — one parser (tfs::mount_spec) shared with tfs exec |
unset (no mounts) |
The variable seeds the mount table of a preload-interposed process. The shim strips an inherited value before a managed dispatch, and a spawned runtime child never sees it — the child rebuilds the namespace from its own boot. |
The cost is exit 78 (EX_TEBAKO_LAYOUT), naming the variable and the offending token. |
|
interpreter + payloads (read-only) · driver (sets at boot) |
directory path, driver-owned |
<temp>/tebako-exec-<key> — the key derives from the env image |
The variable names where materialized binaries and libraries live. The cache is per-process and reaped at exit on POSIX; it stays in place, content-keyed, on windows (a loaded DLL is OS-locked). |
n/a — driver-set. |
|
tfs PE closure walk (windows; POSIX never reads it) · driver (sets) |
PE module basename, e.g. x64-ucrt-ruby340.dll |
unset when the env image declares no runtime_dll layout key |
The variable carries the runtime’s own DLL name; a bare import name matching it (case-insensitive) is excluded from closure materialization. |
n/a — driver-set from the factory record. |
|
the interpreter’s spawn hook (reads) · driver (sets) |
the preload shim’s in-VFS path |
unset when the env image grants no preload_shim layout key |
The variable names where the preload shim lives. The driver additionally arms LD_PRELOAD (ELF) / DYLD_INSERT_LIBRARIES (macOS) with the materialized host copy. |
A declared-but-absent shim costs exit 78 — the image is lying about its contents. |
|
payload code (reads) · driver (sets, one per co-mounted payload) |
physical mount point, drive-qualified on windows; SLUG rules below |
— |
The variable is the discovery surface: it carries a dependency mount’s physical point, re-rooting-proof. |
Two different mounts slugging alike cost exit 65 (an authoring ambiguity, never a silent winner). |
|
driver (reads at boot) |
host file path — the trace bus’s JSONL channel |
unset (bus disarmed) |
The variable arms the interception trace bus before any mount; the channel is appended to for the process’s life, and children re-derive it from the inherited env. --tebako-trace wins when both are set. |
An unopenable channel costs a loud stderr note and a disarmed bus — never a boot failure (observability never gates). |
|
the runtime’s children (read) · driver (sets, always overwrites) |
unsigned integer |
the runtime’s compiled-in contract version |
The variable carries the machine-readable handoff version the runtime speaks; the runtime is authoritative, so an inherited value never survives boot. |
n/a — driver-set. |
Packaging time
These are inputs to press, publish, install, and deploy; they never reach a running payload.
| Variable | Readers | Grammar | Default | What it does | A malformed value costs |
|---|---|---|---|---|---|
|
CLI (press) |
path to a local tebako-bootstrap binary |
resolution order: --bootstrap flag → this var → the binary next to tebako → the release store |
The variable chooses which bootstrap gets stitched onto the package. |
An era-1 or mismatched bootstrap makes the press refuse (the contract-card check). |
|
CLI (press) |
base URL — https or file:// |
the tebako release store |
The variable names where per-triplet bootstrap assets are fetched from. |
No named error at read time. |
|
CLI (press) |
directory path |
none — consulted only when --prefix is not given |
The variable carries the application prefix (announced on stdout when used). |
No named error. |
|
CLI (press — the native-extension deploy SDK) |
a ruby-source release tag |
the CLI’s pinned default |
The variable chooses which patched-source release the runtime software development kit (SDK) resolves from. |
No named error at read time. |
|
CLI (press — the native-extension deploy SDK) |
base URL |
the CLI’s pinned default mirror |
The variable names where the SDK source tarball is fetched from. |
No named error at read time. |
|
CLI (install) |
path to a tebako-shim binary |
the shim resolved beside the CLI |
The variable chooses which binary tebako install --shims links the shims to. |
No named error at read time. |
|
tfs exec (unix) |
path to a preload-shim binary |
the shim resolved beside tfs |
The variable chooses which preload shim gets injected into the exec’d child. |
A non-file value falls through to the default resolution. |
|
press deploy internals (POSIX): set by the generated ruby shim, read by the deployed rbconfig |
directory path |
the deploy wrapper sets it to its own directory |
The variable points the packaging environment’s bindir at the deploy dir during native-extension deploys. It is internal — the operator never sets it. |
n/a. |
|
CLI (press) |
flag — set, non-empty, ≠ 0 |
unset (the unsigned v1 trailer — byte-identical with pre-signing output) |
The variable signs the package trailer at press: the SIGNED_V2 flag plus the v2 chain-of-trust extension. |
An opt-out that drops a lower channel sign declaration is loud: a stderr warning plus an audit-journal event. |
|
CLI (press) |
flag — set, non-empty, ≠ 0 |
unset (notices shown) |
The variable suppresses the unsigned-legacy-trailer warning and the progress lines for every run of the package; the choice is baked into the trailer as a package flag. |
An unparseable value is a named error — never a silent default. |
Diagnostics
Operator inputs: observability never gates — a broken debug or trace setting degrades loudly and the run proceeds.
| Variable | Readers | Grammar | Default | What it does | A malformed value costs |
|---|---|---|---|---|---|
|
every component (tebako-log) |
off | error | warn | debug | trace, plus per-component overrides (debug,preload=trace,tfs=warn) |
off — zero cost: the config reads once, the gate runs before any formatting |
The variable enables stack-wide debug logging, one facility for every crate. |
No named error — unrecognized levels are ignored. |
|
tebako-log |
legacy boolean — any non-empty value |
unset |
The variable maps to debug, for back-compat with the pre-tebako-log knob. |
n/a. |
|
tebako-log |
file path; %p expands to the pid |
stderr (stdout belongs to the payload, never to the log) |
The variable names the log sink — append-mode, parent directories created, per-pid files for exec’d children. |
An unopenable sink falls back to stderr with one warn line naming the failure. |
|
tebako-log |
comma filter of component names (preload, tfs, driver, shim, bootstrap, cli, pkg, resolve) |
all components |
The variable narrows the log to the named crates. |
No named error. |
Internal — never set these
These are handshakes between a process and its own re-exec; setting one can only lie.
| Variable | Readers | Grammar | Default | What it does | A malformed value costs |
|---|---|---|---|---|---|
|
driver (sets it, and the re-exec’d child sees and scrubs it) |
1 |
unset |
The variable is macOS only: the once-per-process sentinel for the driver’s self-inserted interpose dylib. The re-exec precedes all mounting, fires exactly once, and leaves no launcher-ABI change. |
n/a — internal. |
|
the dispatcher sets it; the driver reads it at spawn time |
engine=lang_version:tebako_version, joined with semicolons in manifest order |
a payload without runtime edges exports nothing |
The variable pins the driver spawn-time runtime pick for the payload spawned-runtime edges, which resolve at dispatch time. |
n/a — internal. |
The jail grammar.
One grammar, two parsers that must agree: the authored model in tpkg (compose and serialize) and the engine’s jail spec, which the driver and the preload shim consume. The record token is the discovery mode: it allows everything, journals every access, and lets a journal draft the policy afterwards.
A malformed policy is a security setting that cannot be parsed, so it never runs open: the bootstrap and the driver refuse with exit 73 (EX_TEBAKO_JAIL), the preload shim with exit 78 (EX_TEBAKO_LAYOUT) — the shim’s own configuration code. The platform floor (macOS /usr, /System, /Library; windows System32, SysWOW64, Fonts) is re-derived at every bind and never serialized into the variable, so a spawned child enforces exactly its parent’s policy.
The mount-root override.
TEBAKO_MOUNT_ROOT redirects where the env image mounts. It is validated before any mount — absolute, /… or drive-qualified X:/…, no trailing slash, no .. — and a malformed value is exit 65 naming the variable. The override is then gated post-mount on the env image’s mount_root_override layout grant: an image without the grant predates the override era, and the driver refuses with exit 78 rather than boot an interpreter whose load paths point at an unmounted root.
The mount discovery surface.
Per co-mounted payload the driver exports TEBAKO_MOUNT_<SLUG> holding the physical mount point. The slug is mechanical: the drive qualifier is dropped, every ASCII alphanumeric is uppercased, every other character maps to _, and leading and trailing underscores are trimmed — /tools/inkscape becomes TEBAKO_MOUNT_TOOLS_INKSCAPE. Interior separators are not collapsed (/a//b becomes TEBAKO_MOUNT_A__B). The root mount exports nothing — the name TEBAKO_MOUNT_ROOT is reserved for the override — and two different mounts slugging alike are an authoring ambiguity: exit 65, never a silent winner.
Overlay and decrypt bindings.
This section carries the serialized form of a run’s bound overlay stores and decrypt recipients, handed to the runtime beside TEBAKO_JAIL and inherited by spawned children. No key material ever crosses the channel — the decrypt value is a key reference resolved against $TEBAKO_HOME/keys/ at the driver’s mount.
TEBAKO_OVERLAYS=<mount>=<store>;<mount>=<store>;…
TEBAKO_DECRYPT=<mount>=pgp:<keyid>;<mount>=pgp:<keyid>;…
Truthy is not one rule.
Stated plainly: the flag variables do not share one predicate. The row for the surface being set is the authority — the predicates below are the shipped code.
| Reader | Predicate | Applies to |
|---|---|---|
bootstrap · shim |
set, non-empty, and not "0" |
TEBAKO_OFFLINE · TEBAKO_REQUIRE_SIGNED |
tebako-resolve |
1, true, or yes (case-insensitive) |
TEBAKO_OFFLINE |
tebako-term |
set, non-empty, and not "0" |
TEBAKO_NO_PROGRESS |
tebako-http |
present at all — the value is never read |
TEBAKO_TLS_PLATFORM_ROOTS |
The practical consequence: TEBAKO_OFFLINE=yes is honored everywhere, but TEBAKO_OFFLINE=2 is true for the bootstrap and the shim and false for tebako-resolve. The value 1 is the spelling every reader agrees on.
The debug surface.
One facility wires every component; no ad-hoc printing anywhere in the stack. One parseable line per event:
tebako[<pid>] <level> <component>: <event> <k=v>…
Off costs nothing — the config reads once and the gate runs before any formatting. Paths, decisions, and digests are loggable; payload contents and key material never are.
The trace channel.
TEBAKO_TRACE (or the driver’s --tebako-trace argument, which wins when both are set) arms the interception trace bus at boot, before any mount — one JSON Lines (JSONL) event per interception decision, appended for the process’s life. A spawned child re-derives the channel from the inherited env and appends to the same file. A channel that cannot be opened is a loud stderr note and a disarmed bus, never a boot failure: observability never gates.
Read or written, but not TEBAKO_*.
The stack also touches a handful of shared variables. They are listed here so the table above stays complete without pretending these are tebako’s names.
| Variable | Role |
|---|---|
|
The driver exports the materialized host path of a declared ssl/cert.pem at boot; an unset/empty value is set, a stale in-VFS spelling is rewritten, a real host path always wins. The press also probes the host’s OpenSSL default when assembling the packaging env. |
|
The press-side half of that cert probe (tebako-cli/src/packager.rs). |
|
The driver re-leads it: launcher dir, then dependency bin dirs, then windows library-alias dirs, then the inherited PATH. |
|
The driver arms them with the materialized preload shim. On macOS the spawn hook drops an inherited DYLD_INSERT_LIBRARIES for Apple-restricted targets — the SIP boundary. |
|
Present at all → plain progress output. |
|
The publish fallback when TEBAKO_GITHUB_TOKEN is unset. |
|
The home-resolution chain behind the default store root: %LOCALAPPDATA%\tebako on windows, else $HOME/.tebako (then %USERPROFILE%). |
|
yes or true turns on the CLI’s subprocess echo — a development knob (tebako-cli/src/runner.rs). |
Not environment variables.
These names surface in the same greps and read like variables. None of them is one; the following states what each actually is.
| Name | What it is |
|---|---|
|
Mount-mode constants of the tebako_fs_mount C API (0 / 1 / 2; RW answers ENOTSUP). They are not environment variables. |
|
The named exit codes 65 through 79 — MANIFEST, ABI, RUNTIME_REF, OVERLAY, UNAVAILABLE, SHA, SIGNATURE, TRUST, JAIL, IO, CONTRACT, INSTALL, CONTRACT_ERA, LAYOUT, CHECK — constants in tpkg and the loaders, not variables. |
|
fd-table constants of the VFS engine. |
|
Compiled-in constants — build-time facts, never read from the environment. |
|
The v1 memfs-filter escape hatch, retired: no v2 runtime patch reads it. |
|
Appears nowhere in the v2 spec set or the product code. The v2 certificate surface is SSL_CERT_FILE and TEBAKO_TLS_PLATFORM_ROOTS. |
|
A GitHub Actions secret for cross-repo triggers — CI plumbing, not a runtime or CLI variable. |
See also: Dispatch · The store · Set a jail policy · Debug & logging