Environment variables
Pass configuration, secrets, and runtime settings to your sandboxes using environment variables.
The Sandbox SDK provides three methods for setting environment variables, each suited for different use cases:
Set environment variables globally for all commands in the sandbox:
const sandbox = getSandbox(env.Sandbox, "my-sandbox");
// Set once, available for all subsequent commandsawait sandbox.setEnvVars({ DATABASE_URL: env.DATABASE_URL, API_KEY: env.API_KEY,});
await sandbox.exec("python migrate.py"); // Has DATABASE_URL and API_KEYawait sandbox.exec("python seed.py"); // Has DATABASE_URL and API_KEYUse when: You need the same environment variables for multiple commands.
Pass environment variables for a specific command:
await sandbox.exec("node app.js", { env: { NODE_ENV: "production", PORT: "3000", },});
// Also works with startProcess()await sandbox.startProcess("python server.py", { env: { DATABASE_URL: env.DATABASE_URL, },});Use when: You need different environment variables for different commands, or want to override sandbox-level variables.
Create an isolated session with its own environment variables:
const session = await sandbox.createSession({ env: { DATABASE_URL: env.DATABASE_URL, SECRET_KEY: env.SECRET_KEY, },});
// All commands in this session have these varsawait session.exec("python migrate.py");await session.exec("python seed.py");Use when: You need isolated execution contexts with different environment variables running concurrently.
Securely pass secrets from your Worker to the sandbox. First, set secrets using Wrangler:
wrangler secret put OPENAI_API_KEYwrangler secret put DATABASE_URLThen pass them to your sandbox:
interface Env { Sandbox: DurableObjectNamespace; OPENAI_API_KEY: string; DATABASE_URL: string;}
export default { async fetch(request: Request, env: Env): Promise<Response> { const sandbox = getSandbox(env.Sandbox, "user-sandbox");
// Option 1: Set globally for all commands await sandbox.setEnvVars({ OPENAI_API_KEY: env.OPENAI_API_KEY, DATABASE_URL: env.DATABASE_URL, }); await sandbox.exec("python analyze.py");
// Option 2: Pass per-command await sandbox.exec("python analyze.py", { env: { OPENAI_API_KEY: env.OPENAI_API_KEY, }, });
return Response.json({ success: true }); },};const defaults = { NODE_ENV: "production", LOG_LEVEL: "info" };
await sandbox.exec("npm start", { env: { ...defaults, PORT: "3000", API_KEY: env.API_KEY },});Run different tasks with different environment variables concurrently:
// Production database sessionconst prodSession = await sandbox.createSession({ env: { DATABASE_URL: env.PROD_DATABASE_URL },});
// Staging database sessionconst stagingSession = await sandbox.createSession({ env: { DATABASE_URL: env.STAGING_DATABASE_URL },});
// Run migrations on both concurrentlyawait Promise.all([ prodSession.exec("python migrate.py"), stagingSession.exec("python migrate.py"),]);When mounting S3-compatible object storage, the SDK uses s3fs-fuse under the hood, which requires AWS-style credentials. For R2, generate API tokens from the Cloudflare dashboard and provide them using AWS environment variable names:
Get R2 API tokens:
- Go to R2 > Overview ↗ in the Cloudflare dashboard
- Select Manage R2 API Tokens
- Create a token with Object Read & Write permissions
- Copy the Access Key ID and Secret Access Key
Set credentials as Worker secrets:
wrangler secret put AWS_ACCESS_KEY_ID# Paste your R2 Access Key ID
wrangler secret put AWS_SECRET_ACCESS_KEY# Paste your R2 Secret Access KeyMount buckets with automatic credential detection:
interface Env { Sandbox: DurableObjectNamespace; AWS_ACCESS_KEY_ID: string; AWS_SECRET_ACCESS_KEY: string;}
export default { async fetch(request: Request, env: Env): Promise<Response> { const sandbox = getSandbox(env.Sandbox, 'data-processor');
// Credentials automatically detected from environment await sandbox.mountBucket('my-r2-bucket', '/data', { endpoint: 'https://YOUR_ACCOUNT_ID.r2.cloudflarestorage.com' });
// Access mounted bucket using standard file operations await sandbox.exec('python', { args: ['process.py', '/data/input.csv'] });
return Response.json({ success: true }); }};The SDK automatically detects AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY from your Worker's environment when you call mountBucket() without explicit credentials.
Pass credentials explicitly (if using custom secret names):
await sandbox.mountBucket('my-r2-bucket', '/data', { endpoint: 'https://YOUR_ACCOUNT_ID.r2.cloudflarestorage.com', credentials: { accessKeyId: env.R2_ACCESS_KEY_ID, secretAccessKey: env.R2_SECRET_ACCESS_KEY }});See Mount buckets guide for complete bucket mounting documentation.
When the same variable is set at multiple levels, the most specific level takes precedence:
- Command-level (highest) - Passed to
exec()orstartProcess()options - Sandbox or session-level - Set with
setEnvVars() - Container default - Built into the Docker image with
ENV - System default (lowest) - Operating system defaults
Example:
// In Dockerfile: ENV NODE_ENV=development
// Sandbox-levelawait sandbox.setEnvVars({ NODE_ENV: "staging" });
// Command-level overrides allawait sandbox.exec("node app.js", { env: { NODE_ENV: "production" }, // This wins});- Wrangler configuration - Setting Worker-level environment
- Secrets - Managing sensitive data
- Sessions API - Session-level environment variables
- Security model - Understanding data isolation
Was this helpful?
- Resources
- API
- New to Cloudflare?
- Directory
- Sponsorships
- Open Source
- Support
- Help Center
- System Status
- Compliance
- GDPR
- Company
- cloudflare.com
- Our team
- Careers
- © 2025 Cloudflare, Inc.
- Privacy Policy
- Terms of Use
- Report Security Issues
- Trademark