Skip to content

PCBZ/openclaw-deploy-kit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

85 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OpenClaw on DigitalOcean + Azure + GCP

Security Checks License: MIT Last Commit Terraform DigitalOcean Azure GCP Cloudflare R2 OpenRouter OpenClaw Telegram Slack

One-command deployment of an OpenClaw AI agent on DigitalOcean, Azure VM, GCP VM, or GCP Cloud Run with Telegram and Slack support.

Features

  • Telegram bot with DM and group chat support
  • Slack bot support (Socket Mode)
  • Web search via Brave Search (falls back to DuckDuckGo)
  • 15+ switchable LLM models via /model <alias> (GPT-4o, Claude, Gemini, Llama, DeepSeek, and more)
  • GCP Cloud Run: persistent memory across container restarts via Cloudflare R2 (rclone sidecar syncs every 60s)
  • Secrets managed via .env + direnv — never committed

Prerequisites

  • Terraform >= 1.5
  • direnv (brew install direnv)
  • SSH key pair (for VM targets)
  • DigitalOcean account + API token (for DO path)
  • Azure subscription + service principal credentials (for Azure path)
  • GCP project (for GCP VM or GCP Cloud Run path)
  • Cloudflare account + R2 credentials (for GCP Cloud Run path only)
  • OpenRouter API key
  • Telegram bot token (from @BotFather)
  • Slack App-Level token (starts with xapp-) — optional
  • Slack Bot User OAuth token (starts with xoxb-) — optional

Setup

1. Configure secrets

cp .env.example .env

Edit .env and fill in your values:

Variable Description
OPENROUTER_API_KEY From openrouter.ai/keys
TELEGRAM_BOT_TOKEN From @BotFather
OPENCLAW_GATEWAY_TOKEN Any strong random string
BRAVE_API_KEY From api.search.brave.com — optional, falls back to DuckDuckGo
TELEGRAM_OWNER_ID Your Telegram user ID from @userinfobot — grants /model and other privileged commands
SLACK_APP_TOKEN Slack App-Level token (starts with xapp-) — leave empty to disable Slack
SLACK_BOT_TOKEN Slack Bot User OAuth token (starts with xoxb-) — leave empty to disable Slack
CF_ACCOUNT_ID Cloudflare Account ID — Cloud Run only
CF_API_TOKEN Cloudflare API Token with R2:Edit permission — Cloud Run only
R2_ACCESS_KEY_ID R2 S3-compatible Access Key ID — Cloud Run only
R2_SECRET_ACCESS_KEY R2 S3-compatible Secret Access Key — Cloud Run only

2. Choose deployment target

DigitalOcean

DigitalOcean

Droplet

cd terraform/digitalOcean

Edit terraform.tfvars to set your DigitalOcean token and optionally adjust region, droplet size, and swap:

do_token            = "dop_v1_..."
ssh_public_key_path = "~/.ssh/id_rsa.pub"
region              = "tor1"   # tor1, sfo3, nyc3, sgp1, ams3, ...
droplet_size        = "s-1vcpu-1gb"  # $6/mo — increase if OOM
swap_size           = "3G"

Azure

Azure

Virtual Machine

cd terraform/azure_vm

Create terraform.tfvars and set your Azure + VM values:

subscription_id     = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
tenant_id           = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
client_id           = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
client_secret       = "..."

resource_group_name = "your-existing-rg"
location            = "eastus"
ssh_public_key_path = "~/.ssh/id_rsa.pub"

vm_name             = "openclaw-b2pts"
vm_size             = "Standard_B2pts_v2"
os_disk_size_gb     = 30
swap_size           = 2
openclaw_memory_limit_mb = 800

GCP

GCP Compute Engine

Compute Engine

cd terraform/gcp_vm
cp terraform.tfvars.example terraform.tfvars

Edit terraform.tfvars:

project_id = "your-gcp-project-id"
region     = "us-west1"
zone       = "us-west1-b"
vm_name    = "openclaw-e2-micro"
machine_type = "e2-micro"
boot_disk_size_gb = 30

