Skip to content

Deploying Paddock

You can run Paddock on your laptop — npx @edspencer/paddock --here is one command and the fastest way to try it (see Getting started) — but that’s not how it’s meant to live. Paddock’s whole point is persistent, resumable agents you can reach from anywhere — and a laptop that sleeps, closes, and moves around defeats that.

It does not have to be fancy. Anything that stays on and sips power works:

  • A mini PC (Intel N100-class), an Intel NUC, or an old thin client.
  • A Raspberry Pi 4/5 (Paddock’s image is multi-arch — arm64 and amd64).
  • A NAS that runs Docker (Synology, etc.).
  • An LXC container or VM on a home server (Proxmox, etc.) — this is what the author uses; see A home-lab setup.
  • A small cloud VPS, if you’d rather not host at home.

The common thread: on 24/7, low idle power, and something you (and only you) can reach on the network.

Paddock ships as a Docker image, which is the simplest way to deploy on any of the hosts above:

Terminal window
docker run -d --name paddock -p 127.0.0.1:4000:4000 \
-e CLAUDE_CODE_OAUTH_TOKEN=… `# or ANTHROPIC_API_KEY` \
-e PADDOCK_DATA_DIR=/data \
-e PADDOCK_DANGEROUSLY_ALLOW_OPEN=1 `# every container run needs this` \
-v paddock-data:/data \
--restart unless-stopped \
ghcr.io/edspencer/paddock:latest

PADDOCK_DANGEROUSLY_ALLOW_OPEN=1 is not optional here: in a container the app binds 0.0.0.0, and the fail-closed bind guard refuses to boot on a non-loopback bind under the default PADDOCK_AUTH_MODE=none. It is safe in this command only because the publish is 127.0.0.1-bound — the container namespace plus that publish is the real boundary. Publish on a routable address instead and you should drop this flag and set a real auth mode; see Securing Paddock.

--restart unless-stopped matters here — it’s what makes Paddock come back after a reboot or power blip, which is the whole point of an always-on host. A docker-compose file (see Getting started) is the tidy way to keep the config in version control.

Two image tags are published from the same source: :latest (base — the app plus git/openssh-client/gh/claude) and :devbox (base plus the coding-agent toolbox — pm, ffmpeg, a headless browser, the Docker CLI, kubectl, and a scripting kit — for projects that build and run apps). The Dev Box flavor is the full, current breakdown of what each image carries.

Everything Paddock persists lives under PADDOCK_DATA_DIR — projects, chat transcripts, and its sidecar state. Put it on a named volume or a real disk you back up. The data directory is git-friendly (projects are directories); a periodic snapshot or offsite copy is enough to recover.

Paddock is one process per data root + port. To run several (say, one for work and one for home), start one container each with its own PADDOCK_DATA_DIR and PORT, and front them with a reverse proxy that maps a hostname to each. Nothing is shared between instances except the host.

New releases are published to ghcr.io/edspencer/paddock. Re-pull and recreate the container to update, or automate it — a tool like Watchtower, or a small “watch for a new release and redeploy” job, keeps you on the latest without manual work. (The author’s setup auto-deploys new tagged releases; see A home-lab setup.)

Bind Paddock to the host and reach it through a reverse proxy that terminates TLS (Caddy, nginx, Traefik…), so you get https://paddock.example.com instead of a raw port. Two ways to reach it from outside your home:

  • Keep it private (recommended for most people). Don’t expose it to the internet at all — reach it over a VPN or an overlay network (WireGuard, Tailscale, etc.). Simple and very safe.
  • Expose it through the proxy — only if the proxy authenticates every request (see below).