Use Project Secrets before you run SDKs, scripts, or coding agents inside boxes that need upstream AI access.
Project Secrets let you call AI providers without putting the real API key in a box. Save the real key in Portal, put the placeholder in the box, and keep using the provider’s normal API URL.
Portal Project Secret
real key: sk-real-provider-secret
placeholder: run9secret_abcd1234
Managed box
OPENAI_API_KEY=run9secret_abcd1234
|
v
Request to api.openai.com
Authorization: Bearer run9secret_abcd1234
|
v
run9 egress replaces the placeholder
|
v
Provider sees the real key
No replacement happens in normal boxes, or when the request does not match the configured host and header.
Create a Project Secret
Project admins can create project-scoped secrets that work in every managed box in the project. Project members can create box-scoped secrets for a specific box.
Create the rule from your terminal. The command prints the generated Placeholder; use that placeholder inside managed boxes.
printf '%s' "$REAL_PROVIDER_SECRET" | sys9 run project secrets create \
--name provider-name \
--value-file - \
--allowed-host api.provider.example \
--header-name Authorization
Use sys9 run project secrets ls to list existing rules, sys9 run project secrets update <secret-id> to replace the value or rule metadata, and sys9 run project secrets rm <secret-id> to delete one.
To scope the rule to one box, create a Box Secret for that box:
printf '%s' "$REAL_PROVIDER_SECRET" | sys9 run box secrets create ai-box \
--name provider-name \
--value-file - \
--allowed-host api.provider.example \
--header-name Authorization
Use sys9 run box secrets ls ai-box to list only that box’s scoped rules. You can also create project-scoped rules in Portal from Project Settings -> Secrets, or box-scoped rules from a Portal Box Detail page’s Secrets tab.
V1 uses custom rules only. There are no provider presets: choose the domain and header rule yourself.
Use a Managed box
Project Secret substitution only runs for boxes with Network = Managed.
When you create a box from the CLI, pass --network managed:
sys9 run box create ai-box --network managed
In Portal, choose Managed in the Network field. If an existing box is still Normal, change it to Managed, then start a new exec so run9 creates a new managed instance.
OpenAI-compatible clients
Create a Project Secret:
printf '%s' "$REAL_OPENAI_API_KEY" | sys9 run project secrets create \
--name openai \
--value-file - \
--allowed-host api.openai.com \
--header-name Authorization
Inside a managed box:
export OPENAI_API_KEY=<project-secret-placeholder>
Keep the normal OpenAI base URL. The client builds Authorization: Bearer <project-secret-placeholder>, and run9 replaces only the placeholder part before the request leaves the box.
Anthropic-compatible clients
Create a Project Secret:
printf '%s' "$REAL_ANTHROPIC_API_KEY" | sys9 run project secrets create \
--name anthropic \
--value-file - \
--allowed-host api.anthropic.com \
--header-name X-Api-Key
Inside a managed box:
export ANTHROPIC_API_KEY=<project-secret-placeholder>
Keep the normal Anthropic API endpoint. run9 replaces the placeholder in X-Api-Key only when the request host matches api.anthropic.com.
First checks when requests fail
Check these things before changing client code:
- the box is using
Network = Managed - the request goes to a host listed in
Allowed Hosts - the client sends the placeholder in the configured
Header Name - the configured header value contains the placeholder
- the client is not using QUIC, HTTP/3, mTLS, or certificate pinning
Why this is safer
- the real provider secret stays in project settings instead of box storage
- box-scoped secrets only apply to the selected box
- each project controls exactly which hosts and headers can receive the secret
- forking a box or snap does not copy the real provider secret
- normal boxes keep ordinary network behavior and do not run Project Secret substitution