Openclaw Mastery

Category: AI Agents | Read: 15 min | v1.0.0

OpenClaw Mastery

1. Architecture & Deployment

OpenClaw Component Architecture

┌──────────────────────────────────────────────────────────────┐
│                      OpenClaw Platform                        │
│                                                              │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐  │
│  │  OpenClaw    │  │   Docker    │  │  Browser Stack      │  │
│  │  Gateway     │  │  Compose    │  │  ┌───────────────┐  │  │
│  │  (Port 18789)│  │  Orchestration│ │  │  CamoFox      │  │  │
│  │             │  │             │  │  │  (Port 9377)   │  │  │
│  │  - Chat API │  │  - Redis    │  │  ├───────────────┤  │  │
│  │  - Skill mgmt│ │  - Nginx    │  │  │  Patchright    │  │  │
│  │  - LLM proxy│  │  - SSL      │  │  │  (Port 9378)   │  │  │
│  │  - Auth     │  │  - Watchdog │  │  ├───────────────┤  │  │
│  │             │  │             │  │  │  Scrapling     │  │  │
│  └─────────────┘  └─────────────┘  │  │  (Spider+TLS)  │  │  │
│                                     │  └───────────────┘  │  │
│  ┌─────────────────────────────┐    └─────────────────────┘  │
│  │      LLM Providers          │                             │
│  │  chutes → GLM-5-Turbo       │                             │
│  │  openrouter → 200+ models   │                             │
│  │  venice → uncensored        │                             │
│  │  ollama → local models      │                             │
│  └─────────────────────────────┘                             │
│                                                              │
│  ┌─────────────────────────────┐                             │
│  │    WhatsApp Bridge (bridge.js)│                            │
│  │    - baileys library         │                            │
│  │    - QR auth                 │                            │
│  │    - Message routing         │                            │
│  └─────────────────────────────┘                             │
└──────────────────────────────────────────────────────────────┘

Docker Compose Deployment

# docker-compose.yml for OpenClaw
version: '3.8'

services:
openclaw:
image: openclaw/openclaw:latest
container_name: openclaw
restart: unless-stopped
ports:
- "18789:18789"
volumes:
- ./openclaw.json:/app/openclaw.json
- ./data:/app/data
- ./skills:/app/skills
environment:
- NODE_ENV=production
- LOG_LEVEL=info
depends_on:
- redis

redis:
image: redis:7-alpine
container_name: openclaw-redis
restart: unless-stopped
volumes:
- redis-data:/data
command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru

camofox:
image: camoforest/camofox:latest
container_name: camofox
restart: unless-stopped
ports:
- "9377:9377"
environment:
- PROXY_ROTATION=true
- STEALTH_MODE=high

nginx:
image: nginx:alpine
container_name: openclaw-nginx
restart: unless-stopped
ports:
- "443:443"
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/ssl:/etc/nginx/ssl
- certbot-data:/etc/letsencrypt

volumes:
redis-data:
certbot-data:

openclaw.json Configuration

