key=value pairs owned by an org. A machine sees each one as an environment
variable whose value is an opaque placeholder (ibsec_...). Your app sends that placeholder in its usual
header, to its usual HTTPS URL, and the outbound proxy swaps in the real value for the hosts the Secret
allows. The real key never lands on the machine’s disk or in its snapshots.
Save a Secret and give it to a machine
1
Save a Secret
To save a Secret, you need to be an org owner or admin.The CLI reads the value from stdin, or from a prompt without echo.
2
Give it to a machine
3
Use it as usual
The app reads
SERVICE_API_KEY and sends it as it always would, such as
Authorization: Bearer $SERVICE_API_KEY or X-Api-Key: $SERVICE_API_KEY. There is no separate
retrieval API.Scope a model provider key to its API
--ai scopes a model provider key to its API. The proxy puts the key into x-api-key or
Authorization only for that host.
You can repeat
--ai and combine it with --host.
Choose the hosts a Secret may go to
Each Secret lists the exact hosts it may be sent to. Without--host, it may go to every public HTTPS
destination (*). Partial wildcards such as *.example.com are not supported.
Change a running machine’s Secrets
--secrets allincludes Secrets created later.--secrets noneblocks the machine from all Secrets.- Rotating a value keeps its placeholder, so apps need no restart.
- If you remove a Secret and recreate it with the same name, an explicit grant to the old one is not restored.
Use a Secret for git over HTTPS
Git sends its token as Basic auth, which the proxy handles, sogit clone and git push to private
repos work with a placeholder. Add github.com (for git) to the Secret’s hosts next to api.github.com
(for gh). Then give git a credential helper that returns the placeholder, such as
gh auth setup-git for GH_TOKEN.
Import a .env file
instabox secrets select, as above.
Turn off QUIC in browsers
The proxy sees HTTPS over TCP port 443 only. HTTP/3 (QUIC, on UDP 443) bypasses it, so the API receives the placeholder and usually refuses it, for example with401. curl and most HTTP libraries use TCP,
but Chromium may still pick HTTP/3. In a Chromium-based browser that sends Secrets, turn QUIC off:
chromium.launch({ args: ['--disable-quic'] }) or
puppeteer.launch({ args: ['--disable-quic'] }). The browser must also trust the sandbox CA with normal
certificate checks. Do not turn verification off.
Put the real value in the machine with a direct Secret
A direct Secret (--direct in the CLI, delivery: "env" in the API) puts the real value in the
machine, as a variable or a file. Use one when the proxy cannot carry the credential.
As an owner or admin, save the Secret as direct. Then reference it from a machine as a variable, a home
file, or both:
--secret-env VAR=SECRET, or--secret-env SECRETfor the same name--secret-file PATH=SECRET
Select Secrets over the HTTP API
Select Secrets when you create a machine withPOST /v1/machines:
/v1/machines/{id}/secrets:
PATCHsets a new selection. Explicitnullselections are rejected.GETreturns metadata and status.POSTrefreshes delivery now.
directSecrets replaces the machine’s direct references. "envSecrets": ["DATABASE_URL"] is the
same-name shorthand. Send one or the other, not both. "secrets": "all" never includes env (direct)
Secrets, which reach a machine only through envSecrets or directSecrets.
For one command, POST /v1/machines/{id}/exec takes "secretEnvs": {"DATABASE_URL": "PROD_PG"}.
To save a Secret over HTTP, see “Save a Secret” under Reference. Full schemas are in the
API reference.
How it works
The proxy carries proxy Secrets, and files and variables carry direct ones. The details below say what the proxy changes in a request, when a change reaches a machine, and which processes see the values.What the proxy replaces, and what it does not
What the proxy replaces, and what it does not
The proxy checks the machine’s authorization, the host scope, and the upstream TLS certificate. Then
it replaces the placeholder inside a header value. It supports HTTPS on port 443 only, and it does
not substitute URL parameters or request bodies.
- For HTTP Basic auth in
Authorization, the proxy decodes the credential, replaces the placeholder insideuser:password, and re-encodes it. Any other encoding or signing of the placeholder prevents replacement. - The proxy intercepts all supported HTTPS hosts, even without a placeholder. Clients must trust the sandbox CA and cannot pin certificates.
- The proxy closes intercepted connections to private addresses.
- WebSockets work. The proxy replaces placeholders in the handshake headers, not in messages.
- The proxy drops
Alt-Svcfrom the responses it relays. Chromium may still choose HTTP/3 from DNS, or from an earlier visit saved in its profile.
Delivery status and timing
Delivery status and timing
instabox secrets show reports proxy authorization and placeholder setup separately. A proxy update
is pending until acknowledged, and an acknowledged lease expires within at most 60 seconds without
renewal. Requests already admitted, streams included, may finish.Servers with per-sandbox usage show each Secret’s proxied and denied request counts in
secrets show and GET /v1/machines/{id}/secrets.Which processes see the variables
Which processes see the variables
Secrets are written to
/run/instabox/secrets/env (tmpfs, mode 0600, owned by the machine’s user)
and loaded by /etc/profile.d/zz-instabox-secrets.sh. Login shells get them: SSH, instabox exec,
and the exec API.Processes that skip the profile do not get them, such as systemd units, cron, and bash -c without
-l. Running processes keep their old environment until restarted.Where a direct value lives
Where a direct value lives
Variables go to
/run/instabox/secrets/env. A file’s value is written to
/run/instabox/secrets/files/ (tmpfs, mode 0600, owned by the machine’s user), and the home path
becomes a symlink to it. So the disk, disk snapshots, and forks never hold the value.If the path already holds a file of the machine’s, the file is left alone and secrets show reports
the error. Move the file and run secrets push. A tool that rewrites its login file replaces the
link with a real file on the disk, which is then the machine’s own.Rotation, removal and forks
Rotation, removal and forks
A new value reaches running machines within about 10 seconds. Files change in place and new shells
get the new variable, but running processes keep the old one until restarted. Stopped and paused
machines get the current value when they start or resume. Deleting the Secret or the reference
removes the variable and the file at the next delivery.Forks copy the source’s Secret selection, both proxy and direct, and resolve the values again. A
machine created from a snapshot takes only its own selection.
Reference
Save a Secret: PUT /v1/orgs/{id}/secrets/{name}
Save a Secret: PUT /v1/orgs/{id}/secrets/{name}
A new Secret answers
201 Created, and a replacement 200 OK. Both carry metadata and never the
value: id, orgId, name, delivery, hosts, version, size, createdAt, and updatedAt.POST /v1/orgs/{id}/secrets/import takes {"values":{...},"delivery":...,"hosts":[...]}, with the
same rules for every entry. A missing delivery there answers 400 delivery must be proxy or env.
The CLI saves proxy unless you pass --direct.This example saves a proxy Secret in your personal org. It keeps the token header in a mode 0600 file
and sends the body on stdin, so neither appears in the process list:jq -Rs '{value: rtrimstr("\n"), delivery: "proxy", hosts: ["api.example.com"]}' <key.txt, and
pipe it into the same curl. For an env Secret, send {"value":"postgresql://...","delivery":"env"}
to .../secrets/DATABASE_URL.Who can do what
Who can do what
- Manage values (create, import, change, delete): an org owner or admin, signed in, or the
workspace’s own
workspace:adminAPI key sent asX-API-Key. Afterinstabox login, the CLI’s access token works, andinstabox whoamirefreshes it. A personal org’s key and narrower keys get403 missing_scope. Management reads never return values. - Read Secret metadata and machine selections: keys with
machines:read. - Change selections and refresh delivery: keys with
machines:write.
workspace:admin key in INSTABOX_API_KEY. Org commands then default to
the key’s org, and secrets rm needs --yes without a terminal.Who can reference direct Secrets
Who can reference direct Secrets
Only an org owner or admin can save a Secret as direct. Anyone who can change a machine
(
machines:write) in the org can reference the org’s direct Secrets. A proxy Secret can never be
referenced as direct, and a Secret of another org cannot be referenced at all.Reserved names
Reserved names
The name is the variable the machine exports, so it follows the rule for
Environment variables. A name that env refuses is refused here too
(
400 bad_request), including BASH_ENV, ENV, and IFS.A Secret saved under a name before the name was reserved is not delivered. The rest of the selection
is delivered, secrets show reports not delivered: <names>, and secrets push answers 400. To
fix it, save the value under another name, select it, delete the old Secret, and run secrets push.Direct Secrets: names, paths and limits
Direct Secrets: names, paths and limits
Variable names follow the Secret name rule. They cannot be
PATH, HOME, BASH_ENV, IFS, or the
CA variables, and they cannot start with INSTABOX_ or SSH_.Paths are relative to the machine’s home directory: write .ssh/id_ed25519, not
~/.ssh/id_ed25519. The shell turns an unquoted ~/ into your own home, and the CLI takes that back
as home-relative. A machine has at most 64 direct references.No API returns a value. secrets show and GET /v1/machines/{id}/secrets list directSecrets as
names and paths. Each reference (create, select, fork, exec) is audited by name.Vault, and opting out
Vault, and opting out
Vault (per-user) and Org Secrets are independent stores, with no automatic migration. Existing Vault
env values, file delivery, and metadata selectors keep working, and a machine can use both. For a
same-named variable, an explicitly selected Secret wins.
- Omitting
secretson create keeps the Vault behavior without enrolling the machine in Secrets. --no-vault --secrets nonedisables delivery from both stores on a new machine.--no-vault, and the SDK optionvault: false, affect only Vault. Clearing Secret selections affects only Secrets. Where an SDK does not expose Secret selection fields, use the CLI or HTTP API.instabox vault export NAME --out recovered.jsonremains for items kept by an earlier explicit migration. Its output contains the real value.
Environment variables
Plain variables, and the names a machine refuses.
API keys
Scopes, including
workspace:admin.