DOCS

Environment variables

Set encrypted environment variables on a sandbox at spawn or at runtime — available to every process you start in it.

Sandboxes can carry environment variables: API keys, config flags, connection strings. qbox stores them encrypted at rest (AES-256-GCM) and pushes them into the running sandbox, so any process you start afterward — commands.run, run_code, an SSH shell — inherits them.

Where envs come from

The set a process sees is the merge of two layers, sandbox winning on a tie:

SourceSet onNotes
templatethe templateinherited by every sandbox built from it
userthe sandboxwhat you set via the SDK/CLI/API/dashboard
volumederivedQBOX_VOLUME_<name>_*, added automatically when you attach a volume

list annotates each variable with its source.

At spawn time

import qbox

sandbox = qbox.Sandbox.create(
    "python-3.12",
    envs={"OPENAI_API_KEY": "sk-...", "LOG_LEVEL": "debug"},
)

At runtime

sandbox.envs.set({"OPENAI_API_KEY": "sk-new"})   # upsert
sandbox.envs.delete(["OLD_KEY"])                  # remove some
sandbox.envs.clear()                              # remove all *user* envs
sandbox.envs.set_all({"A": "1"})                  # replace all user envs

sandbox.envs.get("OPENAI_API_KEY")                # -> "sk-new" | None
sandbox.envs.get_all()                            # -> {"OPENAI_API_KEY": ..., ...}
sandbox.envs.list(mask=True)                      # values elided for logging
sandbox.envs.upload_dotenv("./.env")              # bulk-load a .env file

New processes pick up changes immediately; already-running processes keep the environment they started with.

Rules

  • Keys match [A-Z_][A-Z0-9_]* (uppercase, digits, underscore; can’t start with a digit).
  • The QBOX_ prefix is reserved (qbox uses it for volume-derived vars).
  • Up to 64 KB per value, 256 KB per sandbox total.

Violations return 422 with a code like env_key_invalid, env_key_reserved, or env_value_too_large.

CLI

qbox sandboxes envs set sb_123 OPENAI_API_KEY=sk-... LOG_LEVEL=debug
qbox sandboxes envs list sb_123            # masked by default
qbox sandboxes envs list sb_123 --reveal   # show values
qbox sandboxes envs delete sb_123 OLD_KEY
qbox sandboxes envs upload sb_123 ./.env
qbox sandboxes create python-3.12 --env OPENAI_API_KEY=sk-... --env LOG_LEVEL=debug

HTTP

MethodPathNotes
GET/v1/sandboxes/{id}/envs?mask=true to elide values; returns a version (ETag)
PATCH/v1/sandboxes/{id}/envsupsert { "envs": {…} }
PUT/v1/sandboxes/{id}/envsreplace all user envs
DELETE/v1/sandboxes/{id}/envs{ "keys": [...] }
POST/v1/sandboxes/{id}/envs/uploadraw .env body

Writes accept an If-Match: <version> header for optimistic concurrency (412 version_mismatch if it changed since you read it). API keys need the sandboxes:envs scope to read or write envs.

Security

Values are encrypted with the server’s master key (QBOX_ENV_MASTER_KEY) and the ciphertext is bound to its row, so it can’t be moved between sandboxes. The audit log records key names and lengths — never values. The list API can mask values; the dashboard hides them behind a reveal toggle.