{"id":43933004,"url":"https://github.com/digitalocean-labs/openclaw-appplatform","last_synced_at":"2026-02-07T00:19:31.840Z","repository":{"id":334868552,"uuid":"1143087608","full_name":"digitalocean-labs/openclaw-appplatform","owner":"digitalocean-labs","description":"Pre-built Docker image for deploying OpenClaw on DigitalOcean App Platform","archived":false,"fork":false,"pushed_at":"2026-02-01T07:06:25.000Z","size":181,"stargazers_count":1,"open_issues_count":2,"forks_count":3,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-01T07:10:50.363Z","etag":null,"topics":["app-platform","digitalocean","digitalocean-app-platform","openclaw"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/digitalocean-labs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-27T06:50:56.000Z","updated_at":"2026-02-01T06:29:09.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/digitalocean-labs/openclaw-appplatform","commit_stats":null,"previous_names":["digitalocean-labs/clawdbot-appplatform","digitalocean-labs/openclaw-appplatform"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/digitalocean-labs/openclaw-appplatform","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalocean-labs%2Fopenclaw-appplatform","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalocean-labs%2Fopenclaw-appplatform/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalocean-labs%2Fopenclaw-appplatform/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalocean-labs%2Fopenclaw-appplatform/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/digitalocean-labs","download_url":"https://codeload.github.com/digitalocean-labs/openclaw-appplatform/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalocean-labs%2Fopenclaw-appplatform/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29181326,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-06T23:15:33.022Z","status":"ssl_error","status_checked_at":"2026-02-06T23:15:09.128Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["app-platform","digitalocean","digitalocean-app-platform","openclaw"],"created_at":"2026-02-07T00:19:27.269Z","updated_at":"2026-02-07T00:19:31.828Z","avatar_url":"https://github.com/digitalocean-labs.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OpenClaw on DigitalOcean App Platform\n\nDeploy [OpenClaw](https://github.com/openclaw/openclaw) - a multi-channel AI messaging gateway - on DigitalOcean App Platform in minutes.\n\n[![Deploy to DO](https://www.deploytodo.com/do-btn-blue.svg)](https://cloud.digitalocean.com/apps/new?repo=https://github.com/digitalocean-labs/openclaw-appplatform/tree/main)\n\n## Quick Start: Choose Your Stage\n\n| Stage                   | What You Get            | Access Method        |\n|-------------------------|-------------------------|----------------------|\n| **1. CLI Only**         | Gateway + CLI           | `doctl apps console` |\n| **2. + Web UI + ngrok** | Control UI + Public URL | ngrok URL            |\n| **3. + Tailscale**      | Private Network         | Tailscale hostname   |\n| **+ Persistence**       | Data survives restarts  | DO Spaces            |\n\n**Start simple, add features as needed.** Most users start with Stage 2 (ngrok) for the easiest setup.\n\n---\n\n## Architecture\n\n```\n┌────────────────────────────────────────────────────────────────────┐\n│                      openclaw-appplatform                           │\n│  ┌──────────────────────────────────────────────────────────────┐  │\n│  │ s6-overlay - Process supervision and init system             │  │\n│  └──────────────────────────────────────────────────────────────┘  │\n│  ┌─────────────┐  ┌───────────────────┐                            │\n│  │ Ubuntu      │  │ OpenClaw Gateway  │                            │\n│  │ Noble+Node  │  │ WebSocket :18789  │                            │\n│  │ + nvm       │  │ + Control UI      │                            │\n│  └─────────────┘  └───────────────────┘                            │\n│  ┌──────────────────────────────────────────────────────────────┐  │\n│  │ Access Layer (choose one):                                   │  │\n│  │  • Console only (default) - doctl apps console               │  │\n│  │  • ngrok (ENABLE_NGROK) - Public tunnel to UI                │  │\n│  │  • Tailscale (TAILSCALE_ENABLE) - Private network            │  │\n│  └──────────────────────────────────────────────────────────────┘  │\n│  ┌──────────────────────────────────────────────────────────────┐  │\n│  │ Optional: SSH Server (SSH_ENABLE=true)                        │  │\n│  └──────────────────────────────────────────────────────────────┘  │\n└────────────────────────────────────────────────────────────────────┘\n         │                    │                    │\n         ▼                    ▼                    ▼\n   ┌──────────┐        ┌──────────┐        ┌──────────┐\n   │ WhatsApp │        │ Telegram │        │ Discord  │\n   │ Signal   │        │ Slack    │        │ MS Teams │\n   │ iMessage │        │ Matrix   │        │ + more   │\n   └──────────┘        └──────────┘        └──────────┘\n```\n\n---\n\n## Stage 1: CLI Only - The Basics\n\nThe simplest deployment. Access via `doctl apps console` and use CLI commands.\n\n### Deploy\n\n```bash\n# Clone the repo\ngit clone https://github.com/digitalocean-labs/openclaw-appplatform\ncd openclaw-appplatform\n\n# Edit app.yaml - set instance size for Stage 1\n# instance_size_slug: apps-s-1vcpu-2gb  # 1 CPU, 2GB (minimum for stable operation)\n\n# Set your OPENCLAW_GATEWAY_TOKEN in app.yaml or DO dashboard\n\n# Deploy\ndoctl apps create --spec app.yaml\n```\n\n### Connect\n\n```bash\n# Get app ID\ndoctl apps list\n\n# Open console\ndoctl apps console \u003capp-id\u003e openclaw\n\n# Verify gateway is running\nopenclaw gateway health --url ws://127.0.0.1:18789\n\n# Check channel status\nopenclaw channels status --probe\n```\n\n### What's Included\n\n- ✅ OpenClaw gateway (WebSocket on port 18789)\n- ✅ CLI access via `openclaw` command\n- ✅ All channel plugins (WhatsApp, Telegram, Discord, etc.)\n- ❌ No web UI access (use CLI/TUI)\n- ❌ No public URL\n- ❌ Data lost on restart\n\n---\n\n## Stage 2: Add Web UI + ngrok\n\nAdd a public URL to access the Control UI. **Recommended for getting started.**\n\n### Get ngrok Token\n\n1. Sign up at \u003chttps://dashboard.ngrok.com\u003e\n2. Copy your authtoken from the dashboard\n\n### Deploy\n\nUpdate `app.yaml`:\n\n```yaml\ninstance_size_slug: apps-s-1vcpu-2gb  # 1 CPU, 2GB\n\nenvs:\n  - key: ENABLE_NGROK\n    value: \"true\"\n  - key: NGROK_AUTHTOKEN\n    type: SECRET\n    # Set value in DO dashboard\n```\n\n### Get Your URL\n\n```bash\n# In console\ncurl -s http://127.0.0.1:4040/api/tunnels | jq -r '.tunnels[0].public_url'\n```\n\nOr check the ngrok dashboard at \u003chttps://dashboard.ngrok.com/tunnels\u003e\n\n### What's Added\n\n- ✅ Everything from Stage 1\n- ✅ Web Control UI\n- ✅ Public URL via ngrok\n- ❌ URL changes on restart (use Tailscale for stable URL)\n- ❌ Data lost on restart\n\n---\n\n## Stage 3: Production with Tailscale\n\nPrivate network access via your Tailscale tailnet. **Recommended for production.**\n\n### Get Tailscale Auth Key\n\nSee [Setting up Tailscale](#setting-up-tailscale) for a detailed walkthrough with screenshots.\n\n1. Go to \u003chttps://login.tailscale.com/admin/settings/keys\u003e\n2. Generate a reusable auth key\n\n### Deploy\n\nUpdate `app.yaml`:\n\n```yaml\ninstance_size_slug: apps-s-1vcpu-2gb  # 1 CPU, 2GB\n\nenvs:\n  - key: ENABLE_NGROK\n    value: \"false\"\n  - key: TAILSCALE_ENABLE\n    value: \"true\"\n  - key: TS_AUTHKEY\n    type: SECRET\n  - key: STABLE_HOSTNAME\n    value: openclaw\n```\n\n### Access\n\n```\nhttps://openclaw.\u003cyour-tailnet\u003e.ts.net\n```\n\n### What's Added\n\n- ✅ Everything from Stage 1 \u0026 2\n- ✅ Stable hostname on your tailnet\n- ✅ Private access (only your devices)\n- ✅ Production-grade security\n- ❌ Data lost on restart (add Spaces for persistence)\n\n---\n\n## Setting up Tailscale\n\nThis section walks you through creating a Tailscale auth key for your OpenClaw deployment.\n\n### 1. Sign in to Tailscale\n\nGo to \u003chttps://login.tailscale.com\u003e and sign in with your preferred identity provider (Google, Microsoft, GitHub, etc.).\n\n### 2. Access the Admin Console\n\nOnce signed in, you'll be taken to the Tailscale admin console. This is where you manage your tailnet (your private network).\n\n### 3. Navigate to Auth Keys\n\n1. Click **Settings** in the left sidebar\n2. Click **Keys** under the Personal Settings section\n3. Or go directly to \u003chttps://login.tailscale.com/admin/settings/keys\u003e\n\n\u003c!-- Screenshot: Settings \u003e Keys navigation --\u003e\n\n### 4. Generate an Auth Key\n\n1. Click **Generate auth key**\n2. Configure the key settings:\n   - **Reusable**: Enable this so the key can be used if the container restarts\n   - **Ephemeral**: Optional - nodes using this key will be automatically removed when they go offline\n   - **Tags**: Optional - apply ACL tags to control access\n   - **Expiration**: Choose an appropriate expiration (default is 90 days)\n\n![Tailscale Auth Key Settings](ts-auth-key.png)\n\n### 5. Copy Your Auth Key\n\nAfter clicking **Generate key**, your auth key will be displayed. Copy it immediately as it won't be shown again.\n\nThe key format looks like: `tskey-auth-xxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxx`\n\n### 6. Add the Key to Your Deployment\n\nSet the `TS_AUTHKEY` environment variable in your `app.yaml` or in the DigitalOcean dashboard:\n\n```yaml\nenvs:\n  - key: TS_AUTHKEY\n    type: SECRET\n    value: \"tskey-auth-xxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxx\"\n```\n\n### 7. Verify the Connection\n\nAfter deploying, your OpenClaw instance will appear in the **Machines** tab of your Tailscale admin console.\n\nYou can access your instance at:\n```\nhttps://\u003chostname\u003e.\u003cyour-tailnet\u003e.ts.net\n```\n\n---\n\n## Adding Persistence (Any Stage)\n\nWithout persistence, all data is lost when the container restarts. Add DO Spaces to preserve:\n\n- Channel sessions (WhatsApp linking, etc.)\n- Configuration changes\n- Memory/search index\n- Tailscale state\n\n### Setup DO Spaces\n\n1. **Create a Spaces bucket** in the same region as your app\n   - Go to **Spaces Object Storage** → **Create Bucket**\n\n2. **Create access keys**\n   - Go to **API** → **Spaces Keys** → **Generate New Key**\n\n3. **Update app.yaml**:\n\n```yaml\nenvs:\n  - key: ENABLE_SPACES\n    value: \"true\"\n  - key: RESTIC_SPACES_ACCESS_KEY_ID\n    type: SECRET\n  - key: RESTIC_SPACES_SECRET_ACCESS_KEY\n    type: SECRET\n  - key: RESTIC_SPACES_ENDPOINT\n    value: tor1.digitaloceanspaces.com  # Match your region\n  - key: RESTIC_SPACES_BUCKET\n    value: openclaw-backup\n  - key: RESTIC_PASSWORD\n    type: SECRET\n```\n\n### What Gets Persisted\n\nThe backup system uses [Restic](https://restic.net/) for incremental, encrypted snapshots to DigitalOcean Spaces.\n\n| Path              | Contents                                         | Backup Frequency         |\n|-------------------|--------------------------------------------------|--------------------------|\n| `/data/.openclaw` | Gateway config, channel sessions, agents, memory | Every 30s (configurable) |\n| `/data/tailscale` | Tailscale connection state (persistent device)   | Every 30s                |\n| `/etc`            | System configuration                             | Every 30s                |\n| `/home`           | User files, Homebrew packages                    | Every 30s                |\n| `/root`           | Root user data                                   | Every 30s                |\n\n**Automatic Restore:**\n- On container restart, `10-restore-state` init script automatically restores the latest snapshot for each path\n- Restores are fast and incremental\n- Data survives deployments, restarts, and instance replacements\n\n**Repository Management:**\n- Old snapshots are automatically pruned every hour\n- Repository is encrypted with `RESTIC_PASSWORD`\n- Stored in: `s3:\u003cendpoint\u003e/\u003cbucket\u003e/\u003chostname\u003e/restic`\n\n**Configuration File:**\nBackup behavior is controlled by `/etc/digitalocean/backup.yaml`:\n- **Backup paths**: What directories to back up\n- **Exclusions**: Files to skip (*.lock, *.pid, *.sock)\n- **Intervals**: Backup frequency (default: 30s), prune frequency (default: 1h)\n- **Retention policy**: How many snapshots to keep (last 10, hourly 48, daily 30, etc.)\n\nTo customize, create `rootfs/etc/digitalocean/backup.yaml` in your repo and rebuild.\n\n---\n\n## AI-Assisted Setup\n\nWant an AI assistant to help deploy and configure OpenClaw? See **[AI-ASSISTED-SETUP.md](AI-ASSISTED-SETUP.md)** for:\n\n- Copy-paste prompts for each stage\n- WhatsApp channel setup (with QR code handling)\n- Verification steps\n- Works with Claude Code, Cursor, Codex, Gemini, etc.\n\n---\n\n## CLI Cheat Sheet\n\nThe `openclaw` command is a wrapper that runs openclaw with the correct user and environment. **Always use `openclaw` in console sessions.**\n\n```bash\n# Gateway\nopenclaw gateway health --url ws://127.0.0.1:18789\nopenclaw gateway status\n\n# Channels\nopenclaw channels status --probe\nopenclaw channels login                    # WhatsApp QR code\n\n# Messages\nopenclaw message send --channel whatsapp --target \"+1234567890\" --message \"Hello!\"\n\n# Services\n/command/s6-svc -r /run/service/openclaw    # Restart\n/command/s6-svc -r /run/service/ngrok      # Restart ngrok\n\n# Logs\ntail -f /data/.openclaw/logs/gateway.log\n\n# Config\ncat /data/.openclaw/openclaw.json | jq .\n```\n\nSee **[CHEATSHEET.md](CHEATSHEET.md)** for the complete reference.\n\n---\n\n## Environment Variables\n\n### Required\n\n| Variable                 | Description                         |\n|--------------------------|-------------------------------------|\n| `OPENCLAW_GATEWAY_TOKEN` | Password for web setup wizard       |\n| `STABLE_HOSTNAME`        | A stable hostname for this instance |\n\n### Feature Flags\n\n| Variable           | Default | Description                  |\n|--------------------|---------|------------------------------|\n| `ENABLE_NGROK`     | `false` | Enable ngrok tunnel          |\n| `ENABLE_TAILSCALE` | `false` | Enable Tailscale             |\n| `ENABLE_SPACES`    | `false` | Enable DO Spaces persistence |\n| `ENABLE_UI`        | `true`  | Enable web Control UI        |\n| `SSH_ENABLE`       | `false` | Enable SSH server            |\n\n### ngrok (when ENABLE_NGROK=true)\n\n| Variable          | Description           |\n|-------------------|-----------------------|\n| `NGROK_AUTHTOKEN` | Your ngrok auth token |\n\n### Tailscale (when TAILSCALE_ENABLE=true)\n\n| Variable     | Description        |\n|--------------|--------------------|\n| `TS_AUTHKEY` | Tailscale auth key |\n\n### Spaces (when ENABLE_SPACES=true)\n\n| Variable                          | Description                         |\n|-----------------------------------|-------------------------------------|\n| `RESTIC_SPACES_ACCESS_KEY_ID`     | Spaces access key                   |\n| `RESTIC_SPACES_SECRET_ACCESS_KEY` | Spaces secret key                   |\n| `RESTIC_SPACES_ENDPOINT`          | e.g., `tor1.digitaloceanspaces.com` |\n| `RESTIC_SPACES_BUCKET`            | Your bucket name                    |\n| `RESTIC_PASSWORD`                 | Backup encryption password          |\n\n### Optional\n\n| Variable                 | Description                                    |\n|--------------------------|------------------------------------------------|\n| `OPENCLAW_GATEWAY_TOKEN` | Gateway auth token (auto-generated if not set) |\n| `GRADIENT_API_KEY`       | DigitalOcean Gradient AI key                   |\n| `GITHUB_USERNAME`        | For SSH key fetching                           |\n\n---\n\n## Customization (s6-overlay)\n\nThe container uses [s6-overlay](https://github.com/just-containers/s6-overlay) for process supervision.\n\n### Dynamic MOTD\n\nOn login, you'll see a colorful status display. Run `motd` anytime to refresh.\n\n| Section      | Info                                               |\n|--------------|----------------------------------------------------|\n| 🖥️ System   | Hostname, uptime, load, memory, disk (color-coded) |\n| 🔗 Tailscale | Status, IP, relay, serve URL (if enabled)          |\n| 🦞 OpenClaw  | Health status, configured channels, agent count    |\n| 📚 Links     | OpenClaw docs, App Platform docs, source repo      |\n\n### Add Custom Init Scripts\n\nCreate `rootfs/etc/cont-init.d/30-my-script`:\n\n```bash\n#!/command/with-contenv bash\necho \"Running my custom setup...\"\n```\n\n### Add Custom Services\n\nCreate `rootfs/etc/services.d/my-daemon/run`:\n\n```bash\n#!/command/with-contenv bash\nexec my-daemon --foreground\n```\n\n### Built-in Services\n\n| Service     | Description                                              |\n|-------------|----------------------------------------------------------|\n| `openclaw`  | OpenClaw gateway                                         |\n| `ngrok`     | ngrok tunnel (if enabled)                                |\n| `tailscale` | Tailscale daemon (if enabled)                            |\n| `backup`    | Restic backup service - creates snapshots (if enabled)   |\n| `prune`     | Restic prune service - cleans old snapshots (if enabled) |\n| `crond`     | Cron daemon for scheduled tasks                          |\n| `sshd`      | SSH server (if enabled)                                  |\n\n---\n\n## Available Regions\n\n| Code  | Location          |\n|-------|-------------------|\n| `nyc` | New York          |\n| `atl` | Atlanta           |\n| `ams` | Amsterdam         |\n| `sfo` | San Francisco     |\n| `sgp` | Singapore         |\n| `lon` | London            |\n| `fra` | Frankfurt         |\n| `blr` | Bangalore         |\n| `syd` | Sydney            |\n| `tor` | Toronto (default) |\n\n---\n\n## Documentation\n\n- [OpenClaw Documentation](https://docs.openclaw.ai)\n- [DigitalOcean App Platform](https://docs.digitalocean.com/products/app-platform/)\n- [AI-Assisted Setup Guide](AI-ASSISTED-SETUP.md)\n- [CLI Cheat Sheet](CHEATSHEET.md)\n\n---\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigitalocean-labs%2Fopenclaw-appplatform","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdigitalocean-labs%2Fopenclaw-appplatform","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigitalocean-labs%2Fopenclaw-appplatform/lists"}