{
  "port": 18789,
  "defaultModel": "chutes/zai-org/GLM-5-Turbo",
  "auth": {
    "password": "munaf",
    "maxLoginAttempts": 5,
    "sessionTimeout": "24h"
  },
  "models": {
    "chutes/zai-org/GLM-5-Turbo": {
      "provider": "chutes",
      "apiKey": "${CHUTES_API_KEY}",
      "maxTokens": 4096,
      "temperature": 0.7
    },
    "openrouter/google/gemini-2.0-flash-001": {
      "provider": "openrouter",
      "apiKey": "${OPENROUTER_API_KEY}",
      "maxTokens": 4096
    },
    "venice/llama-3.1-70b": {
      "provider": "venice",
      "apiKey": "${VENICE_API_KEY}",
      "maxTokens": 4096
    }
  },
  "skills": {
    "autoUpdate": true,
    "directory": "./skills",
    "maxConcurrent": 5
  },
  "browser": {
    "default": "camofox",
    "camofoxPort": 9377,
    "patchrightPort": 9378,
    "scraplingMode": "spider"
  },
  "whatsapp": {
    "enabled": true,
    "bridgePort": 9375,
    "sessionPath": "./data/whatsapp-session"
  },
  "env": {
    "CHUTES_API_KEY": "chute_xxxxx",
    "OPENROUTER_API_KEY": "sk-or-v1-xxxxx",
    "VENICE_API_KEY": "venice_xxxxx",
    "ARLIAI_API_KEY": "arlia_xxxxx",
    "BYTEPLUS_API_KEY": "bp_xxxxx",
    "FEATHERLESS_API_KEY": "fl_xxxxx",
    "STEPFUN_API_KEY": "sf_xxxxx",
    "ZENMUX_API_KEY": "zm_xxxxx",
    "ORBIT_API_KEY": "orb_xxxxx",
    "INFERMATIC_API_KEY": "inf_xxxxx",
    "OLLAMA_API_KEY": "ollama_xxxxx"
  }
}

Nginx SSL + Reverse Proxy

# /etc/nginx/sites-available/openclaw
server {
    listen 443 ssl http2;
    server_name openclaw.munaf.oc.s4s.host;

ssl_certificate /etc/letsencrypt/live/openclaw.munaf.oc.s4s.host/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/openclaw.munaf.oc.s4s.host/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;

# WebSocket support for real-time features
location / {
proxy_pass http://127.0.0.1:18789;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400;
}

# Rate limiting
limit_req_zone $binary_remote_addr zone=openclaw:10m rate=30r/m;
limit_req zone=openclaw burst=20 nodelay;
}

Systemd Service for OpenClaw

# /etc/systemd/system/openclaw.service
[Unit]
Description=OpenClaw AI Agent Platform
After=docker.service
Requires=docker.service

[Service]
Type=simple
WorkingDirectory=/opt/openclaw
ExecStartPre=/usr/bin/docker compose pull
ExecStart=/usr/bin/docker compose up
ExecStop=/usr/bin/docker compose down
Restart=always
RestartSec=10
KillMode=control-group

[Install]
WantedBy=multi-user.target

# Enable and start
sudo systemctl enable openclaw
sudo systemctl start openclaw
sudo systemctl status openclaw

View logs

sudo journalctl -u openclaw -f

2. ClawHub Skill Ecosystem

Skill Installation & Management

# List available skills in ClawHub
openclaw skills search

Install a skill

openclaw skills install

Install multiple skills

openclaw skills install skill1 skill2 skill3

List installed skills

openclaw skills list

Update all skills

openclaw skills update

Remove a skill

openclaw skills remove

Skill Structure

skills/
├── my-skill/
│   ├── SKILL.md          # Main skill file with frontmatter
│   ├── references/        # Reference documents
│   │   └── api-docs.md
│   ├── templates/         # Template files
│   │   └── config.yaml
│   └── scripts/          # Executable scripts
│       └── setup.sh

Custom Skill Creation

# SKILL.md frontmatter for custom skill

name: my-custom-skill description: >- Brief description of what the skill does and when to use it. Second sentence adds trigger context. version: 1.0.0 author: Your Name metadata: hermes: tags: [tag1, tag2] category: category-name

My Custom Skill

Overview

What this skill does and why it exists.

