openclaw/docs/install/hetzner.md

252 lines
7.4 KiB
Markdown
Raw Permalink Normal View History

2026-01-08 23:06:52 -08:00
---
2026-01-31 21:13:13 +09:00
summary: "Run OpenClaw Gateway 24/7 on a cheap Hetzner VPS (Docker) with durable state and baked-in binaries"
2026-01-08 23:06:52 -08:00
read_when:
2026-01-30 03:15:10 +01:00
- You want OpenClaw running 24/7 on a cloud VPS (not your laptop)
2026-01-08 23:06:52 -08:00
- You want a production-grade, always-on Gateway on your own VPS
- You want full control over persistence, binaries, and restart behavior
2026-01-30 03:15:10 +01:00
- You are running OpenClaw in Docker on Hetzner or a similar provider
title: "Hetzner"
2026-01-08 23:06:52 -08:00
---
2026-01-30 03:15:10 +01:00
# OpenClaw on Hetzner (Docker, Production VPS Guide)
2026-01-08 23:06:52 -08:00
## Goal
2026-01-30 03:15:10 +01:00
Run a persistent OpenClaw Gateway on a Hetzner VPS using Docker, with durable state, baked-in binaries, and safe restart behavior.
2026-01-08 23:06:52 -08:00
2026-01-30 03:15:10 +01:00
If you want “OpenClaw 24/7 for ~$5”, this is the simplest reliable setup.
2026-01-10 01:43:28 +01:00
Hetzner pricing changes; pick the smallest Debian/Ubuntu VPS and scale up if you hit OOMs.
Security model reminder:
- Company-shared agents are fine when everyone is in the same trust boundary and the runtime is business-only.
- Keep strict separation: dedicated VPS/runtime + dedicated accounts; no personal Apple/Google/browser/password-manager profiles on that host.
- If users are adversarial to each other, split by gateway/host/OS user.
See [Security](/gateway/security) and [VPS hosting](/vps).
2026-01-10 01:43:28 +01:00
## What are we doing (simple terms)?
- Rent a small Linux server (Hetzner VPS)
- Install Docker (isolated app runtime)
2026-01-30 03:15:10 +01:00
- Start the OpenClaw Gateway in Docker
- Persist `~/.openclaw` + `~/.openclaw/workspace` on the host (survives restarts/rebuilds)
2026-01-10 01:43:28 +01:00
- Access the Control UI from your laptop via an SSH tunnel
2026-01-08 23:06:52 -08:00
The Gateway can be accessed via:
2026-01-08 23:06:52 -08:00
- SSH port forwarding from your laptop
- Direct port exposure if you manage firewalling and tokens yourself
This guide assumes Ubuntu or Debian on Hetzner.
If you are on another Linux VPS, map packages accordingly.
For the generic Docker flow, see [Docker](/install/docker).
2026-01-08 23:06:52 -08:00
---
## Quick path (experienced operators)
1. Provision Hetzner VPS
2. Install Docker
3. Clone OpenClaw repository
4. Create persistent host directories
5. Configure `.env` and `docker-compose.yml`
6. Bake required binaries into the image
7. `docker compose up -d`
8. Verify persistence and Gateway access
2026-01-08 23:06:52 -08:00
---
## What you need
- Hetzner VPS with root access
- SSH access from your laptop
- Basic comfort with SSH + copy/paste
- ~20 minutes
- Docker and Docker Compose
- Model auth credentials
- Optional provider credentials
- WhatsApp QR
- Telegram bot token
- Gmail OAuth
2026-01-08 23:06:52 -08:00
---
<Steps>
<Step title="Provision the VPS">
Create an Ubuntu or Debian VPS in Hetzner.
Connect as root:
```bash
ssh root@YOUR_VPS_IP
```
This guide assumes the VPS is stateful.
Do not treat it as disposable infrastructure.
</Step>
<Step title="Install Docker (on the VPS)">
```bash
apt-get update
apt-get install -y git curl ca-certificates
curl -fsSL https://get.docker.com | sh
```
Verify:
```bash
docker --version
docker compose version
```
</Step>
<Step title="Clone the OpenClaw repository">
```bash
git clone https://github.com/openclaw/openclaw.git
cd openclaw
```
This guide assumes you will build a custom image to guarantee binary persistence.
</Step>
<Step title="Create persistent host directories">
Docker containers are ephemeral.
All long-lived state must live on the host.
```bash
mkdir -p /root/.openclaw/workspace
# Set ownership to the container user (uid 1000):
chown -R 1000:1000 /root/.openclaw
```
</Step>
<Step title="Configure environment variables">
Create `.env` in the repository root.
```bash
OPENCLAW_IMAGE=openclaw:latest
OPENCLAW_GATEWAY_TOKEN=change-me-now
OPENCLAW_GATEWAY_BIND=lan
OPENCLAW_GATEWAY_PORT=18789
OPENCLAW_CONFIG_DIR=/root/.openclaw
OPENCLAW_WORKSPACE_DIR=/root/.openclaw/workspace
GOG_KEYRING_PASSWORD=change-me-now
XDG_CONFIG_HOME=/home/node/.openclaw
```
Generate strong secrets:
```bash
openssl rand -hex 32
```
**Do not commit this file.**
</Step>
<Step title="Docker Compose configuration">
Create or update `docker-compose.yml`.
```yaml
services:
openclaw-gateway:
image: ${OPENCLAW_IMAGE}
build: .
restart: unless-stopped
env_file:
- .env
environment:
- HOME=/home/node
- NODE_ENV=production
- TERM=xterm-256color
- OPENCLAW_GATEWAY_BIND=${OPENCLAW_GATEWAY_BIND}
- OPENCLAW_GATEWAY_PORT=${OPENCLAW_GATEWAY_PORT}
- OPENCLAW_GATEWAY_TOKEN=${OPENCLAW_GATEWAY_TOKEN}
- GOG_KEYRING_PASSWORD=${GOG_KEYRING_PASSWORD}
- XDG_CONFIG_HOME=${XDG_CONFIG_HOME}
- PATH=/home/linuxbrew/.linuxbrew/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
volumes:
- ${OPENCLAW_CONFIG_DIR}:/home/node/.openclaw
- ${OPENCLAW_WORKSPACE_DIR}:/home/node/.openclaw/workspace
ports:
# Recommended: keep the Gateway loopback-only on the VPS; access via SSH tunnel.
# To expose it publicly, remove the `127.0.0.1:` prefix and firewall accordingly.
- "127.0.0.1:${OPENCLAW_GATEWAY_PORT}:18789"
command:
[
"node",
"dist/index.js",
"gateway",
"--bind",
"${OPENCLAW_GATEWAY_BIND}",
"--port",
"${OPENCLAW_GATEWAY_PORT}",
"--allow-unconfigured",
]
```
`--allow-unconfigured` is only for bootstrap convenience, it is not a replacement for a proper gateway configuration. Still set auth (`gateway.auth.token` or password) and use safe bind settings for your deployment.
</Step>
<Step title="Shared Docker VM runtime steps">
Use the shared runtime guide for the common Docker host flow:
- [Bake required binaries into the image](/install/docker-vm-runtime#bake-required-binaries-into-the-image)
- [Build and launch](/install/docker-vm-runtime#build-and-launch)
- [What persists where](/install/docker-vm-runtime#what-persists-where)
- [Updates](/install/docker-vm-runtime#updates)
</Step>
<Step title="Hetzner-specific access">
After the shared build and launch steps, tunnel from your laptop:
```bash
ssh -N -L 18789:127.0.0.1:18789 root@YOUR_VPS_IP
```
Open:
`http://127.0.0.1:18789/`
Paste your gateway token.
</Step>
</Steps>
2026-01-08 23:06:52 -08:00
2026-03-13 19:51:35 +00:00
The shared persistence map lives in [Docker VM Runtime](/install/docker-vm-runtime#what-persists-where).
## Infrastructure as Code (Terraform)
For teams preferring infrastructure-as-code workflows, a community-maintained Terraform setup provides:
- Modular Terraform configuration with remote state management
- Automated provisioning via cloud-init
- Deployment scripts (bootstrap, deploy, backup/restore)
- Security hardening (firewall, UFW, SSH-only access)
- SSH tunnel configuration for gateway access
**Repositories:**
Feat/litellm provider (#12823) * feat: add LiteLLM provider types, env var, credentials, and auth choice Add litellm-api-key auth choice, LITELLM_API_KEY env var mapping, setLitellmApiKey() credential storage, and LITELLM_DEFAULT_MODEL_REF. * feat: add LiteLLM onboarding handler and provider config Add applyLitellmProviderConfig which properly registers models.providers.litellm with baseUrl, api type, and model definitions. This fixes the critical bug from PR #6488 where the provider entry was never created, causing model resolution to fail at runtime. * docs: add LiteLLM provider documentation Add setup guide covering onboarding, manual config, virtual keys, model routing, and usage tracking. Link from provider index. * docs: add LiteLLM to sidebar navigation in docs.json Add providers/litellm to both English and Chinese provider page lists so the docs page appears in the sidebar navigation. * test: add LiteLLM non-interactive onboarding test Wire up litellmApiKey flag inference and auth-choice handler for the non-interactive onboarding path, and add an integration test covering profile, model default, and credential storage. * fix: register --litellm-api-key CLI flag and add preferred provider mapping Wire up the missing Commander CLI option, action handler mapping, and help text for --litellm-api-key. Add litellm-api-key to the preferred provider map for consistency with other providers. * fix: remove zh-CN sidebar entry for litellm (no localized page yet) * style: format buildLitellmModelDefinition return type * fix(onboarding): harden LiteLLM provider setup (#12823) * refactor(onboarding): keep auth-choice provider dispatcher under size limit --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-11 02:46:56 -08:00
- Infrastructure: [openclaw-terraform-hetzner](https://github.com/andreesg/openclaw-terraform-hetzner)
- Docker config: [openclaw-docker-config](https://github.com/andreesg/openclaw-docker-config)
This approach complements the Docker setup above with reproducible deployments, version-controlled infrastructure, and automated disaster recovery.
> **Note:** Community-maintained. For issues or contributions, see the repository links above.
## Next steps
- Set up messaging channels: [Channels](/channels)
- Configure the Gateway: [Gateway configuration](/gateway/configuration)
- Keep OpenClaw up to date: [Updating](/install/updating)