# How to Customize the Environment in Microsandbox: Sandbox-Wide and Per-Command Variables

> Learn to customize your Microsandbox environment with sandbox-wide, per-command, and secret variables for flexible and secure command execution. Master environment control.

- Repository: [Super Rad Company/microsandbox](https://github.com/superradcompany/microsandbox)
- Tags: how-to-guide
- Published: 2026-08-20

---

**You can customize the environment in Microsandbox by setting sandbox-wide variables that apply to all commands, per-command variables for single invocations, or secret variables that never expose values inside the guest.**

The Microsandbox SDK provides a layered approach to environment customization across Rust, Python, Node.js TypeScript, and Go. Whether you need global configuration values, temporary overrides for specific commands, or secure secrets that stay hidden from logs and guest inspection, the environment system gives you precise control over what reaches your sandboxed workloads.

## Sandbox-Wide Environment Variables

Sandbox-wide variables are available to every command that runs inside the sandbox. These are set at build time and stored in the sandbox's `spec.env` list.

### Setting Global Environment Variables

Use your SDK's builder API to define variables that persist across all executions:

**Rust ([`sdk/rust/lib/sandbox/builder.rs`](https://github.com/superradcompany/microsandbox/blob/main/sdk/rust/lib/sandbox/builder.rs))**

```rust
let sb = Sandbox::builder("demo")
    .env("APP_ENV", "production")
    .env("LOG_LEVEL", "info")
    .create().await?;

```

**Python ([`sdk/python/src/helpers.rs`](https://github.com/superradcompany/microsandbox/blob/main/sdk/python/src/helpers.rs))**

```python
sb = await Sandbox.create(
    "demo",
    env={"APP_ENV": "production", "LOG_LEVEL": "info"}
)

```

**Node.js TypeScript ([`sdk/node-ts/native/sandbox_builder.rs`](https://github.com/superradcompany/microsandbox/blob/main/sdk/node-ts/native/sandbox_builder.rs))**

```typescript
const sb = await microsandbox.Sandbox.builder("demo")
    .env("APP_ENV", "production")
    .env("LOG_LEVEL", "info")
    .create();

```

**Go ([`sdk/go/native/src/lib.rs`](https://github.com/superradcompany/microsandbox/blob/main/sdk/go/native/src/lib.rs))**

```go
sb, _ := microsandbox.NewSandbox(
    "demo",
    microsandbox.WithEnv("APP_ENV", "production"),
    microsandbox.WithEnv("LOG_LEVEL", "info"),
)

```

These values merge with any defaults baked into the container image, with builder-provided values taking precedence over duplicates.

## Per-Command Environment Variables

Override or extend the environment for a single `exec` or `shell` invocation without affecting the sandbox's global configuration.

### Temporary Environment Overrides

**Rust**

```rust
let out = sb.exec(
    "sh",
    ["-c", "echo $APP_ENV"],
    |e| e.env("APP_ENV", "staging")  // Overrides global "production"
).await?;

```

**Python**

```python
out = await sb.exec(
    "sh",
    ["-c", "echo $APP_ENV"],
    env={"APP_ENV": "staging"}
)

```

**Node.js TypeScript**

```typescript
const out = await sb.exec(
    "sh",
    ["-c", "echo $APP_ENV"],
    { env: { APP_ENV: "staging" } }
);

```

**Go**

```go
out, _ := sb.Exec(
    "sh",
    []string{"-c", "echo $APP_ENV"},
    microsandbox.ExecEnv(map[string]string{"APP_ENV": "staging"}),
)

```

Per-command variables are ideal for testing different configurations, injecting request-specific metadata, or temporarily elevating log verbosity.

## Secret Environment Variables

For sensitive values that must never appear in logs, process listings, or the guest environment, use the **secret API** (`SandboxBuilder::secret_env` in Rust, `sandbox.secret_env` in Python, `sandbox.secretEnv` in Node.js TypeScript, `builder.SecretEnv` in Go).

Secrets are sent only to explicitly allowed hosts. The system auto-generates a placeholder (`$MSB_<ENV_VAR>`) for use inside the sandbox—the real value remains protected outside the allowed communication channel.

### Using Secret Variables

**Rust**

```rust
let sb = Sandbox::builder("demo")
    .secret_env("OPENAI_API_KEY", api_key, "api.openai.com")
    .create().await?;

```

**Python**

```python
sb = await Sandbox.create(
    "demo",
    secrets=[{
        "env": "OPENAI_API_KEY",
        "value": os.getenv("OPENAI_API_KEY"),
        "allowed_host": "api.openai.com"
    }]
)

```

**Node.js TypeScript**

```typescript
const sb = await microsandbox.Sandbox.builder("demo")
    .secretEnv("OPENAI_API_KEY", process.env.OPENAI_API_KEY!, "api.openai.com")
    .create();

```

**Go**

```go
sb, _ := microsandbox.NewSandbox(
    "demo",
    microsandbox.WithSecretEnv("OPENAI_API_KEY", apiKey, "api.openai.com"),
)

```

The `allowed_host` parameter restricts where the secret can be sent, providing defense in depth for API keys, database credentials, and other sensitive tokens.

## Reserved Keys and Validation

The Microsandbox protocol defines reserved environment keys in [`crates/protocol/lib/lib.rs`](https://github.com/superradcompany/microsandbox/blob/main/crates/protocol/lib/lib.rs) (lines 123-411). Keys prefixed with `MSB_` are reserved for internal use—examples include `MSB_BLOCK_ROOT` and `MSB_NET`.

Attempts to set user-defined variables with the `MSB_` prefix are rejected with a clear error. This validation occurs in [`sdk/rust/lib/sandbox/builder.rs`](https://github.com/superradcompany/microsandbox/blob/main/sdk/rust/lib/sandbox/builder.rs) at line 922, ensuring protocol integrity and preventing accidental conflicts with runtime-critical values.

## How Environment Merging Works

When a sandbox is built, [`sdk/rust/lib/sandbox/config.rs`](https://github.com/superradcompany/microsandbox/blob/main/sdk/rust/lib/sandbox/config.rs) (functions `merge_env` and `merge_init_env`, lines 492-506) combines three sources in order:

1. **Image defaults** (`image.env`) — Loaded from the container image
2. **Builder-wide env** (`SandboxBuilder::env`) — Merged after image defaults, overriding duplicates
3. **Init-time env** (`InitOptionsBuilder`) — Applied only to the init process (see [`sandbox/init.rs`](https://github.com/superradcompany/microsandbox/blob/main/sandbox/init.rs))

Both sandbox-wide and per-command variables ultimately become part of the **protocol environment block** that the runtime injects into the guest process.

## Summary

- **Sandbox-wide variables** apply to all commands via builder methods (`SandboxBuilder::env`, `Sandbox.env`, `sandbox.env`, `builder.Env`)
- **Per-command variables** override for single invocations via execution options (`ExecOptionsBuilder::env`, `Sandbox.exec(..., env=...)`, `exec.env`, `ExecOptions.Env`)
- **Secret variables** protect sensitive values from exposure using host-restricted placeholders (`secret_env`, `secretEnv`, `SecretEnv`)
- **Reserved keys** with `MSB_` prefix are rejected by validation logic in [`builder.rs`](https://github.com/superradcompany/microsandbox/blob/main/builder.rs)
- **Merge order** is: image defaults → builder env → init-time env, with later sources overriding earlier ones

## Frequently Asked Questions

### Can I use both sandbox-wide and per-command environment variables together?

Yes. Per-command variables layer on top of sandbox-wide variables. When you specify `env` in an `exec` call, those values override any matching keys from the global environment for that single invocation. Non-conflicting keys from both sources remain available.

### What happens if I try to set a variable with the MSB_ prefix?

The SDK rejects the request with a validation error. In [`sdk/rust/lib/sandbox/builder.rs`](https://github.com/superradcompany/microsandbox/blob/main/sdk/rust/lib/sandbox/builder.rs) at line 922, the code checks for this prefix and prevents user-defined variables from conflicting with reserved protocol keys like `MSB_BLOCK_ROOT` and `MSB_NET`. Choose variable names without the `MSB_` prefix.

### How are secret variables different from regular environment variables?

Secret variables never expose their real values inside the sandbox or in any logs. Instead, the system generates a placeholder (`$MSB_OPENAI_API_KEY` for a secret named `OPENAI_API_KEY`). The actual value is transmitted only to the explicitly allowed host you specified. This protects API keys and credentials from guest inspection and process dumps.

### Which SDK methods handle environment configuration in Microsandbox?

The core methods are `SandboxBuilder::env` and `SandboxBuilder::secret_env` in Rust, available with equivalent names across all SDKs. The merge logic lives in [`sdk/rust/lib/sandbox/config.rs`](https://github.com/superradcompany/microsandbox/blob/main/sdk/rust/lib/sandbox/config.rs), validation in [`sdk/rust/lib/sandbox/builder.rs`](https://github.com/superradcompany/microsandbox/blob/main/sdk/rust/lib/sandbox/builder.rs), and protocol constants in [`crates/protocol/lib/lib.rs`](https://github.com/superradcompany/microsandbox/blob/main/crates/protocol/lib/lib.rs).