When to Use

  • Condition 1
  • Condition 2
  • Commands

    bash

    Main commands

    command --option value

    With examples

    command --example "real usage"
    
    

    Common Pitfalls

    | Pitfall | Fix | |---|---| | Common mistake | Correct approach |

    3. Browser Automation Stack

    Browser Selection Decision Tree

    Browser task?
    ├── Anti-detection needed (social media, login)?
    │   └── YES → CamoFox (port 9377)
    │       - Residential proxy rotation
    │       - Canvas/WebGL fingerprint randomization
    │       - WebRTC leak protection
    │       - Timezone spoofing
    │
    ├── DataDome/Cloudflare bypass needed?
    │   └── YES → Patchright (port 9378)
    │       - Patched Chromium binary
    │       - Advanced bot detection evasion
    │       - Cloudflare Turnstile solver
    │
    ├── Fast scraping (no rendering needed)?
    │   └── YES → Scrapling (spider mode)
    │       - TLS fingerprint impersonation
    │       - HTTP/2 multiplexing
    │       - No DOM rendering (fast)
    │
    └── Normal web browsing?
        └── Default browser tools
            - browser_navigate
            - browser_snapshot
            - browser_click/type
    

    CamoFox Anti-Detection Configuration

    # Start CamoFox (typically managed by systemd)
    

    /etc/systemd/system/camofox.service

    [Unit] Description=CamoFox Anti-Detection Browser After=network.target

    [Service]
    Type=simple
    WorkingDirectory=/opt/camofox-browser
    ExecStart=/opt/camofox-browser/camofox --port 9377 --stealth-mode high
    Restart=always
    RestartSec=5

    [Install]
    WantedBy=multi-user.target

    Scrapling Web Scraping

    from scrapling import Fetcher, StealthyFetcher, BrowserConstructor
    

    Fast mode (no rendering)

    fetcher = Fetcher(auto_match=False) response = fetcher.get("https://example.com") print(response.css("h1::text").get())

    Stealth mode (with browser)

    stealth = StealthyFetcher() response = stealth.fetch("https://protected-site.com")

    Spider mode (crawl multiple pages)

    from scrapling import Adaptor adaptor = Adaptor("https://example.com") links = adaptor.css_links() # Auto-extract all links

    4. Multi-Provider LLM Configuration

    Provider Configuration Matrix

    Provider      │ Model              │ Strengths              │ Cost
    ──────────────┼────────────────────┼────────────────────────┼──────────
    chutes        │ GLM-5-Turbo        │ Code, Chinese, fast    │ Free
    openrouter    │ 200+ models        │ Reasoning, variety     │ ~$0.001/tk
    venice        │ Llama 3.1 70B      │ Uncensored, creative   │ Free tier
    arliai        │ Open models        │ Research, benchmarks   │ Free
    featherless   │ Community models   │ Open-source LLMs      │ Free
    byteplus      │ Code-specific      │ Programming tasks      │ Varies
    stepfun       │ Chinese-optimized  │ CJK language tasks    │ Free tier
    zenmux        │ Aggregate routing  │ Model variety          │ Varies
    orbit         │ Enterprise models  │ Professional tasks     │ Varies
    infermatic    │ Research models     │ Academic use cases    │ Free tier
    ollama-cloud  │ GLM-5.1            │ Primary daily driver   │ Free
    

    Model Selection Strategy

    Task type? ─┬─ Code generation ──→ GLM-5-Turbo (chutes) or GLM-5.1 (ollama-cloud)
                 ├─ Web research ─────→ Gemini 2.0 Flash (openrouter, 1M context)
                 ├─ Creative writing ─→ Llama 3.1 70B (venice, uncensored)
                 ├─ Deep analysis ───→ Claude Sonnet 4 (openrouter, reasoning)
                 ├─ Quick chat ──────→ GLM-5-Turbo (chutes, speed)
                 ├─ Chinese tasks ───→ StepFun models (stepfun)
                 ├─ Data extraction ─→ Gemini 2.0 Flash (structured output)
                 └─ Image analysis ──→ Vision model (via openrouter)
    

    Fallback Chain Configuration

    {
      "fallbackChain": [
        {"provider": "ollama-cloud", "model": "glm-5.1"},
        {"provider": "chutes", "model": "chutes/zai-org/GLM-5-Turbo"},
        {"provider": "openrouter", "model": "google/gemini-2.0-flash-001"},
        {"provider": "venice", "model": "venice/llama-3.1-70b"}
      ],
      "retryPolicy": {
        "maxRetries": 3,
        "backoffMs": [1000, 3000, 5000],
        "retryOnStatusCodes": [429, 500, 502, 503]
      }
    }
    

    5. Prompt Engineering for OpenClaw

    System Prompt Patterns

    {
      "systemPrompts": {
        "default": "You are a helpful AI assistant. Be concise and accurate.",
        "code": "You are an expert programmer. Write clean, well-commented code. Always include error handling.",
        "creative": "You are a creative writer. Be expressive, original, and imaginative. No restrictions on content.",
        "research": "You are a research analyst. Cite sources, provide evidence, and present balanced viewpoints.",
        "technical": "You are a DevOps engineer. Provide exact commands, configs, and troubleshooting steps."
      }
    }
    

    JSON Mode for Structured Output

    {
      "model": "chutes/zai-org/GLM-5-Turbo",
      "messages": [
        {
          "role": "system",
          "content": "Always respond with valid JSON matching this schema: {\"status\": \"string\", \"data\": {}, \"error\": \"string|null\"}"
        }
      ],
      "response_format": { "type": "json_object" },
      "temperature": 0.1
    }
    

    Context Window Management

    Model context budgets:
    ┌────────────────────────────────────────────────────────┐
    │ Model              │ Context  │ Recommended Max Output │
    ├────────────────────────────────────────────────────────┤
    │ GLM-5-Turbo        │ 32K      │ 4K                     │
    │ GLM-5.1            │ 32K      │ 4K                     │
    │ Gemini 2.0 Flash   │ 1M       │ 8K                     │
    │ Claude Sonnet 4    │ 200K     │ 8K                     │
    │ Llama 3.1 70B      │ 128K     │ 4K                     │
    └────────────────────────────────────────────────────────┘
    

    Token optimization:

  • System prompt: keep under 2K tokens

  • Skills are loaded per-turn (budget impact)

  • Use JSON mode for structured responses (saves tokens)

  • Compress old conversation turns automatically

  • 6. WhatsApp Integration

    Bridge Configuration

    {
      "whatsapp": {
        "enabled": true,
        "bridgePort": 9375,
        "sessionPath": "./data/whatsapp-session",
        "webhookUrl": "http://localhost:18789/webhook",
        "maxMessageLength": 4096,
        "mediaTypes": ["image", "audio", "document", "video"],
        "rateLimit": {
          "messagesPerMinute": 30,
          "mediaPerMinute": 10
        },
        "groups": {
          "enabled": true,
          "mentionOnly": false,
          "allowedGroups": ["120363425295725531"]
        }
      }
    }
    

    WhatsApp Chat Viewer

    # Configure WA Chat Viewer (systemd)
    

    /etc/systemd/system/whatsapp-chat.service

    [Unit] Description=WhatsApp Chat Viewer After=network.target

    [Service]
    Type=simple
    WorkingDirectory=/opt/whatsapp-chat-viewer
    ExecStart=/usr/bin/python3 app.py --port 9376
    Restart=always

    [Install]
    WantedBy=multi-user.target

    Start

    sudo systemctl start whatsapp-chat

    7. Custom Tools & Integration

    Creating Custom Tools for OpenClaw

    {
      "customTools": [
        {
          "name": "server_health_check",
          "description": "Check health of all fleet servers",
          "parameters": {
            "type": "object",
            "properties": {
              "servers": {
                "type": "array",
                "items": {"type": "string"},
                "description": "List of server IPs/hostnames"
              }
            }
          },
          "execute": {
            "type": "script",
            "path": "./scripts/health-check.sh"
          }
        },
        {
          "name": "deploy_fleet",
          "description": "Deploy configuration across fleet",
          "parameters": {
            "type": "object",
            "properties": {
              "service": {"type": "string"},
              "config_path": {"type": "string"}
            }
          },
          "execute": {
            "type": "script",
            "path": "./scripts/deploy-fleet.sh"
          }
        }
      ]
    }
    

    Health Check Script

    #!/bin/bash
    

    scripts/health-check.sh

    SERVERS=("51.83.223.88" "152.114.193.86") for server in "${SERVERS[@]}"; do echo "=== $server ===" ssh "$server" "uptime; df -h / | tail -1; free -m | head -2" done

    8. Fleet Deployment Across VPS

    Fleet Architecture

    ┌─────────────────────────────────────────────────────────┐
    │                S4S Fleet (5 VPS Instances)               │
    │                                                          │
    │  Gateway: 51.83.223.88 (oc.s4s.host, 48c/252GB)        │
    │    ├── US Instance (port 9377) — Primary                 │
    │    ├── TR Instance (port 9378) — Secondary               │
    │    ├── PK-C2 (port 9379) — Pakistan                      │
    │    ├── PK-C3 (port 9380) — Pakistan (default)            │
    │    └── HK-UK2 (152.114.193.86) — Full clone             │
    │        ├── OpenClaw (port 18789, nginx+SSL)              │
    │        ├── CamoFox (port 9377)                            │
    │        ├── MariaDB (port 3306)                            │
    │        ├── Hindsight (port 9077)                          │
    │        ├── WA Chat Viewer (port 9376)                     │
    │        └── 12 SSL subdomains (*.hkuk2.s4s.host)          │
    └─────────────────────────────────────────────────────────┘
    

    Fleet Sync Script

    #!/bin/bash
    

    fleet-sync.sh — Sync OpenClaw config across fleet

    CONFIG_SOURCE="/opt/openclaw/openclaw.json"
    TARGETS=("us:51.83.223.88" "tr:51.83.223.88" "pkoc2:51.83.223.88" "hkuk2:152.114.193.86")

    echo "🔄 Syncing OpenClaw configuration..."
    for target in "${TARGETS[@]}"; do
    IFS=':' read -r name host <<< "$target"
    echo " → Syncing to $name ($host)..."
    rsync -avz "$CONFIG_SOURCE" "$host:/opt/openclaw/openclaw.json"
    ssh "$host" "cd /opt/openclaw && docker compose restart openclaw"
    echo " ✅ $name synced"
    done
    echo "🎉 Fleet sync complete"

    9. Troubleshooting

    OpenClaw Won't Start

    OpenClaw won't start? ─┬─ Docker not running? ──→ systemctl start docker
                            ├─ Port 18789 in use? ──→ lsof -i :18789 → kill or change port
                            ├─ Config error? ──→ jq . openclaw.json
                            ├─ Redis not running? ──→ docker compose restart redis
                            ├─ Permission denied? ──→ sudo chown -R $USER:$USER /opt/openclaw
                            └─ Image pull failure? ──→ docker compose pull
    

    WhatsApp Connection Issues

    WA issues? ─┬─ QR code expired? ──→ Regenerate: delete session, restart bridge
                  ├─ Bridge process dead? ──→ docker compose restart openclaw
                  ├─ Rate limited? ──→ Reduce message frequency, wait 5min
                  ├─ Media not sending? ──→ Check file size (max 16MB WA limit)
                  └─ Group messages not working? ──→ Check groups.enabled in config
    

    Browser Automation Failing

    Browser fails? ─┬─ CamoFox port not responding? ──→ Check systemd status, restart
                      ├─ Cloudflare block? ──→ Switch to Patchright (port 9378)
                      ├─ DataDome detection? ──→ Use Patchright + residential proxy
                      ├─ Rate limited? ──→ Add delays between requests (2-5s)
                      ├─ Element not found? ──→ Refresh snapshot, use full=True
                      └─ SSL error? ──→ Update CA certs: apt install ca-certificates
    

    LLM Provider Errors

    Provider error? ─┬─ 401 ──→ Check API key in openclaw.json env block
                       ├─ 429 ──→ Rate limited, wait or switch provider
                       ├─ 500 ──→ Provider down, try fallback chain
                       ├─ Timeout ──→ Increase maxTokens or reduce input
                       └─ Invalid model ──→ Check model name in provider docs
    

    Performance Optimization

    ┌──────────────────────────────────────────────────────────────┐
    │ Optimization               │ Impact          │ Complexity    │
    ├──────────────────────────────────────────────────────────────┤
    │ Redis for session caching   │ -40% latency    │ Easy          │
    │ Nginx SSL termination      │ -30% TLS time   │ Easy          │
    │ Docker resource limits      │ Stable perf     │ Easy          │
    │ Model response caching     │ -60% repeated    │ Medium        │
    │ Skill lazy-loading         │ -50% cold start │ Medium        │
    │ WebSocket connection pool   │ +2x throughput   │ Medium        │
    │ Redis queue for messages   │ +3x throughput   │ Hard          │
    └──────────────────────────────────────────────────────────────┘
    

    10. Best Practices & Common Pitfalls

    Best Practices

  • Always use systemd — Never run with nohup or background &. Orphaned bridge processes break WhatsApp.
  • Restart both gateway and bridge togethersystemctl restart hermes-gateway with KillMode=control-group
  • Keep skills under 40KB — Larger skills waste context budget
  • Use JSON mode for structured output — Reduces token waste on creative writing
  • Set rate limits on nginx — 30 req/min per IP prevents abuse
  • Use CamoFox for anti-detection — Not default browser for social media
  • Monitor disk space — WhatsApp sessions + media can fill disks
  • Backup sessionstar czf wa-backup.tar.gz data/whatsapp-session/
  • Test provider failover — Disable primary provider to verify fallback chain works
  • Rotate API keys quarterly — Set calendar reminder for key rotation
  • Common Pitfalls Table

    | Pitfall | Symptom | Fix | |---|---|---| | Using nohup for bridge | WhatsApp stops responding randomly | Use systemctl restart hermes-gateway | | Stale WhatsApp session | QR code loop, can't authenticate | Delete session dir, re-authenticate | | Missing API key in env | Provider returns 401 | Add key to openclaw.json env block | | Docker volume not mounted | Data lost on restart | Add volume mounts in compose file | | No nginx SSL termination | Mixed content errors, slow TLS | Configure nginx HTTPS reverse proxy | | Overloaded context window | Agent loses track mid-conversation | Reduce skills loaded, compress history | | Wrong browser for site | Bot detection, captcha | Switch CamoFox → Patchright → Scrapling | | Disk full from media | Agent stops, sessions corrupt | Monitor with cron + df -h alerts | | Orphaned Docker containers | Port conflicts, zombie processes | docker compose down && docker compose up -d | | Skills in wrong directory | Skill not discovered | Check openclaw skills list for path |

    11. Security Hardening

    API Key Management

    # Environment variable approach (NEVER hardcode in config.json)
    

    openclaw.json env block references env vars:

    "env": {

    "CHUTES_API_KEY": "chute_xxxxx",

    "OPENROUTER_API_KEY": "sk-or-v1-xxxxx"

    }

    For production, use Docker secrets or vault:

    echo "chute_xxxxx" | docker secret create chutes_api_key -

    Rotate keys quarterly

    Calendar reminder: Q1=Jan, Q2=Apr, Q3=Jul, Q4=Oct

    Input Sanitization & Validation

    def validate_openclaw_config(config: dict) -> list[str]:
        """Validate OpenClaw configuration for security issues."""
        errors = []
        
        # Check for hardcoded API keys in non-env sections
        config_str = json.dumps(config)
        api_key_patterns = [
            r'sk-[a-zA-Z0-9]{20,}',  # OpenAI-style keys
            r'cpk_[a-zA-Z0-9]{20,}',  # Chutes keys
            r'gsk_[a-zA-Z0-9]{20,}',  # Groq keys
        ]
        for pattern in api_key_patterns:
            import re
            if re.search(pattern, config_str):
                # Ignore env block references
                matches = re.findall(pattern, config_str)
                for m in matches:
                    # Check if it's outside the env block
                    if '"env"' not in config_str[:config_str.index(m)]:
                        errors.append(f"Hardcoded API key found: {m[:8]}...")
        
        # Check password strength
        auth = config.get("auth", {})
        if auth.get("password") and len(auth["password"]) < 8:
            errors.append("Auth password too short (min 8 chars)")
        
        # Check for open CORS
        # Validate SSL config
        # Check rate limits
        
        return errors
    

    Container Security

    # docker-compose.yml security hardening
    services:
      openclaw:
        image: openclaw/openclaw:latest
        security_opt:
          - no-new-privileges:true
        read_only: true
        tmpfs:
          - /tmp
          - /app/data
        cap_drop:
          - ALL
        cap_add:
          - NET_BIND_SERVICE
        deploy:
          resources:
            limits:
              cpus: '4'
              memory: 8G
            reservations:
              cpus: '2'
              memory: 4G
        healthcheck:
          test: ["CMD", "curl", "-f", "http://localhost:18789/health"]
          interval: 30s
          timeout: 10s
          retries: 3
    

    Network Security

    # Firewall rules (ufw)
    ufw default deny incoming
    ufw default allow outgoing
    ufw allow 22/tcp       # SSH
    ufw allow 80/tcp       # HTTP (for certbot)
    ufw allow 443/tcp      # HTTPS (nginx)
    ufw deny 18789/tcp     # Block direct OpenClaw access
    ufw deny 9377:9378/tcp # Block direct browser access
    ufw deny 3306/tcp      # Block direct DB access
    ufw deny 6379/tcp      # Block direct Redis access
    

    Verify

    ufw status numbered

    12. Testing & Quality Assurance

    Smoke Test Suite

    #!/bin/bash
    

    smoke-test.sh — OpenClaw deployment verification

    echo "🔍 OpenClaw Smoke Tests"
    echo "========================"

    Test 1: Gateway health

    echo -n "1. Gateway health... " STATUS=$(curl -sf http://localhost:18789/health | jq -r '.status' 2>/dev/null) [ "$STATUS" = "ok" ] && echo "✅" || echo "❌ (status: $STATUS)"

    Test 2: LLM provider connectivity

    echo -n "2. LLM provider... " RESPONSE=$(curl -sf http://localhost:18789/api/chat \ -H "Content-Type: application/json" \ -d '{"message":"ping","model":"chutes/zai-org/GLM-5-Turbo"}' 2>/dev/null) [ -n "$RESPONSE" ] && echo "✅" || echo "❌"

    Test 3: Skill loading

    echo -n "3. Skill count... " COUNT=$(curl -sf http://localhost:18789/api/skills 2>/dev/null | jq 'length') [ "$COUNT" -gt 0 ] && echo "✅ ($COUNT skills)" || echo "❌"

    Test 4: Redis connectivity

    echo -n "4. Redis... " docker exec openclaw-redis redis-cli ping 2>/dev/null | grep -q PONG && echo "✅" || echo "❌"

    Test 5: Nginx SSL

    echo -n "5. SSL termination... " curl -sf https://openclaw.munaf.oc.s4s.host/health >/dev/null 2>&1 && echo "✅" || echo "❌"

    Test 6: Browser automation

    echo -n "6. CamoFox... " curl -sf http://localhost:9377/health >/dev/null 2>&1 && echo "✅" || echo "❌"

    echo "========================"
    echo "Smoke tests complete"

    Load Testing

    # Basic load test with hey (HTTP load generator)
    hey -n 100 -c 10 -m POST \
      -H "Content-Type: application/json" \
      -d '{"message":"Hello, how are you?","model":"chutes/zai-org/GLM-5-Turbo"}' \
      http://localhost:18789/api/chat
    

    Expected results:

    - p95 latency < 5s (for simple queries)

    - 0% error rate

    - Throughput > 10 req/s