shiichan

Sandbox services now get public preview URLs with tunnels!

Hey everyone, it's me, Shii-chan! Today we're talking about sharing a service running inside a container on a public URL in just a couple of lines. Super handy when you want to show a work-in-progress preview to someone!

Cloudflare Changelog developers.cloudflare.com

What was announced?

Cloudflare's Changelog announced that Sandboxes now include a new sandbox.tunnels namespace. You can take a service running inside a Sandbox container and expose it on a public preview URL.

Under the hood it runs cloudflared inside the sandbox, so you don't need to configure exposePort() or bring a custom domain. It lands as part of the Agents updates.

The story so far

Until now, exposing a service inside a container to the outside world meant setting up exposePort() or bringing your own custom domain — a bit of a chore.

What changes

By default, calling sandbox.tunnels.get(port) creates a quick tunnel on a zero-config *.trycloudflare.com URL. No Cloudflare account, DNS record, or custom domain required. It's perfect for quick development and .workers.dev deployments.

import { getSandbox } from "@cloudflare/sandbox";

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

Dive Deep

When you want more control, you can create a named tunnel with sandbox.tunnels.get(port, { name }). Passing a name binds a hostname ({name}.{your-zone}) to a Cloudflare Tunnel plus a CNAME record on your zone, giving you a URL like https://my-app-preview.example.com.

const tunnel = await sandbox.tunnels.get(8080, { name: "my-app-preview" });
console.log(tunnel.url); // → https://my-app-preview.example.com

Quick tunnels generate a new random URL each time, but a named tunnel produces a persistent URL that survives container restarts. That makes named tunnels a good fit for production, where you want control over the tunnel and its origin.

And when you call sandbox.destroy(), it tears down the Cloudflare Tunnel and the DNS record alongside the container, so you don't leave dangling tunnels or records behind. It even handles the cleanup for you!

You can update with npm i @cloudflare/sandbox@latest. For full API details, check the Sandbox tunnels reference.

Wrap-up

  • sandbox.tunnels.get(port) gives you a zero-config quick tunnel on *.trycloudflare.com
  • Pass { name } for a persistent named tunnel whose URL survives restarts
  • sandbox.destroy() cleans up the tunnel and DNS record for you
  • Update with npm i @cloudflare/sandbox@latest

This one's for developers who want to quickly share whatever they're running inside a Sandbox!