From 5e79e97673f455d86118fba79a003805495920bd Mon Sep 17 00:00:00 2001
From: aron <263346377+aron-cf@users.noreply.github.com>
Date: Mon, 18 May 2026 12:12:27 +0100
Subject: [PATCH 1/6] [Sandboxes] Add new docs for tunnel support
---
src/content/docs/sandbox/api/index.mdx | 6 +
src/content/docs/sandbox/api/tunnels.mdx | 151 +++++++++++++++++++++++
2 files changed, 157 insertions(+)
create mode 100644 src/content/docs/sandbox/api/tunnels.mdx
diff --git a/src/content/docs/sandbox/api/index.mdx b/src/content/docs/sandbox/api/index.mdx
index 8a3d0dabac46bb5..411c6eab0594f69 100644
--- a/src/content/docs/sandbox/api/index.mdx
+++ b/src/content/docs/sandbox/api/index.mdx
@@ -52,6 +52,12 @@ The Sandbox SDK provides a comprehensive API for executing code, managing files,
and APIs from the internet.
+
+ Expose services on zero-config `*.trycloudflare.com` URLs via
+ `sandbox.tunnels.get(port)`. Best for quick development and `.workers.dev`
+ deployments.
+
+
Mount S3-compatible buckets (R2, S3, GCS) as local filesystems for persistent
data storage across sandbox lifecycles.
diff --git a/src/content/docs/sandbox/api/tunnels.mdx b/src/content/docs/sandbox/api/tunnels.mdx
new file mode 100644
index 000000000000000..7d45333180f49ed
--- /dev/null
+++ b/src/content/docs/sandbox/api/tunnels.mdx
@@ -0,0 +1,151 @@
+---
+title: Tunnels
+description: Expose sandbox services on zero-config *.trycloudflare.com URLs using the Sandbox SDK tunnels API.
+pcx_content_type: reference
+sidebar:
+ order: 6
+products:
+ - sandbox
+---
+
+import { TypeScriptExample } from "~/components";
+
+The `sandbox.tunnels` namespace exposes a service running inside a sandbox on a `*.trycloudflare.com` URL. The SDK runs `cloudflared` inside the container and opens a persistent QUIC connection to Cloudflare's edge; no Cloudflare account, DNS record, or custom domain is required.
+
+:::note[When to use tunnels vs. `exposePort()`]
+Use `sandbox.tunnels` for **quick development** and **deployments on `.workers.dev`**, where wildcard DNS is not available. For **production**, use [`exposePort()`](/sandbox/api/ports/) with a custom domain — quick tunnels are positioned by Cloudflare as a debug aid and do not carry an uptime guarantee. Production-grade named tunnels are planned for a future release.
+:::
+
+## Requirements
+
+- **RPC transport.** Calling `sandbox.tunnels` on a route-based transport throws `"RPC transport required"`. See [Transport configuration](/sandbox/configuration/transport/).
+- **glibc image variant.** The default, `python`, `opencode`, and `desktop` images ship `cloudflared`. The `musl`/Alpine variant does not — there is no upstream `cloudflared` build for musl at this time.
+
+## Methods
+
+### `tunnels.get()`
+
+Return a tunnel record for `port`. Idempotent: repeated calls for the same port return the same record. On a cache miss, the SDK spawns a fresh `cloudflared` process inside the container and persists the record in Durable Object storage.
+
+```ts
+const tunnel = await sandbox.tunnels.get(port: number): Promise
+```
+
+**Parameters**:
+
+- `port` — Port number inside the sandbox to expose (1024-65535, excluding reserved ports). The service must already be listening on `0.0.0.0:` inside the container.
+
+**Returns**: `Promise` — the tunnel record. See [`TunnelInfo`](#tunnelinfo).
+
+
+```ts
+import { getSandbox } from "@cloudflare/sandbox";
+
+export { Sandbox } from "@cloudflare/sandbox";
+
+export default {
+ async fetch(request: Request, env: Env): Promise {
+ const sandbox = getSandbox(env.Sandbox, "my-sandbox");
+
+ await sandbox.startProcess("python -m http.server 8080");
+
+ const tunnel = await sandbox.tunnels.get(8080);
+ console.log(tunnel.url);
+ // → https://random-words-here.trycloudflare.com
+
+ // Repeated calls for the same port return the same record.
+ const same = await sandbox.tunnels.get(8080);
+ console.log(same.url === tunnel.url); // true
+
+ return Response.json({ url: tunnel.url });
+
+},
+};
+
+````
+
+
+### `tunnels.list()`
+
+Return every tunnel currently tracked for this sandbox.
+
+```ts
+const tunnels = await sandbox.tunnels.list(): Promise
+````
+
+**Returns**: `Promise` — an array of [`TunnelInfo`](#tunnelinfo) records. Empty when no tunnels are active.
+
+
+```ts
+const tunnels = await sandbox.tunnels.list();
+
+for (const tunnel of tunnels) {
+console.log(`port ${tunnel.port} → ${tunnel.url}`);
+}
+
+````
+
+
+### `tunnels.destroy()`
+
+Tear down a tunnel. Accepts either the port number or the `TunnelInfo` record returned by `get()`. Idempotent — destroying an unknown port resolves successfully.
+
+```ts
+await sandbox.tunnels.destroy(portOrInfo: number | TunnelInfo): Promise
+````
+
+**Parameters**:
+
+- `portOrInfo` — Either the port number or the `TunnelInfo` record returned by [`get()`](#tunnelsget).
+
+
+```ts
+const tunnel = await sandbox.tunnels.get(8080);
+
+// Tear down by port number...
+await sandbox.tunnels.destroy(8080);
+
+// ...or by the record.
+await sandbox.tunnels.destroy(tunnel);
+
+````
+
+
+## Types
+
+### `TunnelInfo`
+
+| Field | Type | Description |
+| ----------- | -------- | -------------------------------------------------------------------------------------------- |
+| `id` | `string` | SDK-assigned identifier for the tunnel (for example, `quick-9f2c8a1d`). |
+| `port` | `number` | Port number inside the sandbox that the tunnel proxies to. |
+| `url` | `string` | Public URL — `https://.trycloudflare.com`. |
+| `hostname` | `string` | Hostname component of `url` (`.trycloudflare.com`). |
+| `createdAt` | `string` | ISO-8601 timestamp of when the tunnel was created. |
+
+```ts
+interface TunnelInfo {
+ id: string;
+ port: number;
+ url: string;
+ hostname: string;
+ createdAt: string;
+}
+````
+
+## Limitations
+
+- **URLs do not survive container restart.** Cloudflare assigns the hostname during `cloudflared`'s startup handshake, so every restart yields a new URL. The SDK clears its tunnel cache when the container starts, so the next `tunnels.get(port)` returns a fresh record.
+- **No uptime guarantee.** Cloudflare positions `trycloudflare.com` as a debug aid, not a production target. Use [`exposePort()`](/sandbox/api/ports/) with a custom domain for production.
+- **No Server-Sent Events.** The `trycloudflare.com` edge buffers `text/event-stream` responses, so SSE does not reach the client. WebSockets work normally.
+- **No persistent hostname.** Every restart picks a new `.trycloudflare.com`. If you need a stable URL, use [`exposePort()`](/sandbox/api/ports/#exposeport) with a custom token.
+- **Brief DNS warm-up.** The first request through a brand-new URL can take a couple of seconds while DNS propagates, even after `get()` resolves.
+- **WARP / Zero Trust egress.** If your local machine runs Cloudflare WARP or another Zero Trust egress policy, outbound traffic to `api.trycloudflare.com` and the cloudflared edge can be blocked. When that happens, `tunnels.get()` hangs on the edge handshake and eventually times out. Disable WARP or add an egress exception for these destinations.
+- **No musl/Alpine support.** The musl image variant does not include `cloudflared`. Use one of the glibc-based image variants (`default`, `python`, `opencode`, `desktop`).
+
+## Related resources
+
+- [Preview URLs concept](/sandbox/concepts/preview-urls/) — Worker-fronted preview URLs and how they differ from quick tunnels.
+- [Ports API](/sandbox/api/ports/) — `exposePort()` and the Worker-fronted preview URL flow.
+- [Expose services guide](/sandbox/guides/expose-services/) — End-to-end walkthrough for exposing services in production.
+- [Transport configuration](/sandbox/configuration/transport/) — RPC vs. route-based transport.
From 8d54e68acaca1ca662c7f786fc6d518d3aadde91 Mon Sep 17 00:00:00 2001
From: aron <263346377+aron-cf@users.noreply.github.com>
Date: Mon, 18 May 2026 12:25:47 +0100
Subject: [PATCH 2/6] [Sandboxes] Add links back to the quick tunnels docs
---
src/content/docs/sandbox/api/ports.mdx | 6 ++++++
src/content/docs/sandbox/concepts/index.mdx | 2 +-
src/content/docs/sandbox/concepts/security.mdx | 10 ++++++++++
src/content/docs/sandbox/get-started.mdx | 5 +----
src/content/docs/sandbox/guides/expose-services.mdx | 5 +++++
.../docs/sandbox/guides/production-deployment.mdx | 5 ++++-
.../docs/sandbox/guides/websocket-connections.mdx | 5 +++++
7 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/src/content/docs/sandbox/api/ports.mdx b/src/content/docs/sandbox/api/ports.mdx
index 4b1b2a1424b67ac..45bc6195c3d1a39 100644
--- a/src/content/docs/sandbox/api/ports.mdx
+++ b/src/content/docs/sandbox/api/ports.mdx
@@ -14,6 +14,10 @@ import { TypeScriptExample } from "~/components";
Preview URLs require a custom domain with wildcard DNS routing in production. See [Production Deployment](/sandbox/guides/production-deployment/).
:::
+:::note[Alternative: quick tunnels]
+For quick development or `.workers.dev` deployments, consider [`sandbox.tunnels`](/sandbox/api/tunnels/), which returns `*.trycloudflare.com` URLs without DNS setup. `exposePort()` remains the recommended option for production.
+:::
+
Expose services running in your sandbox via public preview URLs. See [Preview URLs concept](/sandbox/concepts/preview-urls/) for details.
## Module functions
@@ -285,3 +289,5 @@ export default {
- [Expose Services guide](/sandbox/guides/expose-services/) - Full workflow for starting services, exposing ports, and routing requests
- [WebSocket Connections guide](/sandbox/guides/websocket-connections/) - WebSocket routing via preview URLs
- [Commands API](/sandbox/api/commands/) - Start background processes
+- [Tunnels API](/sandbox/api/tunnels/) - Zero-config `*.trycloudflare.com` URLs for quick development
+```
diff --git a/src/content/docs/sandbox/concepts/index.mdx b/src/content/docs/sandbox/concepts/index.mdx
index cb7291e6c1a03d2..586ad13822d0ac5 100644
--- a/src/content/docs/sandbox/concepts/index.mdx
+++ b/src/content/docs/sandbox/concepts/index.mdx
@@ -14,7 +14,7 @@ These pages explain how the Sandbox SDK works, why it's designed the way it is,
- [Sandbox lifecycle](/sandbox/concepts/sandboxes/) - Understanding sandbox states and behavior
- [Container runtime](/sandbox/concepts/containers/) - How code executes in isolated containers
- [Session management](/sandbox/concepts/sessions/) - When and how to use sessions
-- [Preview URLs](/sandbox/concepts/preview-urls/) - How service exposure works
+- [Preview URLs](/sandbox/concepts/preview-urls/) - How to expose sandboxed services on the public internet.
- [Security model](/sandbox/concepts/security/) - Isolation, validation, and safety mechanisms
- [Terminal connections](/sandbox/concepts/terminal/) - How browser terminal connections work
diff --git a/src/content/docs/sandbox/concepts/security.mdx b/src/content/docs/sandbox/concepts/security.mdx
index 4319689e4e05b1c..5c15d8d4295ba00 100644
--- a/src/content/docs/sandbox/concepts/security.mdx
+++ b/src/content/docs/sandbox/concepts/security.mdx
@@ -92,6 +92,16 @@ To revoke access, unexpose the port:
await sandbox.unexposePort(8080);
```
+### Quick tunnel URLs
+
+Quick tunnels (`sandbox.tunnels.get(port)`) return a `*.trycloudflare.com` URL with a random hostname assigned by Cloudflare — there is no separate access token. The hostname itself is the access control: anyone who knows the URL can reach the service. To revoke access, destroy the tunnel:
+
+```typescript
+await sandbox.tunnels.destroy(8080);
+```
+
+URLs do not survive a container restart, so a restart effectively rotates the hostname. As with preview URLs, add application-level authentication for any sensitive service. See the [Tunnels API](/sandbox/api/tunnels/) for details.
+
```python
from flask import Flask, request, abort
import os
diff --git a/src/content/docs/sandbox/get-started.mdx b/src/content/docs/sandbox/get-started.mdx
index de388a8cafd7cf8..1cf2ee8d1179b04 100644
--- a/src/content/docs/sandbox/get-started.mdx
+++ b/src/content/docs/sandbox/get-started.mdx
@@ -157,10 +157,6 @@ curl https://my-sandbox.YOUR_SUBDOMAIN.workers.dev/run
Your sandbox is now deployed and can execute code in isolated containers.
-:::note[Preview URLs require custom domain]
-If you plan to expose ports from sandboxes (using `exposePort()` for preview URLs), you will need to set up a custom domain with wildcard DNS routing. The `.workers.dev` domain does not support the subdomain patterns required for preview URLs. See [Production Deployment](/sandbox/guides/production-deployment/) when you are ready to expose services.
-:::
-
## Understanding the configuration
Your `wrangler.jsonc` connects three pieces together:
@@ -210,5 +206,6 @@ Now that you have a working sandbox, explore more capabilities:
- [Execute commands](/sandbox/guides/execute-commands/) - Run shell commands and stream output
- [Manage files](/sandbox/guides/manage-files/) - Work with files and directories
- [Expose services](/sandbox/guides/expose-services/) - Get public URLs for services running in your sandbox
+- [Quick tunnels](/sandbox/api/tunnels/) - Zero-config `*.trycloudflare.com` URLs for development and `.workers.dev` deployments
- [Production Deployment](/sandbox/guides/production-deployment/) - Set up custom domains for preview URLs
- [API reference](/sandbox/api/) - Complete API documentation
diff --git a/src/content/docs/sandbox/guides/expose-services.mdx b/src/content/docs/sandbox/guides/expose-services.mdx
index 6f2b063ab65aea0..db3032671d42d7a 100644
--- a/src/content/docs/sandbox/guides/expose-services.mdx
+++ b/src/content/docs/sandbox/guides/expose-services.mdx
@@ -14,6 +14,10 @@ import { TypeScriptExample } from "~/components";
Preview URLs require a custom domain with wildcard DNS routing in production. See [Production Deployment](/sandbox/guides/production-deployment/) for setup instructions.
:::
+:::note[Alternative: quick tunnels]
+If you only need a public URL for development or a `.workers.dev` deployment, [`sandbox.tunnels`](/sandbox/api/tunnels/) returns a `*.trycloudflare.com` URL without DNS setup. For production, follow this guide and use `exposePort()` with a custom domain.
+:::
+
This guide shows you how to expose services running in your sandbox to the internet via preview URLs.
## When to expose ports
@@ -393,3 +397,4 @@ See [Sandbox options - normalizeId](/sandbox/configuration/sandbox-options/#norm
- [Ports API reference](/sandbox/api/ports/) - Complete port exposure API
- [Background processes guide](/sandbox/guides/background-processes/) - Managing services
- [Execute commands guide](/sandbox/guides/execute-commands/) - Starting services
+- [Tunnels API reference](/sandbox/api/tunnels/) - Quick `*.trycloudflare.com` URLs as an alternative to `exposePort()`
diff --git a/src/content/docs/sandbox/guides/production-deployment.mdx b/src/content/docs/sandbox/guides/production-deployment.mdx
index a527397f09ef99b..27c08a0c143f74a 100644
--- a/src/content/docs/sandbox/guides/production-deployment.mdx
+++ b/src/content/docs/sandbox/guides/production-deployment.mdx
@@ -11,7 +11,9 @@ products:
import { WranglerConfig } from "~/components";
:::note[Only required for preview URLs]
-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.
+This guide covers `exposePort()` in production. Custom domain setup is ONLY needed if you use `exposePort()` to expose services from sandboxes. If your application does not use `exposePort()`, you can deploy to `.workers.dev` without this configuration.
+
+For development or `.workers.dev` deployments that need public URLs, [`sandbox.tunnels`](/sandbox/api/tunnels/) is a zero-config alternative — we recommend `exposePort()` for production today; named tunnels for production are planned for a future release.
:::
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`.
@@ -108,5 +110,6 @@ For detailed troubleshooting, see the [Workers routing documentation](/workers/c
- [Preview URLs](/sandbox/concepts/preview-urls/) - How preview URLs work
- [Expose Services](/sandbox/guides/expose-services/) - Patterns for exposing ports
+- [Tunnels API](/sandbox/api/tunnels/) - Zero-config `*.trycloudflare.com` URLs for development (not for production)
- [Workers Routing](/workers/configuration/routing/) - Advanced routing configuration
- [Cloudflare DNS](/dns/) - DNS management
diff --git a/src/content/docs/sandbox/guides/websocket-connections.mdx b/src/content/docs/sandbox/guides/websocket-connections.mdx
index f9ba738b14a25bb..f63858ba22b8a1a 100644
--- a/src/content/docs/sandbox/guides/websocket-connections.mdx
+++ b/src/content/docs/sandbox/guides/websocket-connections.mdx
@@ -138,6 +138,10 @@ export default {
```
+:::note[Alternative: quick tunnels]
+Quick tunnels also handle WebSocket upgrades and do not require a custom domain, so they work on `.workers.dev`. Swap `sandbox.exposePort(8080, { hostname })` for `sandbox.tunnels.get(8080)` to get a `*.trycloudflare.com` URL.
+:::
+
**Client connects to preview URL:**
```javascript
@@ -246,4 +250,5 @@ Port exposure in Dockerfile is only required for local development. In productio
- [Ports API reference](/sandbox/api/ports/) - Complete API documentation
- [Preview URLs concept](/sandbox/concepts/preview-urls/) - How preview URLs work
+- [Tunnels API](/sandbox/api/tunnels/) - Zero-config `*.trycloudflare.com` URLs for WebSocket services in development
- [Background processes guide](/sandbox/guides/background-processes/) - Managing long-running services
From 9798f0fa85c1e6dad0639c666229058b6f19967c Mon Sep 17 00:00:00 2001
From: aron <263346377+aron-cf@users.noreply.github.com>
Date: Mon, 18 May 2026 12:39:52 +0100
Subject: [PATCH 3/6] [Sandboxes] Update the Preview URLs docs
---
.../docs/sandbox/concepts/preview-urls.mdx | 47 ++++++++++++++++---
1 file changed, 40 insertions(+), 7 deletions(-)
diff --git a/src/content/docs/sandbox/concepts/preview-urls.mdx b/src/content/docs/sandbox/concepts/preview-urls.mdx
index 30bbf9f5c46d4fb..7fdf50c71ce90b4 100644
--- a/src/content/docs/sandbox/concepts/preview-urls.mdx
+++ b/src/content/docs/sandbox/concepts/preview-urls.mdx
@@ -8,6 +8,36 @@ products:
- sandbox
---
+# Quick deployment
+
+For quick preview deployments we recommend using [Cloudflare Tunnel](https://developers.cloudflare.com/tunnel/) to generate preview URLs to your web services. These work across local development, workers.dev and production usage.
+
+```ts
+await sandbox.startProcess("python -m http.server 8000");
+const tunnel = await sandbox.tunnels.get(8000);
+console.log(tunnel.url);
+// https://acute-llama-dancing-roundly.trycloudflare.app
+
+// Request will be routed directly to the webserver running on the sandbox.
+const req = await fetch(`${tunnel.url}/api/users`); // => GET http://localhost:8000/api/users
+```
+
+Cloudflare Tunnel support currently has the following limitations:
+
+ - No control over generated URL.
+ - No authentication mechanism beyond randomly generated URL.
+ - Each URL uses an additional `cloudflared` process on the sandbox.
+
+:::note[Production requires custom domain]
+We are working on production deployments, custom hostnames and authentication for Cloudflare Tunnel support. In the mean time we recommend using `exposePort()` and `proxyToSandbox()` documented below under [Production usage, stable URLs and custom domains](#).
+:::
+
+See the [tunnels API reference](/sandbox/api/tunnels/) for the full API and feature set.
+
+# Production usage, stable URLs & custom domains
+
+For production use we recommend using the `exposePort()` API and routing traffic through your worker.
+
:::note[Production requires custom domain]
Preview URLs work in local development without configuration. For production, you need a custom domain with wildcard DNS routing. See [Production Deployment](/sandbox/guides/production-deployment/).
:::
@@ -53,20 +83,22 @@ URLs with auto-generated tokens change when you unexpose and re-expose a port.
For production deployments or shared URLs, specify a custom token to maintain consistency across container restarts:
```typescript
-const stable = await sandbox.exposePort(8000, {
- hostname,
- token: 'api_v1'
+const stable = await sandbox.exposePort(8000, {
+ hostname,
+ token: "api_v1",
});
// https://8000-sandbox-id-api_v1.yourdomain.com
// Same URL every time ✓
```
**Token requirements:**
+
- 1-16 characters long
-- Lowercase letters (a-z), numbers (0-9), and underscores (_) only
+- Lowercase letters (a-z), numbers (0-9), and underscores (\_) only
- Must be unique within each sandbox
**Use cases for custom tokens:**
+
- Production APIs with stable endpoints
- Sharing demo URLs with external users
- Documentation with consistent examples
@@ -80,7 +112,7 @@ Preview URLs extract the sandbox ID from the hostname to route requests. Since h
```typescript
// Problem scenario
-const sandbox = getSandbox(env.Sandbox, 'MyProject-123');
+const sandbox = getSandbox(env.Sandbox, "MyProject-123");
// Durable Object ID: "MyProject-123"
await sandbox.exposePort(8080, { hostname });
// Preview URL: 8080-myproject-123-token123.yourdomain.com
@@ -90,8 +122,8 @@ await sandbox.exposePort(8080, { hostname });
**The solution**: Use `normalizeId: true` to lowercase IDs when creating sandboxes:
```typescript
-const sandbox = getSandbox(env.Sandbox, 'MyProject-123', {
- normalizeId: true
+const sandbox = getSandbox(env.Sandbox, "MyProject-123", {
+ normalizeId: true,
});
// Durable Object ID: "myproject-123" (lowercased)
// Preview URL: 8080-myproject-123-token123.yourdomain.com
@@ -266,4 +298,5 @@ This is **only required for local development**. In production, all container po
- [Production Deployment](/sandbox/guides/production-deployment/) - Set up custom domains for production
- [Expose Services](/sandbox/guides/expose-services/) - Practical patterns for exposing ports
- [Ports API](/sandbox/api/ports/) - Complete API reference
+- [Tunnels API](/sandbox/api/tunnels/) - Zero-config `*.trycloudflare.com` URLs as an alternative for development
- [Security Model](/sandbox/concepts/security/) - Security best practices
From 4998863b38ecfc986a2ed22a687a2788d178ebc1 Mon Sep 17 00:00:00 2001
From: Aron <263346377+aron-cf@users.noreply.github.com>
Date: Tue, 19 May 2026 16:54:45 +0100
Subject: [PATCH 4/6] Update src/content/docs/sandbox/api/tunnels.mdx
Co-authored-by: Naresh
---
src/content/docs/sandbox/api/tunnels.mdx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/content/docs/sandbox/api/tunnels.mdx b/src/content/docs/sandbox/api/tunnels.mdx
index 7d45333180f49ed..2e675707f3fefba 100644
--- a/src/content/docs/sandbox/api/tunnels.mdx
+++ b/src/content/docs/sandbox/api/tunnels.mdx
@@ -18,7 +18,7 @@ Use `sandbox.tunnels` for **quick development** and **deployments on `.workers.d
## Requirements
-- **RPC transport.** Calling `sandbox.tunnels` on a route-based transport throws `"RPC transport required"`. See [Transport configuration](/sandbox/configuration/transport/).
+- **RPC transport.** Calling `sandbox.tunnels` on HTTP/Websocket transports will throw `"RPC transport required"`. See [Transport configuration](/sandbox/configuration/transport/).
- **glibc image variant.** The default, `python`, `opencode`, and `desktop` images ship `cloudflared`. The `musl`/Alpine variant does not — there is no upstream `cloudflared` build for musl at this time.
## Methods
From c15aecb9d3894b0aec29929cca431ecd9a680fb4 Mon Sep 17 00:00:00 2001
From: Aron <263346377+aron-cf@users.noreply.github.com>
Date: Tue, 19 May 2026 16:54:58 +0100
Subject: [PATCH 5/6] Update src/content/docs/sandbox/api/tunnels.mdx
Co-authored-by: Naresh
---
src/content/docs/sandbox/api/tunnels.mdx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/content/docs/sandbox/api/tunnels.mdx b/src/content/docs/sandbox/api/tunnels.mdx
index 2e675707f3fefba..382478fb83632cf 100644
--- a/src/content/docs/sandbox/api/tunnels.mdx
+++ b/src/content/docs/sandbox/api/tunnels.mdx
@@ -25,7 +25,7 @@ Use `sandbox.tunnels` for **quick development** and **deployments on `.workers.d
### `tunnels.get()`
-Return a tunnel record for `port`. Idempotent: repeated calls for the same port return the same record. On a cache miss, the SDK spawns a fresh `cloudflared` process inside the container and persists the record in Durable Object storage.
+Return a tunnel record for `port`. The SDK spawns a fresh `cloudflared` process inside the container if not already running. The method is idempotent so repeated calls for the same port return the same record.
```ts
const tunnel = await sandbox.tunnels.get(port: number): Promise
From adca048825d992c179424845f71d94c33a81a592 Mon Sep 17 00:00:00 2001
From: Aron <263346377+aron-cf@users.noreply.github.com>
Date: Tue, 19 May 2026 16:55:07 +0100
Subject: [PATCH 6/6] Update src/content/docs/sandbox/api/tunnels.mdx
Co-authored-by: Naresh
---
src/content/docs/sandbox/api/tunnels.mdx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/content/docs/sandbox/api/tunnels.mdx b/src/content/docs/sandbox/api/tunnels.mdx
index 382478fb83632cf..662add384f9a7ef 100644
--- a/src/content/docs/sandbox/api/tunnels.mdx
+++ b/src/content/docs/sandbox/api/tunnels.mdx
@@ -33,7 +33,7 @@ const tunnel = await sandbox.tunnels.get(port: number): Promise
**Parameters**:
-- `port` — Port number inside the sandbox to expose (1024-65535, excluding reserved ports). The service must already be listening on `0.0.0.0:` inside the container.
+- `port` — Port number inside the sandbox to expose (1024-65535, excluding reserved ports). The service to tunnel to must already be listening on `0.0.0.0:` inside the container.
**Returns**: `Promise` — the tunnel record. See [`TunnelInfo`](#tunnelinfo).