Benjamin Anderson
github logo linkedin logo rss feed

Building a Sandbox Provider in my Living Room

Get in bitches, we're crashing Leopold's AI fund again

Posted Oct 18, 2026 by Benjamin Anderson

This weekend I decided to get serious about building my own backend for sandboxed coding agents. The problem: I am currently spending hundreds and hundreds of dollars every month on Modal sandboxes. I love Modal, and they made an amazing sandbox product, so I'm not super upset about contributing to their ripping ARR and continued success. However, I also have a Mac Mini sitting on my desk mostly idle, and you know I love side projects, so I was curious if I could solve multiple problems at once (including being bored at home on a weekend).

The Foundation: Apple's Container Runtime

The first step if you're going to build a sandbox is to figure out what kind of isolation you need. In other words, just because I'm now running my coding agent on my Mac Mini doesn't mean it should be able to look at all my files and text my ex. This is a difficult and important problem, which is why companies like Modal are worth a bajillion dollars. Agents are really really good at breaking out of sandboxes, and people are still finding critical bugs in the Linux primitives that are supposed to keep isolated VMs, y'know, isolated. For the truly paranoid, and especially if you're trying to train a next-generation model with offensive cyber capabilities, probably don't build your own sandboxes at home for fun. For the rest of us though, good enough is pretty good – we just need enough to contain a midwit open-source model or a cyber-neutered frontier model, and in my case, I am the only "tenant".

I was already curious about Apple's container tool, which is basically a stripped-down version of Docker. One interesting architectural decision they made was to use one VM per container, instead of a shared VM like Docker Desktop. That means that even if a clever coding agent escapes its container, it still lands in its own VM, and can't touch other containers' files. (Illustrations below courtesy of ChatGPT's Intelligent UI.) I thought this was a sane starting point (though there are some obvious gaping holes I'll talk about later) and decided to build my Mac Mini sandboxes as Apple Containers.

Docker Desktop

Apple Containers

Docker Desktop vs. Apple Containers

The Container Control Plane

After installing container, the next thing to do is build a control plane. Some application has to constantly be running to start containers, clean them up when they're done, say "no" if someone tries to request a container but we're out of RAM, and so on. This was built as a simple FastAPI server with a handful of endpoints: creating a sandbox, executing a command in that sandbox, placing a file in that sandbox, and so on. This control plane server amounts to a crappy version of Modal or Daytona — we abstract operations on sandboxes into HTTP endpoints that can be called over a network, so a tool like my Slack coding agent can just swap out calls to Modal for calls to the Mac Mini that request a sandbox, run stuff in it, read and write files, and terminate it when done. The control plane also has configuration that limits the number of concurrent sandboxes, total RAM, total CPU, and so on, so we can't accidentally DDoS the Mini.

The other fiddly piece is images. Whenever container is going to run a coding agent, it needs to know what environment to run it in. A professional-grade sandbox service has to provide tools for defining and building these images. For example, on Modal, you can do this:

image = (
modal.Image.debian_slim(python_version="3.13")
.apt_install("git")
.uv_pip_install("torch<3")
.env({"HALT_AND_CATCH_FIRE": "0"})
.run_commands("git clone https://github.com/modal-labs/agi && echo 'ready to go!'")
)

How ergonomic! Allowing our sandbox service to hand out containers that run arbitrary, caller-defined images would be cool and interesting. However, in my limited case, I really only need 1 shared image. It has git, Claude Code, Codex, Pi, ripgrep, and a few other basic things installed. Anything else needed to set up a particular repo can be run on the fly by the agent. So we skip the hard part, and just have 1 hardcoded image that all callers get for their sandboxes. Whenever this needs to be updated with a new Claude Code or Codex version, I have to do it manually.

Hello, Internet

Once you have the control plane running on the Mac handing out containers, you have to connect it to the internet. This is scary. Remember, the sandboxes are sandboxed, but the control plane itself is just... running naked on your computer. There are lots of tools for exposing a service on your computer to the internet: ngrok was the thing to use when I was in school in 2018, Tailscale is the new popular kid on the block, and I'm sure there's a bunch more I don't know about. The smartest thing to do is to not expose it to the public internet at all. Instead, put the Mac Mini on your Tailscale, put whatever service is going to call it on your Tailscale, and they can talk with no public internet access required.

If you DO put it on the internet, be aware that anyone that has the URL can start sending requests to your living room. That means (a) that this URL should be handled with care, (b) you should definitely have some kind of bearer token or other authentication to prevent unauthorized access, and (c) you should probably prepare for the worst and not have a bunch of important/sensitive stuff on that computer.

After setting this all up, I tested it end-to-end: I can send a Slack message to my async coding agent orchestrator; the orchestrator requests an Apple sandbox instead of a Modal sandbox using the control plane's URL and token; and it sets up the environment and starts the agent in that sandbox. When the agent is done, the exec and file APIs allow the orchestrator to commit the changes, extract the patch, and put it on Github as a PR before terminating the sandbox.

Conclusion and Remaining Holes

It may sound a bit silly to go to all this trouble for a service that can run at most 2 sandboxes. But when I checked the logs, 90% of the week, I am running 0, 1, or 2 sandboxes. Offloading even 1 or 2 concurrent containers from Modal to the Mac Mini, plus scheduling the coding agent workflows a bit better to reduce the overlap, could reduce my monthly bill to a rounding error from $0.

I wouldn't say it's quite production-ready, though. The biggest gap in what I've talked about above is locking down each sandbox's network. There are ways to do this with apple/container, but they're a bit complicated. Containers share a network with the host Mac by default, which means they can access each others' networks, and can also access the host's network. So for example, if I had a Jupyter notebook open on port 8888 in one sandbox, another sandbox could potentially send requests to and access the notebook. You are supposed to set up an --internal network for each container to prevent this, but even then, there are still open GitHub issues related to programs running inside the containers being able to send requests to raw IPs. The ideal setup would be finding a way to force all container traffic through a proxy like secproxy, which only allows requests to authorized hosts. Until then, more sensitive workloads should still run on Modal, which provides stronger isolation and native support for proxies like secproxy via sandbox sidecars.

I hope you enjoyed reading about yet another side project! I didn't share the code for this one because it's nothing special, but feel free to reach out if you are trying this yourself and curious about any details I didn't include.


« Previous post: Async Coding Agents Part 3: I Vibecoded A Secrets Proxy