Skip to main content
Clawup uses Pulumi to provision cloud infrastructure as code, deploying each agent on a dedicated Ubuntu server with persistent storage, secure networking, and all the tools defined by its identity.

Deploy Flow

When you run clawup deploy, here’s what happens:
clawup.yaml         identity.yaml
   (Manifest)            (Per-agent)
  • Provider, region     • Model, coding agent
  • Instance type        • Plugins & deps
  • Agent list           • Skills
  • Owner info           • Workspace files
        │                      │
        └──────────┬───────────┘

             Pulumi Stack           Cloud Provider
             (TypeScript)    ────▶  (AWS / Hetzner)


          Per-agent resources:
          • Server (Ubuntu 24.04)
          • Security group / firewall
          • SSH keypair
          • Gateway token
          • Cloud-init script
  1. Load manifest — The CLI reads your clawup.yaml config and shows a deployment summary.
  2. Fetch identities — For each agent with an identity field, the CLI fetches the identity from the Git repo or local path, validates identity.yaml, and collects all workspace files and skills.
  3. Select Pulumi stack — Creates or selects a stack matching your config name.
  4. Sync config — Copies the manifest to the project root and sets provider-specific Pulumi config.
  5. Provision resources — Pulumi creates infrastructure for each agent: server, firewall, SSH key, and injects a cloud-init bootstrap script as user data.
  6. Cloud-init runs — On first boot, each server executes the bootstrap sequence (see below) to install tools, configure OpenClaw, and join the Tailscale mesh.
  7. Show outputs — The CLI displays each agent’s Tailscale URL, public IP, and instance ID.

Cloud-Init Bootstrap Sequence

Every agent server runs the same bootstrap script on first boot. The sequence takes a few minutes and handles everything from base packages to a running OpenClaw daemon.

1. System Setup

  • Set non-interactive mode
  • apt-get update && apt-get upgrade
  • Install unzip
  • Create ubuntu user (Hetzner only — AWS AMIs already have one)

2. Docker

  • Install via get.docker.com
  • Enable and start the Docker service
  • Add ubuntu to the docker group

3. Node.js

  • Install NVM (v0.40.1)
  • Install Node.js 22
  • Set as default version
  • Install OpenClaw CLI globally via npm

4. Dependencies (from dep registry)

System dependencies declared in the identity’s deps field are installed. For example:
  • gh — GitHub CLI from the official apt repository, authenticated with the provided token
  • brave-search — Brave Search API key configured as an environment variable
The dep registry (packages/core/src/dep-registry.ts) maps each dep name to its install script.

5. Coding Agent

The coding agent CLI declared in the identity’s codingAgent field is installed. For example:
  • claude-code — Claude Code installed via claude.ai/install.sh, added to ~/.local/bin
The coding agent registry (packages/core/src/coding-agent-registry.ts) maps each agent name to install and model configuration scripts.

6. Tailscale

  • Install via tailscale.com/install.sh
  • Join the mesh: tailscale up --authkey=<key> --ssh --hostname=<stack>-<agent-name>
  • See Networking & Security for details

7. Deno + Linear CLI (if Linear configured)

  • Install Deno to ~/.deno
  • Install Linear CLI: deno install --global jsr:@schpet/linear-cli

8. OpenClaw Onboard

  • Enable systemd linger for the ubuntu user
  • Run openclaw onboard --non-interactive --accept-risk (local mode, gateway on loopback)

9. Identity File Injection

  • Fetch workspace files from the agent’s identity (Git repo or local path)
  • Inject files into ~/.openclaw/workspace/ (SOUL.md, IDENTITY.md, HEARTBEAT.md, TOOLS.md, USER.md, AGENTS.md, BOOTSTRAP.md)
  • Inject skill files into ~/.openclaw/workspace/skills/
  • Substitute template variables ({{OWNER_NAME}}, {{TIMEZONE}}, etc.) with values from the manifest
  • Files are gzipped and base64-encoded in the cloud-init script for efficiency

