and experiment to see if I can create a safe and reproducible way to play with openclaw: uses Digital Ociean and Ansible.
Find a file
2026-06-01 18:39:18 +00:00
docs secr 2026-05-06 17:56:18 -07:00
inventory multi 2026-04-14 19:08:02 -07:00
playbooks success for deepseek 2026-04-14 10:33:09 -07:00
roles bump openclaw image for droplet target too 2026-06-01 15:04:16 +00:00
.gitignore phase-1 2026-04-07 20:33:37 -07:00
ansible.cfg phase-1 2026-04-07 20:33:37 -07:00
README.md readme 2026-04-15 05:26:42 -07:00
requirements.yml k8s 2026-04-13 18:40:39 -07:00

dooc

Ansible automation to deploy an OpenClaw AI agent with its own Telegram bot, email inbox, and git account — each a real, independent identity the agent owns.

What it does

  • Deploys OpenClaw to a DigitalOcean Droplet or an existing Kubernetes cluster
  • Gives the agent its own Telegram bot identity
  • Gives the agent its own email inbox via AgentMail.to
  • Gives the agent its own Forgejo user account on any self-hosted Forgejo instance — unique username, scoped API token, no shared admin creds. The agent opens issues, creates repos, and submits PRs under its own name, with its own audit trail (optional)
  • Picks an LLM mode per agent: OpenRouter (budget-capped), DeepSeek direct (cheap + fast), user-hosted Ollama, or self-hosted vLLM on a DO GPU Droplet
  • Supports multiple agents side-by-side in one k8s namespace (distinct Telegram/email/Forgejo identities, distinct workspace PVCs)
  • Tears everything down cleanly with a single command

Prerequisites

  • Python 3.10+
  • Ansible 2.15+pip install ansible
  • community.digitalocean collection — installed automatically via requirements.yml
  • A DigitalOcean account with an API token (read+write)
  • An SSH key uploaded to your DO account
  • A Telegram bot created via @BotFather
  • An AgentMail.to account with an API key
  • An OpenRouter account with an API keyset a budget limit on the key at Settings > Keys (daily, weekly, or monthly cap)

Quick start

1. Install dependencies

pip install ansible
ansible-galaxy collection install -r requirements.yml

2. Prepare external accounts

Before deploying, set up these services (5-10 minutes):

  1. DigitalOcean — create an API token with read+write scope, and upload an SSH key
  2. Telegram — message @BotFather, send /newbot, save the token. Then message @userinfobot to get your numeric user ID
  3. AgentMail — sign up at agentmail.to, create an inbox, and get an API key
  4. OpenRouter — sign up at openrouter.ai, create an API key, and set a budget limit on it at Settings > Keys

3. Configure

cp inventory/hosts.ini.example inventory/hosts.ini

Edit inventory/hosts.ini and fill in:

Variable Where to get it
do_api_token DigitalOcean API settings
do_ssh_key_name Name of your SSH key in DO (e.g., mykey)
telegram_bot_token @BotFather after creating your bot
telegram_user_id @userinfobot — must be numeric (e.g., 123456789)
agentmail_inbox_email Your pre-created inbox address (e.g., mybot@agentmail.to)
agentmail_api_key AgentMail dashboard
openrouter_api_key OpenRouter dashboard — ensure budget limit is set

4. Deploy

ansible-playbook playbooks/deploy.yml

This validates your credentials, provisions a DO Droplet, and starts OpenClaw. Your Telegram bot will be online in about 2 minutes.

5. Tear down

ansible-playbook playbooks/destroy.yml

Destroys the Droplet and cleans up. Your AgentMail inbox and Telegram bot are preserved for reuse.

Security

This is a public repo. Never commit secrets.

  • Your inventory/hosts.ini is gitignored — it holds all credentials
  • The committed hosts.ini.example contains only placeholder values
  • Consider using ansible-vault to encrypt your inventory at rest

LLM provider and budget

By default, dooc uses OpenRouter in API mode with anthropic/claude-sonnet-4. You can change the model in group_vars/all.yml — see that file for pricing and budget guidance.

You must set a budget limit on your OpenRouter API key. This is a hard cap — requests are rejected when the limit is hit, so there are no surprise charges. Configure it at OpenRouter Settings > Keys.

Cheaper alternatives with tool-calling support:

Model Input / Output (per 1M tokens) Notes
anthropic/claude-sonnet-4 $3 / $15 Default — reliable tool-calling
google/gemini-2.5-flash-lite $0.25 / $1.50 Good budget option
deepseek/deepseek-v3.2 $0.28 / $0.42 Cheapest for code tasks
openai/gpt-4o-mini $0.15 / $0.60 Cheapest cloud, weaker on complex chains

DeepSeek direct mode

For significantly cheaper inference than OpenRouter while keeping an official, paid upstream, set llm_mode=deepseek. Uses DeepSeek's OpenAI-compatible API directly.

llm_mode=deepseek
deepseek_api_key=YOUR_DEEPSEEK_API_KEY
deepseek_model=deepseek-chat

DeepSeek V3.2 via direct API runs ~$0.28/$0.42 per 1M tokens (cache-miss input / output) with automatic prompt caching dropping cache-hit input to ~$0.07 per 1M. Get a key at platform.deepseek.com/api_keys and watch usage at platform.deepseek.com/usage.

Works with both DO Droplet and Kubernetes deploy targets.

Self-hosted GPU mode

For zero per-token cost, set llm_mode=gpu in your inventory. This provisions a DO GPU Droplet running vLLM with tool-calling enabled. OpenClaw reaches vLLM over DO's private VPC network.

# Deploy with GPU mode
ansible-playbook playbooks/deploy.yml -e llm_mode=gpu

GPU Droplets start at ~$3.19/hr (1x H100). The default model is Qwen/Qwen3-Coder-480B-A35B (MoE, fits single H100). See group_vars/all.yml for alternatives.

Kubernetes deployment (homelab)

Deploy to an existing Kubernetes cluster instead of DigitalOcean. Works with any conformant k8s distribution (k3s, k8s, etc.).

# Deploy to k8s with Ollama
ansible-playbook playbooks/deploy-k8s.yml

# Tear down
ansible-playbook playbooks/destroy-k8s.yml

Set llm_mode=ollama and ollama_base_url in your inventory to point at your local Ollama instance. The same custom Docker image is used — no separate build needed.

Requires kubectl configured and the kubernetes.core Ansible collection (ansible-galaxy collection install -r requirements.yml).

Running multiple agents in one namespace

Every k8s resource is prefixed with agent_name (default dooc), so multiple agents coexist in one namespace without collision. Each agent should have its own inventory file with unique agent_name, telegram_bot_token, agentmail_inbox_email, and (if used) forgejo_agent_username:

agent_name=dooc2

Standard k8s labels make it easy to slice:

# All dooc agents
kubectl get all -n dooc -l app.kubernetes.io/part-of=dooc

# One specific agent
kubectl get all -n dooc -l app.kubernetes.io/instance=dooc2

Ollama mode

For self-hosted inference on your own hardware with zero cost:

llm_mode=ollama
ollama_base_url=http://192.168.50.100:11434
ollama_model=qwen3-coder-next

Works with both DO and k8s deployment targets. Uses the native Ollama API (not /v1) for reliable tool calling.

Forgejo git identity for the agent (optional)

If you run a self-hosted Forgejo instance, dooc gives the agent its own full Forgejo user account — not a shared service token, not a bot role bolted onto your personal account. A real user with a real username, a scoped API token, and its own activity feed.

Why it matters:

  • Audit trail. Every commit, issue comment, PR, and repo creation shows the agent as author. You can see exactly what the agent did and when, separately from your own work.
  • Least privilege. The agent's token is scoped to repo and issue read/write only — no admin, no user management, no ability to escalate.
  • Revocable without fallout. Destroy the agent user and its token disappears with it. Your admin credentials stay yours.
  • Works on any Forgejo. The forgejo_agent role uses only the standard Forgejo admin API — no Forgejo version pinning, no custom patches.

Inside the container, the agent uses the fj CLI (Forgejo's gh equivalent, pre-installed and auto-authenticated) to create repos, open issues, comment, and submit PRs under its own name.

To enable, uncomment and fill in the Forgejo section in your inventory/hosts.ini:

forgejo_agent_enabled=true
forgejo_url=https://git.example.com
forgejo_admin_token=YOUR_ADMIN_TOKEN
forgejo_agent_username=dooc1
forgejo_agent_email=dooc1@agentmail.to

The agent user is created on deploy and purged on teardown (cascades to its repos, tokens, and issues). Multiple agents get distinct Forgejo users — use a unique forgejo_agent_username per inventory file.

Customizing your agent

OpenClaw uses a SOUL.md file to define the agent's personality. A default "technical cofounder" personality ships with dooc. To customize:

  • Set soul_md_content in your inventory/hosts.ini to override the default entirely
  • Or edit roles/openclaw/defaults/main.yml to change the soul_md_default

Project structure

dooc/
├── ansible.cfg                 # Ansible configuration
├── requirements.yml            # Ansible collection dependencies
├── inventory/
│   ├── hosts.ini.example       # Credential template (copy to hosts.ini)
│   └── group_vars/
│       └── all.yml             # Default settings (region, size, mode, model, SOUL.md)
├── roles/
│   ├── droplet/                # Provision/destroy DO compute droplet
│   ├── gpu_droplet/            # Provision/destroy DO GPU droplet (GPU mode)
│   ├── agentmail/              # Create/destroy AgentMail email inbox
│   ├── llm_provider/           # Validate LLM provider config (API or GPU mode)
│   ├── vllm/                   # Deploy vLLM inference server on GPU droplet
│   ├── forgejo_agent/          # Create/destroy Forgejo user account for the agent (optional)
│   ├── openclaw/               # Install Docker, deploy OpenClaw container (DO target)
│   └── k8s_openclaw/           # Deploy OpenClaw as k8s Deployment (k8s target)
├── playbooks/
│   ├── deploy.yml              # DO deployment
│   ├── destroy.yml             # DO teardown
│   ├── deploy-k8s.yml          # Kubernetes deployment
│   └── destroy-k8s.yml         # Kubernetes teardown
└── docs/
    ├── ARCHITECTURE.md          # System design
    └── ROADMAP.md               # Current state and next steps