Skip to content
 
 

Repository files navigation

OpenClaw Infrastructure

Self-hosted OpenClaw gateway on a Hetzner VPS with zero-trust Tailscale networking. No public ports exposed. ~€11.39/month.

This is a reference template. Clone it and adapt for your own deployment — the config values (timezone, model, cron prompts) are working examples you'll customize.

Features

  • Cheap: Hetzner CX43 x86 (8 vCPU, 16 GB) ~€9.49/mo + backups (~€11.39/mo total)
  • Secure: Hetzner firewall + UFW + Tailscale-only access + device pairing
  • Simple: Pulumi IaC, single command deploy, systemd user service
  • Telegram: Optional scheduled tasks (configurable cron jobs)
  • Workspace sync: Optional hourly git backup of the agent's workspace to GitHub

Prerequisites

See CLAUDE.md for detailed setup instructions.

First-Time Tailscale Setup

If you've never used Tailscale before:

  1. Create account: Go to https://tailscale.com/start

    • Sign up with GitHub (recommended for infra projects), Google, or email
    • Free tier supports up to 100 devices
  2. Install on your Mac:

    brew install --cask tailscale
    • Open Tailscale from Applications
    • Click "Allow" for System Extension and VPN Configuration prompts
    • Click menu bar icon → Log in → Authorize in browser
  3. Generate auth key for server:

Telegram Bot Setup

To enable optional Telegram notifications:

  1. Create a bot: Open Telegram, search for @BotFather, send /newbot

    • Choose a display name (e.g., "OpenClaw Assistant")
    • Choose a username (must end in "bot", e.g., openclaw_assistant_bot)
    • Copy the bot token (format: 123456789:ABCdefGHIjklMNOpqrsTUVwxyz)
  2. Get your user ID (either method):

    • Run ./scripts/get-telegram-id.sh — briefly pauses the gateway, you send a message, it shows your IDs
    • Or search for @userinfobot on Telegram, send /start, copy your numeric user ID
  3. Configure: See Quick Start below for the Pulumi commands.

Quick Start

npm install
cd pulumi
pulumi login             # Authenticate with Pulumi Cloud
pulumi stack init prod

# Required
pulumi config set hcloud:token --secret       # Hetzner API token
pulumi config set tailscaleAuthKey --secret    # Tailscale auth key
pulumi config set claudeSetupToken --secret    # From `claude setup-token`

# Optional: Telegram notifications (daily digests, weekly planning)
pulumi config set telegramBotToken --secret    # From @BotFather
pulumi config set telegramUserId "YOUR_ID"     # ./scripts/get-telegram-id.sh or @userinfobot

# Optional: hourly workspace backup to a private GitHub repo
pulumi config set workspaceRepoUrl "git@github.com:YOU/openclaw-workspace.git"

# Deploy
pulumi up

# Verify (wait ~5 min for cloud-init)
cd ..
./scripts/verify.sh

After verifying, clean up the cloud-init log (contains secrets): ssh ubuntu@openclaw-vps.<tailnet>.ts.net "sudo shred -u /var/log/cloud-init-openclaw.log"

State and secrets are managed by Pulumi Cloud — no local passphrase needed.

Access

Wait ~5 minutes after deployment for cloud-init + Ansible to finish, then open:

https://openclaw-vps.<tailnet>.ts.net/chat

First-Time Device Pairing

OpenClaw requires device pairing for all connections — including the server's own CLI. On a fresh install:

  1. Use the tokenized URL to access the web UI without pairing:

    cd pulumi && pulumi stack output tailscaleUrlWithToken --show-secrets

    Open that URL in your browser. This bypasses pairing for initial setup.

  2. Approve devices that need pairing. The server's CLI (used by Ansible) may show as pending:

    ssh ubuntu@openclaw-vps.<tailnet>.ts.net 'openclaw devices list'
    ssh ubuntu@openclaw-vps.<tailnet>.ts.net 'openclaw devices approve <request-id>'
  3. If Ansible failed during first deploy (cron setup skipped due to pairing), re-run after approving:

    ./scripts/provision.sh --tags telegram

No public SSH port is exposed. SSH works over Tailscale only.

See CLAUDE.md for details and docs/TROUBLESHOOTING.md for common issues.

Architecture

Your Machine ──(Tailscale)──> Hetzner VPS ──> OpenClaw Gateway
                               Hetzner FW: no inbound
                               UFW: tailscale0 only
                               Gateway: localhost:18789 (systemd --user)
                               Tailscale Serve: HTTPS proxy

Documentation

License

MIT

About

Secure self-hosted OpenClaw deployment on Hetzner Cloud with Tailscale

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages