Hetzner

Run your agents on a real, inexpensive Hetzner VPS with full root and Docker-in-Docker

Run your agents on a real, inexpensive cloud VM you fully control — no local Docker needed. Each box is its own Hetzner Cloud VPS (1:1) you drive with the same agentbox commands as a local box, reached over pure OpenSSH (no third-party agent in the box — you own root). Heads up: a Hetzner box is a real VPS that bills ~€4/mo even when stopped — pause is poweroff/poweron, not free — and its firewall locks to your current egress IP.

Switch per box with --provider hetzner, or pin it project-wide with box.provider: hetzner in agentbox.yaml. Pick Hetzner for bare-VPS control (full kernel, your own region), a Cloud Firewall locked to your egress IP, and full Docker-in-Docker. Cost is roughly €4/mo per running box. Comparing options? See local-docker, daytona, vercel, and e2b.

Set up

The easiest path is the interactive wizard — it signs you in and bakes the base snapshot in one flow:

agentbox install        # then select hetzner

Paste a Hetzner Cloud API token when prompted — a Read & Write token from the target project's Security → API Tokens page (boxes will be created in whichever project minted it). Credentials persist to ~/.agentbox/secrets.env; project .env files are never harvested. install also bakes the base snapshot (a one-time agentbox prepare --provider hetzner under the hood) with the AgentBox runtime — agentbox-ctl, the agents, tmux — so every new box boots ready in ~15-20s.

For CI or scripted setup, run the explicit equivalents:

agentbox hetzner login                 # credentials only
agentbox prepare --provider hetzner    # bake the base snapshot

NOTE

Mint the token under the specific Hetzner project you want boxes to live in, and make it Read & Write. Read-only tokens can't create servers.

Mint a Read & Write API token under Security → API Tokens in the Hetzner console.

Use it

agentbox hetzner claude

agentbox hetzner create|claude|codex|opencode is sugar for the same command with --provider hetzner.

Prepare snapshot

Hetzner can't build an image from a Dockerfile, so a one-time base snapshot must be baked before the first create. agentbox prepare --provider hetzner boots a throwaway VPS, runs the install script, snapshots the result, then cleans up.

agentbox prepare --provider hetzner

The snapshot is a shell mirror of the Docker box image (Node, Python, Docker, the VNC stack, Playwright Chromium, the agents, and the agentbox-ctl supervisor). First run takes ~10–15 minutes; after that, every create --provider hetzner boots from it in ~15–20s. Re-running is idempotent — pass --force to rebake.

