Add OpenClaw and NanoClaw scripts for Hetzner Cloud (#6)

Fills the remaining 2 gaps in the agents x clouds matrix:
- hetzner/openclaw.sh: provisions Hetzner server with OpenClaw gateway + TUI
- hetzner/nanoclaw.sh: provisions Hetzner server with NanoClaw WhatsApp agent

Matrix is now 100% complete (3 agents x 2 clouds = 6/6 implemented).

Co-authored-by: Sprite <noreply@sprite.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
L 2026-02-07 08:49:11 -08:00 committed by GitHub
parent 6002e6c7f7
commit 78e009176b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 202 additions and 2 deletions

View file

@ -75,6 +75,18 @@ Spawn agents on [Hetzner Cloud](https://www.hetzner.com/cloud/) servers. No `hcl
bash <(curl -fsSL https://openrouter.ai/lab/spawn/hetzner/claude.sh)
```
#### OpenClaw
```bash
bash <(curl -fsSL https://openrouter.ai/lab/spawn/hetzner/openclaw.sh)
```
#### NanoClaw
```bash
bash <(curl -fsSL https://openrouter.ai/lab/spawn/hetzner/nanoclaw.sh)
```
### Non-Interactive Mode
```bash

81
hetzner/nanoclaw.sh Executable file
View file

@ -0,0 +1,81 @@
#!/bin/bash
set -e
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
else
source <(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/hetzner/lib/common.sh)
fi
log_info "NanoClaw on Hetzner Cloud"
echo ""
# 1. Resolve Hetzner API token
ensure_hcloud_token
# 2. Generate + register SSH key
ensure_ssh_key
# 3. Get server name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$HETZNER_SERVER_IP"
wait_for_cloud_init "$HETZNER_SERVER_IP"
# 5. Install Node.js deps and clone nanoclaw
log_warn "Installing tsx..."
run_server "$HETZNER_SERVER_IP" "source ~/.bashrc && bun install -g tsx"
log_warn "Cloning and building nanoclaw..."
run_server "$HETZNER_SERVER_IP" "git clone https://github.com/gavrielc/nanoclaw.git ~/nanoclaw && cd ~/nanoclaw && npm install && npm run build"
log_info "NanoClaw installed"
# 6. Get OpenRouter API key
echo ""
if [[ -n "$OPENROUTER_API_KEY" ]]; then
log_info "Using OpenRouter API key from environment"
else
OPENROUTER_API_KEY=$(get_openrouter_api_key_oauth 5180)
fi
# 7. Inject environment variables into ~/.zshrc
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
export ANTHROPIC_API_KEY="${OPENROUTER_API_KEY}"
export ANTHROPIC_BASE_URL="https://openrouter.ai/api"
EOF
upload_file "$HETZNER_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$HETZNER_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
# 8. Create nanoclaw .env file
log_warn "Configuring nanoclaw..."
DOTENV_TEMP=$(mktemp)
cat > "$DOTENV_TEMP" << EOF
ANTHROPIC_API_KEY=${OPENROUTER_API_KEY}
EOF
upload_file "$HETZNER_SERVER_IP" "$DOTENV_TEMP" "/root/nanoclaw/.env"
rm "$DOTENV_TEMP"
echo ""
log_info "Hetzner server setup completed successfully!"
log_info "Server: $SERVER_NAME (ID: $HETZNER_SERVER_ID, IP: $HETZNER_SERVER_IP)"
echo ""
# 9. Start nanoclaw
log_warn "Starting nanoclaw..."
log_warn "You will need to scan a WhatsApp QR code to authenticate."
echo ""
interactive_session "$HETZNER_SERVER_IP" "cd ~/nanoclaw && source ~/.zshrc && npm run dev"

107
hetzner/openclaw.sh Executable file
View file

@ -0,0 +1,107 @@
#!/bin/bash
set -e
# Source common functions - try local file first, fall back to remote
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
if [[ -f "$SCRIPT_DIR/lib/common.sh" ]]; then
source "$SCRIPT_DIR/lib/common.sh"
else
source <(curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/hetzner/lib/common.sh)
fi
log_info "OpenClaw on Hetzner Cloud"
echo ""
# 1. Resolve Hetzner API token
ensure_hcloud_token
# 2. Generate + register SSH key
ensure_ssh_key
# 3. Get server name and create server
SERVER_NAME=$(get_server_name)
create_server "$SERVER_NAME"
# 4. Wait for SSH and cloud-init
verify_server_connectivity "$HETZNER_SERVER_IP"
wait_for_cloud_init "$HETZNER_SERVER_IP"
# 5. Install openclaw via bun
log_warn "Installing openclaw..."
run_server "$HETZNER_SERVER_IP" "source ~/.bashrc && bun install -g openclaw"
log_info "OpenClaw installed"
# 6. Get OpenRouter API key
echo ""
if [[ -n "$OPENROUTER_API_KEY" ]]; then
log_info "Using OpenRouter API key from environment"
else
OPENROUTER_API_KEY=$(get_openrouter_api_key_oauth 5180)
fi
# 7. Get model preference
echo ""
log_warn "Browse models at: https://openrouter.ai/models"
log_warn "Which model would you like to use?"
MODEL_ID=$(safe_read "Enter model ID [openrouter/auto]: ") || MODEL_ID=""
MODEL_ID="${MODEL_ID:-openrouter/auto}"
# 8. Inject environment variables into ~/.zshrc
log_warn "Setting up environment variables..."
ENV_TEMP=$(mktemp)
cat > "$ENV_TEMP" << EOF
# [spawn:env]
export OPENROUTER_API_KEY="${OPENROUTER_API_KEY}"
export ANTHROPIC_API_KEY="${OPENROUTER_API_KEY}"
export ANTHROPIC_BASE_URL="https://openrouter.ai/api"
EOF
upload_file "$HETZNER_SERVER_IP" "$ENV_TEMP" "/tmp/env_config"
run_server "$HETZNER_SERVER_IP" "cat /tmp/env_config >> ~/.zshrc && rm /tmp/env_config"
rm "$ENV_TEMP"
# 9. Configure openclaw
log_warn "Configuring openclaw..."
run_server "$HETZNER_SERVER_IP" "rm -rf ~/.openclaw && mkdir -p ~/.openclaw"
# Generate a random gateway token
GATEWAY_TOKEN=$(openssl rand -hex 16)
OPENCLAW_CONFIG_TEMP=$(mktemp)
cat > "$OPENCLAW_CONFIG_TEMP" << EOF
{
"env": {
"OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}"
},
"gateway": {
"mode": "local",
"auth": {
"token": "${GATEWAY_TOKEN}"
}
},
"agents": {
"defaults": {
"model": {
"primary": "openrouter/${MODEL_ID}"
}
}
}
}
EOF
upload_file "$HETZNER_SERVER_IP" "$OPENCLAW_CONFIG_TEMP" "/root/.openclaw/openclaw.json"
rm "$OPENCLAW_CONFIG_TEMP"
echo ""
log_info "Hetzner server setup completed successfully!"
log_info "Server: $SERVER_NAME (ID: $HETZNER_SERVER_ID, IP: $HETZNER_SERVER_IP)"
echo ""
# 10. Start openclaw gateway in background and launch TUI
log_warn "Starting openclaw..."
run_server "$HETZNER_SERVER_IP" "source ~/.zshrc && nohup openclaw gateway > /tmp/openclaw-gateway.log 2>&1 &"
sleep 2
interactive_session "$HETZNER_SERVER_IP" "source ~/.zshrc && openclaw tui"

View file

@ -99,7 +99,7 @@
"sprite/openclaw": "implemented",
"sprite/nanoclaw": "implemented",
"hetzner/claude": "implemented",
"hetzner/openclaw": "missing",
"hetzner/nanoclaw": "missing"
"hetzner/openclaw": "implemented",
"hetzner/nanoclaw": "implemented"
}
}