Environment Files & Secrets
ជំពូកនេះមិនទាន់ត្រូវបានបកប្រែជាភាសាខ្មែរនៅឡើយទេ — សូមអានជាភាសាអង់គ្លេសខាងក្រោម។
Table of Contents
- Why declare instead of type
- The sbxenv.yaml schema
- Secrets: three ways to supply a value
- Plan before you apply
- The full lifecycle: create, exec, rm
- A worked example
- Beginner Pitfalls
1. Why declare instead of type
Every sandbox in this course so far has been created by typing a command:
sbx run --name sbx-crash-course shell, later sbx ports ... --publish 3000:3000, later still a kit flag from Part 10.
That's fine solo, but it doesn't survive being handed to a teammate, or to
CI, or to your own future self in six months. An environment file —
sbxenv.yaml — captures the whole setup as one reviewable, shareable file:
the agent, the workspace, any kits, environment variables, secrets, ports,
and MCP servers a project's sandbox needs, in one place.
Note: like kits, environment files are an experimental, evolving part of
sbx. The schema below matches the documented behavior at the time of writing.
2. The sbxenv.yaml schema
A minimal file needs only two fields:
schemaVersion: "1"
agent: claude
The fuller set of fields you'll actually use on a real project:
| Field | Purpose |
|---|---|
name | Sandbox name (defaults to <agent>-<workspace folder name>) |
workspace | Path to mount, or { path, clone: true } for a private clone |
additionalWorkspaces | Extra mounted directories, each with an optional readOnly flag |
env | Plain environment variables |
args | Parameters the file itself accepts (default, required, enum, pattern) |
sandboxOptions | Resource sizing: cpus, memory, gpu, template, profile |
kits | Kits to apply — OCI references, Git URLs, local paths, or ZIP archives |
ports | Port mappings (sandbox, host, protocol) |
secrets | Credentials to provision — see the next section |
bindings | Which domains a provisioned credential is allowed to be injected into |
mcp.servers | MCP servers to register (see Part 12) |
lifecycle | Host commands to run at initialize, postCreate, preRemove |
Relative paths in the file resolve from the file's own directory, and two
built-in variables help with that: ${{ env.fileDir }} (the directory
containing sbxenv.yaml) and ${{ env.projectDir }} (the workspace you
pointed the command at).
You can also keep a ~/.sbxenv.yaml with personal defaults (agent,
preferred workspace root) that every project file layers on top of — lists
concatenate, scalars get overridden, and the user file can't set name.
3. Secrets: three ways to supply a value
secrets declares credentials the sandbox needs, without putting the raw
value in a file you might commit:
secrets:
anthropic:
ref: op://Private/Anthropic/api-key # from a secrets vault
refresh: 55m
github:
command: gh auth token # run a host command, use its output
demo:
value: "not-a-real-secret" # literal — fine for local demos only
Each secret needs exactly one of value (a literal — visible in the file,
so don't use it for anything real), ref (a vault URI your secrets backend
resolves), or command (a command run on the host, whose output becomes
the secret value). bindings then says which domains that credential is
allowed to reach:
bindings:
github:
apiKey:
domains:
- api.github.com
The proxy injects the real value into outbound requests to those domains only — the agent inside the sandbox never sees the raw secret, the same credential-injection model you already saw with the MCP gateway.
4. Plan before you apply
Because an environment file can run host-side commands (lifecycle,
secrets.<name>.command), sbx shows you a plan before doing anything:
sbx env plan
This prints every host command it would run and why, every credential it
would provision (literal values shown only as a SHA-256 digest, references
shown as-is), and every environment variable, port, path, and MCP
registration it would set up. Nothing runs until you either approve
interactively or pass --auto-approve. A plan with no host commands at all
applies silently on later runs, once you've approved it the first time.
5. The full lifecycle: create, exec, rm
sbx env create # provision secrets, create the sandbox, don't attach
sbx env run # same, then attach to the agent
sbx env exec -- npm test # run a command in the existing sandbox, no lifecycle hooks
sbx env rm # remove the sandbox and the secrets scoped to it
All four read sbxenv.yaml from the current directory by default, or a
path you pass explicitly. sbx env rm --prune-bindings also removes the
host-global credential bindings and MCP registrations the file created —
by default those two things persist after the sandbox itself is gone,
since other sandboxes might still be using them.
Changing env values or MCP servers takes effect on the next sbx env run. Changing anything structural — the workspace, kits, ports, secrets,
or sandboxOptions — needs the sandbox recreated: sbx env rm, edit the
file, sbx env create again.
6. A worked example
A version of the backend stack from Part 6, declared instead of typed:
schemaVersion: "1"
name: sbx-crash-course-backend
agent: shell
workspace: ./backend
env:
NODE_ENV: development
ports:
- sandbox: 3000
host: 3000
secrets:
db_password:
value: postgres
lifecycle:
postCreate:
- command: npm install
workdir: ${{ env.fileDir }}/backend
sbx env run
One command reproduces the exact sandbox — workspace, port, and installed dependencies — that took several manual steps back in Part 6.
7. Beginner Pitfalls
secrets.<name>.valueis a literal string stored in the file. It's fine for thedemocase above, but never use it for a real API key — useref(a vault) orcommand(something likegh auth tokenorop read) instead.- A plan with host commands (a
lifecyclestep, or asecrets.*.command) asks for approval every single invocation unless you either pass--auto-approveor turn on the persistentenv.rememberHostCommandssetting — don't reach for--skip-host-commandsjust to make the prompt go away, since that also skips whatever setup those commands were doing. - Editing
sbxenv.yamldoesn't automatically apply to an already-running sandbox for structural fields (workspace, kits, ports, secrets). You need the explicitsbx env rm→ edit →sbx env createcycle, the same as you'd expect from any declarative config.
ទិញកាហ្វេជូនខ្ញុំ
ចូលចិត្តមេរៀននេះមែនទេ? សូមពិចារណាទិញកាហ្វេជូនខ្ញុំមួយកែវ ដើម្បីគាំទ្រការបង្កើតមាតិកាឥតគិតថ្លៃបន្ថែមទៀត!