When you upgrade AgentBox, create --provider hetzner notices if the new install would bake a different snapshot (the comparison is checksum-based on the baked files — CLI version strings on their own don't count) and offers to rebake inline; with -y or non-TTY it instead warns loudly and boots on the existing snapshot. agentbox hetzner login also nudges you toward agentbox prepare --provider hetzner on the first successful login.

If the bake fails installing Claude Code

The bake installs Claude Code with Anthropic's native installer, whose CDN occasionally returns a Cloudflare 403 to cloud-datacenter egress IPs (Hetzner among them). The bake retries three times and then aborts rather than shipping a Claude-less snapshot. If it keeps failing, switch to the npm installer:

agentbox prepare --provider hetzner --claude-install npm
# or persist it: agentbox config set box.claudeInstall npm

npm installs @anthropic-ai/claude-code and symlinks it into the same ~/.local/bin/claude path the native installer uses, so the box behaves identically. Bake-time only — changing it re-bakes the snapshot.

HEADS UP

The bake costs a few minutes and a couple euro-cents, but you only do it once per account.

Create a box and run an agent

Once login and prepare are done, create/claude/codex/opencode/shell behave exactly like local Docker — only --provider hetzner (or the pinned config) differs. The workspace is seeded from a host git bundle plus your uncommitted and untracked changes, the same as the other clouds (see teleport a project and sync & git).

$ agentbox create -y --provider hetzner
# VPS provisioned + firewall locked + SSH up (~90s cold, ~15-20s from snapshot)

$ agentbox shell 1 --no-tmux -- uname -a
Linux agentbox-7f3a ... x86_64 GNU/Linux

Or jump straight into an agent, which auto-creates the box:

agentbox claude --provider hetzner

See run an agent, access your box, and background & parallel.

Sizes and regions

The default VM is cx23 (2 vCPU / 4 GB / 40 GB, ~€4/mo while running) in location nbg1 (Nuremberg). On Hetzner, --size is the server type and --location is the datacenter. Change them per box, or pin them with box.sizeHetzner and box.hetznerLocation (precedence: flag > box.size<Provider> > box.size / box.hetznerLocation) — see configuration.

agentbox create -y --provider hetzner --size cx33 --location fsn1

Locations are nbg1 (Nuremberg), fsn1 (Falkenstein), hel1 (Helsinki), and ash (Ashburn, US). --location on a non-hetzner provider is ignored with a warning. The bake VPS location can be set the same way: agentbox prepare --provider hetzner --location fsn1.

After the box comes up, AgentBox reports the real provisioned resources read back from Hetzner — e.g. provisioned 4 vCPU / 16 GB RAM / 160 GB disk — rather than a static guess, and stores them on the box record.

Preflight validation

Before AgentBox creates any billable resource (firewall, SSH key, server), it validates your server-type + location choice against Hetzner's live /server_types catalog and fails fast with an actionable message — so a typo never bills you for a half-created box:

  • Unknown type (--size cx99) → lists valid non-deprecated x86 types.
  • ARM type (--size cax31) → rejected; AgentBox base snapshots are x86-only, so cax* types aren't supported.
  • Deprecated type (e.g. the old cx22) → rejected, with current alternatives.
  • Type not offered in the location (--size ccx23 --location nbg1) → lists where it is offered and reminds you of --location.
  • Disk too small for the base snapshot → asks for a larger type.

Dedicated (ccx) types and account limits

New Hetzner accounts start with a low server limit, and the dedicated-vCPU ccx* types count against it quickly. If Hetzner refuses the create with resource_limit_exceeded, AgentBox surfaces the account-limits explanation and points you at the Hetzner Console → your project → Limits to request an increase. An out-of-capacity error (resource_unavailable) suggests trying another --location.

Firewall

Each box gets its own Hetzner Cloud Firewall with a single rule: inbound TCP port 22 from your host's egress IP only. All box traffic flows over SSH, so port 22 from your IP is genuinely all that's exposed.

If you change networks (new Wi-Fi, VPN toggle), your egress IP changes and SSH times out. agentbox hetzner firewall sync <box> re-detects your IP and updates that box's rule with no reboot:

agentbox hetzner firewall sync smoke

TIP

Moved networks and agentbox shell suddenly times out? Run agentbox hetzner firewall sync <box> — that's almost always it.

To reach a box from another device (a phone over Terminus/Blink, with your laptop off), open the firewall and hand the device a key: agentbox inbound <box> open then agentbox connect <box> --add-key <device.pub>. The baked sshd is key-only (vscode-only, no passwords), so open exposes port 22 to the internet but only your keys get in. See remote access.

Web apps, checkpoints, and Docker

The box's standard capabilities work as on any provider, with a few Hetzner specifics:

  • Web apps / preview URLs. agentbox url <box> returns a URL, and the in-box portless proxy mirrors it so https://<box-name>.localhost resolves the same content from your host browser and from inside the box. agentbox screen works too. See web apps & tunnels and browser & screen.
  • Checkpoints map to Hetzner create_image snapshots (no-pause by default, matching docker commit). Set a per-provider default with agentbox checkpoint set-default --provider hetzner <ref>. See checkpoints & pausing.
  • Docker-in-Docker works unmodified. See Docker-in-Docker.
  • Services & tasks from agentbox.yaml run via the in-box supervisor. See services & tasks.
agentbox checkpoint create smoke setup

TIP

Because Hetzner checkpoints are full-disk snapshots, capturing one after your project's setup lets later boxes boot ready-to-go and skip workspace seeding.

Specs

Spec
Base imageUbuntu 24.04 snapshot
Build methodBaked snapshot — install script on a throwaway VPS then create_image (agentbox prepare --provider hetzner); no Dockerfile
Docker-in-DockerYes (full root, unmodified)
SSHYes — one persistent OpenSSH ControlMaster per box
Archx86_64 (amd64)
Live snapshotscreate_image snapshots (no-pause default); pause = poweroff/poweron and a stopped VPS still bills ~€4/mo
Preview URLSSH local port forward via ssh -O forward, mirrored to https://<box-name>.localhost (Portless)

Caveats

  • Pause still bills. Hetzner charges ~€4/mo even for a stopped VPS. Destroy the box (agentbox destroy <box> -y) to stop billing entirely — it deletes the VPS, its firewall, and the per-box SSH key.
  • No live stats. agentbox top and dashboard render for CPU/mem; the basic API doesn't expose per-server metrics.
  • No shared credential volume. Agent credentials are pushed to each box via scp at create time.
  • IPv4 only. SSH targets the VPS's IPv4 address; IPv6-only host networks aren't exercised yet.
  • agentbox prune --provider hetzner isn't wired yet. Clean up orphans from the Hetzner dashboard or the REST API ($HCLOUD_TOKEN lives in ~/.agentbox/secrets.env).

HEADS UP

Destroying is the only way to stop billing. A stopped box keeps accruing the ~€4/mo charge.

On this page