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
2026-01-31 16:04:03 -05:00
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-31 18:31:49 +09:00
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.
2026-02-24 01:02:06 +00:00
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-31 18:31:49 +09:00
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.
2026-01-09 18:21:28 +01:00
For the generic Docker flow, see [Docker ](/install/docker ).
2026-01-08 23:06:52 -08:00
---
## Quick path (experienced operators)
2026-01-31 18:31:49 +09:00
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
2026-01-31 18:31:49 +09:00
- 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
---
2026-03-19 11:56:49 -07: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 ).
2026-02-10 09:56:54 +00:00
## 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
2026-02-10 09:56:54 +00: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.
2026-03-19 11:38:51 -07:00
## Next steps
- Set up messaging channels: [Channels ](/channels )
- Configure the Gateway: [Gateway configuration ](/gateway/configuration )
- Keep OpenClaw up to date: [Updating ](/install/updating )