Hetzner Cloud
Connect a Hetzner Cloud project and you can spin up a server, SSH into it, watch its logs, and tear it down again without leaving the terminal — or let an AI agent do the same under guard rails. Hetzner's hourly billing and fast provisioning make it ideal for disposable demo and staging boxes, and Servonaut covers the full lifecycle: list, create, power on, shutdown, power off, reboot, delete, plus the project's SSH-key registry.
Three ways to drive the same operations: a Hetzner section in the TUI sidebar (Manager screen + SSH-key registry) for day-to-day work, a scriptable servonaut hetzner CLI for CI and cron, and 11 MCP tools so AI agents can manage your Hetzner fleet — guarded, confirmed, and audit-logged like everything else in Servonaut.
Setup
1. Get a Hetzner Cloud API token
Open the Hetzner Cloud Console, pick the project you want Servonaut to manage, and create a new API token under Security → API Tokens with Read & Write scope. Copy it once — Hetzner only shows it on creation.
2. Make the token available
Servonaut resolves the token from the first matching source:
| # | Source | Notes |
|---|---|---|
| 1 | config.hetzner.api_token | Supports $ENV_VAR and file:/path/to/token prefixes. |
| 2 | $HCLOUD_TOKEN env var | Same env var the official hcloud CLI / Terraform provider use. |
| 3 | ~/.config/hcloud/token | Default location of the hcloud CLI's token file — zero-config if you already have it. |
Recommended: drop the token at ~/.config/hcloud/token so the same file works for the hcloud CLI, Servonaut, and Terraform.
3. Enable the provider
The quickest path is the in-TUI wizard: open Settings → Hetzner Setup, paste or point at your token, and pick your defaults — the wizard writes the config for you.
On headless machines, or if you manage config in version control, edit the hetzner block in ~/.servonaut/config.json directly:
{
"hetzner": {
"enabled": true,
"api_token": "",
"default_username": "root",
"default_image": "ubuntu-22.04",
"default_server_type": "cx23",
"default_location": "fsn1",
"default_hetzner_ssh_key": "my-laptop",
"default_local_ssh_key": "~/.ssh/id_ed25519",
"require_ssh_keys_on_create": true
}
}
The CLI commands work even with enabled: false, as long as the token chain resolves. The TUI and the chat panel honour the flag.
4. Validate
Using it in the TUI
With hetzner.enabled = true, a Hetzner section appears in the TUI sidebar, and your Hetzner servers join the unified instance list alongside AWS, OVHcloud, and custom servers, tagged provider: hetzner. Everything you can do to any other server works here too, using the configured default_local_ssh_key and default_username (root by default — Hetzner's stock images don't ship a non-root user):
- From the instance list: S SSH to the selected server, C run-command overlay, B remote file browser, T SCP transfer, Y copy the IP.
- Click a row (or press Enter) to open the per-server Server Actions dashboard — browse files inline, tail logs, run AI analysis, and press L for an opt-in live resource monitor (CPU / RAM / load / disk, polled over SSH only while the pane is open).
- Press F2 anywhere to open the AI chat panel and ask for Hetzner operations in plain language — "shut down demo-1", "what server types are available in Falkenstein?". The assistant calls the same guarded tools described below.
Hetzner Manager screen
The sidebar's Hetzner → ⚙ Manage entry opens a per-provider table with a state-aware lifecycle toolbar:
- Create opens the create wizard.
- Power on / Shutdown / Power off / Reboot — buttons enable based on the selected row's state.
- Delete — typed-name confirmation; permanent.
The create wizard walks you through four steps — region → server type → image → SSH keys — pulling current server types and EUR pricing live from the Hetzner catalog, and pre-selects your default SSH key. If the project has no SSH key registered, the wizard nudges you to add one before continuing — Servonaut refuses by default to create a server with no keys. New servers register into your fleet automatically and show up in the instance list within seconds, ready for SSH.
SSH key registry
Hetzner → 🔑 SSH Keys shows every Hetzner Cloud SSH key registered with the project. Add new ones from a public-key file, delete obsolete ones, copy the fingerprint. The same registry feeds the create-wizard's SSH-key picker, so what you see here is what gets injected into new servers.
Automating with the CLI
Every operation above is also available headlessly via servonaut hetzner — built for CI runners, cron jobs, and scripts. For day-to-day
operation, the Hetzner Manager screen in the TUI is the recommended interface.
Examples
| Exit code | Meaning |
|---|---|
0 | Success |
1 | Generic error (API failure, network) |
2 | Not configured (no token resolvable) |
3 | Typed-confirmation declined for destroy |
4 | Input validation error |
Pressing Ctrl+C during any command cancels it cleanly — a one-line Cancelled. and exit code 130, never a traceback — so wrapping scripts can rely on the standard SIGINT convention.
For AI agents: MCP tools (11)
Eleven Hetzner tools are available to agents the moment your Hetzner provider is configured — no extra registration step. They appear in tools/list for any MCP client (Claude Code, Cursor, Windsurf, …) connected to the Servonaut MCP server, whether it runs locally over stdio (servonaut --mcp, one-command install via servonaut --mcp-install) or reaches your machine through the hosted relay. Create and delete tools require mcp.guard_level = dangerous; power controls (power_on, power_off, shutdown, reboot) and create_ssh_key run at the standard tier so an agent can recover a stuck server without escalation. See guard levels for how the tiers work.
Hosted MCP calls count toward your plan's per-provider operations allowance — see Pricing for the current per-plan numbers. Dangerous-tier tools additionally require the dangerous-AI-tools opt-in on your servonaut.dev account; on Teams plans, a per-team approval policy can require human approval before they run.
| Tool | Guard | Description |
|---|---|---|
hetzner_list_servers | readonly | List servers in project |
hetzner_list_server_types | readonly | Catalog + EUR prices |
hetzner_list_ssh_keys | readonly | Registered SSH keys |
hetzner_create_ssh_key | standard | Register a new SSH public key |
hetzner_delete_ssh_key | dangerous | Remove an SSH key from the project |
hetzner_create_server | dangerous | Create a server (auto-registers in fleet). Confirmation required. |
hetzner_delete_server | dangerous | Permanently delete a server. Confirmation required. |
hetzner_power_on | standard | Power a stopped server back on |
hetzner_power_off | standard | Hard power-off (no graceful shutdown) |
hetzner_shutdown | standard | Graceful ACPI shutdown |
hetzner_reboot | standard | Soft reboot |
From Servonaut AI chat and the headless relay
The same tools back the built-in AI chat: press F2 in the TUI, or use servonaut ai chat --tools headlessly, and the assistant can list, power-cycle, or (with the dangerous opt-in) create and delete Hetzner servers on your behalf. When no TUI is open, a running servonaut connect listener executes these tool calls too — approval is policy-driven via relay.ai_tool_auto_approve in ~/.servonaut/config.json, which sets the maximum guard tier auto-approved (default standard, so power controls run but create/delete are denied unless you raise it and hold the dangerous-tools entitlement). Every execution is audit-logged.
Auto-registration into the fleet
Servers created through hetzner_create_server (or the wizard, or the CLI) appear in your fleet automatically — the next
list_instances call or TUI refresh shows them. Downstream tools — run_command,
get_logs, transfer_file, build_server_memory — work on the new server within seconds, with no manual "add server" flow.
Security & safety notes
- The API token is stored in
~/.servonaut/config.json, encrypted at rest if you opt in to a passphrase via the existing config-encryption flow (AES-256-GCM with PBKDF2-HMAC-SHA256, 600 000 iterations). - The token is stripped from any config-sync upload to servonaut.dev, so even if you opt in to cloud config sync, the token never leaves this machine.
- The local cache and audit log are created with owner-only file permissions and hardened against symlink and partial-write attacks.
hetzner_create_ssh_keydoes not log the public-key text — only the key name. API error messages are sanitised before they reach the audit log, so key material never appears there.hetzner_create_serverrefuses by default to create a server with no SSH keys (require_ssh_keys_on_create=true). Hetzner would otherwise spawn one with a random root password the CLI discards, leaving a billed unreachable box.
Troubleshooting
"No Hetzner Cloud API token configured"
The token chain didn't resolve. Place the token at one of:
config.hetzner.api_token(with optional$ENV_VAR/file:prefix)$HCLOUD_TOKENenvironment variable~/.config/hcloud/token(the standardhcloudCLI location)
"unsupported location for server type"
Hetzner periodically retires server types in specific locations. If your default_server_type is no longer available in default_location, the create call will fail.
Run servonaut hetzner server-types to see what's currently available, then either pass --type per call or update the default in ~/.servonaut/config.json.
SSH host-key prompt on first connect
Hetzner does not return the new server's host fingerprint in the create response. Servonaut's SSH wrapper uses
StrictHostKeyChecking=accept-new, so the first connect adds the host to your known_hosts automatically. No special handling required.
shutdown sent but server stays running
The TUI's Shutdown action (and the hetzner_shutdown MCP tool) sends an ACPI signal to the guest. On a freshly-booted Hetzner cloud-init image, acpid isn't started yet during the first ~3 minutes, so the signal is dropped and the server stays in running state. The call returns success because the API accepted the signal — guest cooperation is what didn't happen.
Two options:
- Wait until the server has fully booted (cloud-init finished,
systemctl is-system-runningreturnsrunning) before issuingshutdown. - Use the TUI's Power off action / the
hetzner_power_offMCP tool instead — that's a hard power-off via the Hetzner API which doesn't depend on the guest. Risks in-flight write loss, so prefer Shutdown on settled servers and Power off on fresh ones or when the guest is unresponsive.
Not supported
Servonaut does not manage the following Hetzner products:
- Hetzner Robot (dedicated servers) — different API surface.
- Storage Boxes, DNS, Load Balancers, Volumes, Networks, Firewalls, Floating IPs, Placement Groups — manage these in the Hetzner Console.
- Snapshot / image management.