One-command deployment of an OpenClaw AI agent on DigitalOcean or Azure VM with Telegram and Slack support. After terraform apply, the bot is fully operational with no manual SSH steps required.
- Telegram bot with DM and group chat support
- Slack bot support (Socket Mode)
- Web search via Brave Search (falls back to DuckDuckGo)
- 8 switchable free LLM models via
/model <alias> - Secrets managed via
.env— never committed
- Terraform >= 1.5
- direnv (
brew install direnv) - SSH key pair
- DigitalOcean account + API token (for DO path)
- Azure subscription + service principal credentials (for Azure path)
- OpenRouter API key
- Telegram bot token (from @BotFather)
- Slack App-Level token (starts with
xapp-) - Slack Bot User OAuth token (starts with
xoxb-)
cp .env.example .envEdit .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-) |
SLACK_BOT_TOKEN |
Slack Bot User OAuth token (starts with xoxb-) |
cd terraform/digitalOceanEdit 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"cd terraform/azure_vmCreate 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# First time only
echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc && source ~/.zshrc
direnv allowterraform init # first time only
terraform applyWait ~5 minutes for bootstrap to complete. The bot will start automatically.
terraform output ssh_command # SSH into the server if neededSend a message to your bot on Telegram to confirm it's working.
In Telegram, use /model <alias>:
All models are free tier on OpenRouter (rate limits apply).
ssh_allowed_cidrsandgateway_allowed_cidrsdefault to open (0.0.0.0/0). For production, restrict to your IP interraform.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).