10. OpenClaw Configuration & Plugins

  • Patch openclaw.json with gateway, heartbeat, sandbox, and integration settings (see below)
  • Configure the AI model and backup model from the identity’s model and backupModel fields
  • Configure cliBackends from the coding agent registry entry
  • Install plugins declared in the identity’s plugins field (e.g., openclaw-linear, slack)
  • Install the OpenClaw daemon service

11. Tailscale Serve

  • Proxy the gateway port over HTTPS: tailscale serve --bg 18789
  • Creates a public URL on your tailnet for the OpenClaw web UI

12. Post-Setup Commands

  • Run any custom commands from postSetupCommands in the manifest

What Gets Installed

Each agent server ends up with:
SoftwareVersionPurpose
DockerLatestSandbox code execution
Node.js22Runtime for OpenClaw
OpenClawLatest (npm)Agent framework — gateway, heartbeat, plugins, daemon
Coding agent CLILatestAI coding assistant (e.g., Claude Code) — from identity’s codingAgent field
TailscaleLatestMesh VPN, SSH, HTTPS proxy
System depsLatestPer-identity — e.g., GitHub CLI, Brave Search (from deps field)
Deno + Linear CLILatestLinear ticket management (if Linear plugin configured)

OpenClaw Configuration

After onboarding, the bootstrap script patches openclaw.json with your deployment settings:

Gateway

  • Binds to 127.0.0.1 (loopback only — not publicly accessible)
  • Trusted proxies: ["127.0.0.1"]
  • Token-based authentication (auto-generated per agent)
  • Control UI enabled with allowInsecureAuth: true (safe behind Tailscale)

Heartbeat

{
  "every": "1m",
  "session": "main"
}
The heartbeat fires every minute in the main session, executing each agent’s HEARTBEAT.md checklist. For most agents this is minimal (bootstrap detection only) — the primary work trigger is the Linear plugin queue system.

Sandbox

Docker-based sandbox is enabled by default (enableSandbox: true), providing isolated code execution.

Integrations

Slack (if configured):
  • Socket mode with bot token and app token
  • DMs enabled with open policy
  • Group policy: open
Linear (if configured):
  • openclaw-linear plugin installed and configured with API key, webhook secret, agent mapping, and per-role queue routing rules (from pluginDefaults in the identity)
  • Linear CLI available via Deno

Environment Variables

Credentials are auto-detected and set:
  • OAuth tokens (sk-ant-oat*) → CLAUDE_CODE_OAUTH_TOKEN
  • API keys → ANTHROPIC_API_KEY
  • Plus LINEAR_API_KEY, GITHUB_TOKEN, SLACK_BOT_TOKEN, SLACK_APP_TOKEN as configured

Identity File Injection

Each agent gets workspace files injected from its identity source (Git repo or local path):

Identity-Specific Files

FilePurpose
SOUL.mdPersonality, approach, core truths, superpowers, boundaries
IDENTITY.mdName, role, emoji, avatar
HEARTBEAT.mdPeriodic checklist — bootstrap detection and polling-based tasks
TOOLS.mdTool-specific notes and common commands

Shared Files

FilePurpose
USER.mdOwner information (name, timezone, working hours, notes)
AGENTS.mdShared operational instructions — memory management, safety rules, group chat etiquette
BOOTSTRAP.mdFirst-run integration checks with self-cleanup

Template Variables

Workspace files support template variables that get replaced at deploy time:
VariableExample
{{OWNER_NAME}}"Jane"
{{TIMEZONE}}"America/New_York"
{{WORKING_HOURS}}"9am-6pm"
{{USER_NOTES}}"No additional notes provided yet."
{{LINEAR_TEAM}}"ENG"
{{GITHUB_REPO}}"org/repo"
Custom template variables declared in the identity’s templateVars are also supported.

Provider-Specific Differences

Both AWS and Hetzner follow the same bootstrap sequence, with a few differences:
AspectAWSHetzner
Base imageUbuntu 24.04 LTS (Canonical AMI)ubuntu-24.04
User creationubuntu user exists by defaultCreated during cloud-init
NetworkingVPC + subnet + internet gatewayFlat networking
FirewallSecurity groupHetzner firewall
Metadata securityIMDSv2 enforcedN/A
Cloud-init deliveryGzipped + base64 user dataPlain user data
See Cloud Providers for region, instance type, and cost details.