Daytona
Run Claude Code in a Daytona sandbox with secrets injected via proxy
Overview
This example creates a Daytona sandbox with Claude Code pre-installed using the declarative image builder, and uses Oshu Vault to securely inject your Anthropic API key.
Prerequisites
- Daytona account and
DAYTONA_KEYset - Oshu Vault instance running
SECRETS_PROXY_API_KEY— your proxy management API keyANTHROPIC_API_KEY— your real Anthropic key
Install Dependencies
npm install @daytonaio/sdk @oshu/vault-sdkFull Example
import { Daytona, Image } from "@daytonaio/sdk";
import { SecretsProxyClient } from "@oshu/vault-sdk";
// --- Config ---
const PROXY_BASE_URL = "https://pv.oshu.dev";
const PROXY_HOST = "pv.oshu.dev";
const API_KEY = process.env.SECRETS_PROXY_API_KEY!;
const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY!;
// 1. Create a Oshu Vault session
const client = new SecretsProxyClient({
baseUrl: PROXY_BASE_URL,
apiKey: API_KEY,
});
const session = await client.createSession({
secrets: { ANTHROPIC_API_KEY },
});
const proxyUrl = `https://${session.session_id}:${session.token}@${PROXY_HOST}`;
// 2. Build a sandbox image with Claude Code + trusted CA cert
const image = Image.base("node:22-slim").runCommands(
"apt-get update && apt-get install -y curl ca-certificates && rm -rf /var/lib/apt/lists/*",
`curl -fsSL ${PROXY_BASE_URL}/v1/ca.pem -o /usr/local/share/ca-certificates/proxy-ca.crt && update-ca-certificates`,
"npm install -g @anthropic-ai/claude-code",
);
// 3. Create sandbox with proxy env vars
const daytona = new Daytona({ apiKey: process.env.DAYTONA_KEY });
const sandbox = await daytona.create(
{
image,
envVars: {
ANTHROPIC_API_KEY: session.sealed_secrets["ANTHROPIC_API_KEY"],
HTTP_PROXY: proxyUrl,
HTTPS_PROXY: proxyUrl,
NODE_EXTRA_CA_CERTS: "/etc/ssl/certs/ca-certificates.crt",
},
},
{ timeout: 0, onSnapshotCreateLogs: console.log },
);
try {
// 4. Run claude -p — no special flags, just works
const result = await sandbox.process.executeCommand(
`claude -p "Write a hello world program in Python"`,
);
console.log(result.result);
} finally {
await client.deleteSession(session.session_id);
await daytona.delete(sandbox);
}Declarative Image Builder
The key difference from E2B is Daytona's declarative image builder. Instead of installing tools and uploading certificates at runtime, everything is baked into the image — including the proxy's CA certificate:
const image = Image.base("node:22-slim").runCommands(
"apt-get update && apt-get install -y curl ca-certificates && rm -rf /var/lib/apt/lists/*",
`curl -fsSL ${PROXY_BASE_URL}/v1/ca.pem -o /usr/local/share/ca-certificates/proxy-ca.crt && update-ca-certificates`,
"npm install -g @anthropic-ai/claude-code",
);The CA certificate is static per proxy instance, so it's safe to bake into the image. update-ca-certificates adds it to the system trust store (used by curl, wget, etc.). Node.js ignores the system store, so you still need NODE_EXTRA_CA_CERTS in envVars — but it can point to the system bundle that already contains the cert.
Daytona caches this image for 24 hours, so subsequent sandbox creations skip the build step entirely. You can also pre-build it as a named snapshot:
await daytona.snapshot.create(
{ name: "claude-code", image },
{ onLogs: console.log },
);
// Then use it later — instant startup
const sandbox = await daytona.create({
snapshot: "claude-code",
envVars: { /* ... */ },
});What's Happening
Session created
The SDK sends your real ANTHROPIC_API_KEY to the proxy and gets back a sealed token like SEALED_7f3a9b2c....
Image built with Claude Code + trusted CA
Daytona builds a Docker image from node:22-slim with curl, Claude Code, and the proxy CA certificate pre-installed. The cert is fetched from /v1/ca.pem and added to the system trust store via update-ca-certificates. This image is cached for reuse.
Sandbox configured
The sandbox receives ANTHROPIC_API_KEY=SEALED_7f3a9b2c... and the proxy env vars. Everything looks normal to code running inside.
Secret injected on-the-fly
When Claude Code calls the Anthropic API, the proxy intercepts the request and replaces SEALED_7f3a9b2c... with your real API key.
The sandbox never sees your real API key. The declarative image builder runs before any secrets are configured, so even the build process has no access to sensitive values.