admin_username      = "openclaw"
ssh_public_key_path = "~/.ssh/id_rsa.pub"
network_name        = "default"

# Replace with your public IP/CIDR
ssh_allowed_cidrs     = ["203.0.113.10/32"]
gateway_allowed_cidrs = ["203.0.113.10/32"]

swap_size                = 3
openclaw_memory_limit_mb = 800

GCP VM deployment in this repo uses:

  • Compute Engine VM (default e2-micro, Always Free eligible)
  • 30 GB boot disk
  • Swap file + systemd memory cap for OpenClaw process
  • Firewall rules for SSH (22) and OpenClaw gateway (18789)
  • Shielded VM (Secure Boot + vTPM + Integrity Monitoring)

Cloud Run

Cloudflare R2

cd terraform/gcp_cloudrun
cp terraform.tfvars.example terraform.tfvars

Edit terraform.tfvars:

project_id = "your-gcp-project-id"
region     = "us-west1"

service_name  = "openclaw"
min_instances = 1
max_instances = 3

ghcr_remote_repository_id = "ghcr-remote"
ghcr_image_path = "openclaw/openclaw"
ghcr_image_tag  = "latest"

# Cloudflare R2 — persistent memory across container restarts
cloudflare_account_id = "your-cloudflare-account-id"
cloudflare_api_token  = "your-cloudflare-api-token"
r2_access_key_id      = "your-r2-access-key-id"
r2_secret_access_key  = "your-r2-secret-access-key"
r2_bucket_name        = "openclaw-state"

Cloudflare R2 credentials — two separate tokens are needed:

  • cloudflare_api_token: dash.cloudflare.com/profile/api-tokens → Create Token → R2:Edit (used by Terraform to create the bucket)
  • r2_access_key_id + r2_secret_access_key: Cloudflare Dashboard → R2 → Manage R2 API Tokens → Create Account API Token (used by rclone at runtime)

GCP Cloud Run deployment in this repo uses:

  • Cloud Run service (managed runtime, no VM SSH needed)
  • Artifact Registry remote repo proxy for GHCR images
  • Secret Manager for all runtime secrets
  • Cloudflare R2 for persistent state (session history, memory, soul files) — synced every 60s via rclone sidecar
  • Multi-container setup: openclaw + rclone-sync sidecar sharing an emptyDir volume

3. Load secrets via direnv

# First time only
echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc && source ~/.zshrc
direnv allow

4. Deploy

terraform init   # first time only
terraform apply

Wait ~5 minutes for bootstrap to complete. The bot will start automatically.

5. Verify

For VM targets (DigitalOcean / Azure VM / GCP VM):

terraform output ssh_command

For GCP Cloud Run target:

terraform output cloud_run_url

Then:

  • VM targets: SSH to the VM using the output command.
  • Cloud Run target: open the Cloud Run URL from output to confirm the service is reachable.
  • Send a Telegram message to confirm bot response.
  • (Optional) send a Slack message if Slack tokens are configured.

Switching Models

In Telegram or Slack, use /model <alias>. Available aliases:

Alias Model
opus Claude Opus 4
sonnet Claude Sonnet 4
haiku Claude Haiku 4
gpt4o GPT-4o
mini GPT-4o mini
gemini-pro Gemini 2.5 Pro
flash Gemini 2.5 Flash
r1 DeepSeek R1
llama Llama 3.3 70B (free)
auto OpenRouter auto-select

Security Notes

  • ssh_allowed_cidrs and gateway_allowed_cidrs default to open (0.0.0.0/0). For production, restrict to your IP in terraform.tfvars:
ssh_allowed_cidrs     = ["203.0.113.10/32"]
gateway_allowed_cidrs = ["203.0.113.10/32"]
  • CI security checks are defined in .github/workflows/security.yml (ShellCheck, .envrc policy, Checkov, Gitleaks).
  • Secrets are never written to Terraform state — all sensitive variables are injected at runtime via Secret Manager (Cloud Run) or .env + direnv.

About

An OpenClaw Deployment on Cloud Platform

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors