Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/content/docs/sandbox/api/ports.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ await sandbox.startProcess('python -m http.server 8000');
const exposed = await sandbox.exposePort(8000, { hostname });

console.log('Available at:', exposed.exposedAt);
// https://8000-abc123.yourdomain.com
// https://8000-abc123-a1b2c3d4e5f6g7h8.yourdomain.com

// Multiple services with names
await sandbox.startProcess('node api.js');
Expand Down
24 changes: 15 additions & 9 deletions src/content/docs/sandbox/concepts/preview-urls.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,27 @@ await sandbox.startProcess("python -m http.server 8000");
const exposed = await sandbox.exposePort(8000, { hostname });

console.log(exposed.exposedAt);
// Production: https://8000-abc123.yourdomain.com
// Production: https://8000-abc123-a1b2c3d4e5f6g7h8.yourdomain.com
// Local dev: http://localhost:8787/...
```

## URL Format

**Production**: `https://{port}-{sandbox-id}.yourdomain.com`
**Production**: `https://{port}-{sandbox-id}-{token}.yourdomain.com`

- Port 8080: `https://8080-abc123.yourdomain.com`
- Port 3000: `https://3000-abc123.yourdomain.com`
- Port 8080: `https://8080-abc123-a1b2c3d4e5f6g7h8.yourdomain.com`
- Port 3000: `https://3000-abc123-x9y8z7w6v5u4t3s2.yourdomain.com`

**Local development**: `http://localhost:8787/...`

The token is a 16-character random string containing only lowercase alphanumeric characters and hyphens, ensuring DNS compliance with RFC 952/1123 hostname requirements.

Preview URLs remain stable while a port is exposed and can be shared during that time. However, if you unexpose and re-expose a port, a new random token is generated and the URL changes. For persistent URLs, keep ports exposed for the duration you need them accessible.

:::note[Token format change - SDK v0.5.4+]
Starting in SDK version 0.5.4, preview URL tokens use only DNS-valid characters (RFC 952/1123 compliant). Tokens generated by earlier versions containing underscores are automatically migrated when you access the sandbox. This is a breaking change - old preview URLs with underscores will stop working after upgrade. Call `exposePort()` again to get new DNS-compliant URLs.
:::

## ID Case Sensitivity

Preview URLs extract the sandbox ID from the hostname to route requests. Since hostnames are case-insensitive (per RFC 3986), they're always lowercased: `8080-MyProject-123.yourdomain.com` becomes `8080-myproject-123.yourdomain.com`.
Expand Down Expand Up @@ -101,9 +107,9 @@ await sandbox.startProcess("node admin.js"); // Port 3001
const api = await sandbox.exposePort(3000, { hostname, name: "api" });
const admin = await sandbox.exposePort(3001, { hostname, name: "admin" });

// Each gets its own URL:
// https://3000-abc123.yourdomain.com
// https://3001-abc123.yourdomain.com
// Each gets its own URL with unique tokens:
// https://3000-abc123-x1y2z3w4v5u6t7s8.yourdomain.com
// https://3001-abc123-p9q8r7s6t5u4v3w2.yourdomain.com
```

## What Works
Expand Down Expand Up @@ -155,9 +161,9 @@ Preview URLs are publicly accessible by default, but require a valid access toke

**Built-in security**:

- **Token-based access** - Each exposed port gets a unique token in the URL (for example, `https://8080-sandbox-abc123token.yourdomain.com`)
- **Token-based access** - Each exposed port gets a unique 16-character token in the URL (for example, `https://8080-sandbox-a1b2c3d4e5f6g7h8.yourdomain.com`)
- **HTTPS in production** - All traffic is encrypted with automatic TLS
- **Unpredictable URLs** - Tokens are randomly generated and difficult to guess
- **Unpredictable URLs** - Tokens are cryptographically random and use only DNS-valid characters (lowercase alphanumeric and hyphens per RFC 952/1123)

**Add application-level authentication**:

Expand Down
10 changes: 6 additions & 4 deletions src/content/docs/sandbox/guides/expose-services.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export default {

// 4. Preview URL is now available (public by default)
console.log('Server accessible at:', exposed.exposedAt);
// Production: https://8000-abc123.yourdomain.com
// Production: https://8000-abc123-a1b2c3d4e5f6g7h8.yourdomain.com
// Local dev: http://localhost:8787/...

return Response.json({ url: exposed.exposedAt });
Expand Down Expand Up @@ -330,10 +330,12 @@ See [Sandbox options - normalizeId](/sandbox/configuration/sandbox-options/#norm

## Preview URL Format

**Production**: `https://{port}-{sandbox-id}.yourdomain.com`
**Production**: `https://{port}-{sandbox-id}-{token}.yourdomain.com`

- Port 8080: `https://8080-abc123.yourdomain.com`
- Port 5173: `https://5173-abc123.yourdomain.com`
- Port 8080: `https://8080-abc123-a1b2c3d4e5f6g7h8.yourdomain.com`
- Port 5173: `https://5173-abc123-x9y8z7w6v5u4t3s2.yourdomain.com`

The token is a 16-character random string using only DNS-valid characters (lowercase alphanumeric and hyphens per RFC 952/1123).

**Local development**: `http://localhost:8787/...`

Expand Down
4 changes: 2 additions & 2 deletions src/content/docs/sandbox/guides/production-deployment.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { WranglerConfig } from "~/components";
Custom domain setup is ONLY needed if you use `exposePort()` to expose services from sandboxes. If your application does not expose ports, you can deploy to `.workers.dev` without this configuration.
:::

Deploy your Sandbox SDK application to production with preview URL support. Preview URLs require wildcard DNS routing because they generate unique subdomains for each exposed port: `https://8080-abc123.yourdomain.com`.
Deploy your Sandbox SDK application to production with preview URL support. Preview URLs require wildcard DNS routing because they generate unique subdomains for each exposed port: `https://8080-abc123-a1b2c3d4e5f6g7h8.yourdomain.com`.

The `.workers.dev` domain does not support wildcard subdomains, so production deployments that use preview URLs need a custom domain.

Expand Down Expand Up @@ -74,7 +74,7 @@ await sandbox.startProcess('python -m http.server 8080');
const exposed = await sandbox.exposePort(8080, { hostname });

console.log(exposed.exposedAt);
// https://8080-test-sandbox.yourdomain.com
// https://8080-test-sandbox-a1b2c3d4e5f6g7h8.yourdomain.com
```

Visit the URL in your browser to confirm your service is accessible.
Expand Down
Loading