caddy playground FAQ

Notes and credits for the playground and rules builder.

What runs inside the sandbox

Every run spins up a fresh, isolated Linux network namespace with its own loopback interface. Nothing you run can reach the host network, other visitors, or the public internet. Inside the namespace you get:

  • Caddy on port 80, configured from the editor's Caddyfile.
  • go-httpbin on port 7777, an HTTP echo service. Add reverse_proxy 127.0.0.1:7777 to your Caddyfile to test upstream/proxy handling.
  • A wildcard DNS resolver: every hostname resolves to 127.0.0.1, so curl http://anything.at.all/ still lands on your sandboxed Caddy.

Try it: put this in the Caddyfile editor and run the command below it.

:80 reverse_proxy 127.0.0.1:7777
curl -i http://made-up-hostname.example/get

The request hits go-httpbin through your Caddy proxy, and the response shows the headers Caddy added on the way through.

Which commands and flags are allowed

Only curl and http (HTTPie) run in the sandbox, with a reviewed subset of their flags. Anything that would read local files or change how the client is configured is rejected before the run starts:

  • File-backed inputs: -d @file, -H @file, HTTPie's field=@file, and file:// URLs.
  • Client-config flags such as --config.
  • Any executable other than curl or http.

When a run is rejected this way, the error names the blocked token. Inline the value directly in the command instead of referencing a file, then run again.

Rate limits and concurrency

Two distinct limits can answer 429:

  • Per-client rate limit (rate_limited): 20 runs per minute per client IP. The response carries a Retry-After header; wait for the window to reset and run again.
  • Shared concurrency cap (too_many_requests): 5 sandboxes run at once across all visitors. This clears as soon as another visitor's run finishes, so retry after a few seconds.

The 10 second command timeout

Each command is stopped after 10 seconds (command_timed_out). Whatever the command printed before it was killed is shown with the error.

To stay under the limit, bound the request yourself with curl --max-time 5 or http --timeout 5, and prefer bounded go-httpbin endpoints (for example /delay/2) over long-running ones.

The 1 MiB output limit

At most 1 MiB of combined stdout and stderr is captured per run (output_too_large). Past that point the output is cut off and marked as truncated.

Ask for less output: drop -v, request fewer bytes from go-httpbin (for example /bytes/1024 instead of a large stream), or print only the headers with curl -I or http --headers.

Share URLs and saved state

Both editors keep their state in the URL fragment (everything after #), so the full playground is exactly what the link carries — nothing is stored server-side. The same state is mirrored to browser local storage, so navigating away and back does not lose your work.

Opening a share link replaces your saved local state (a backup copy of the previous state is kept under a separate key). A truncated or foreign fragment is ignored and the saved local state loads instead.

Credits

The main playground is based on Wizard Zines' nginx playground. The original code and design were the basis for this playground.