feat(openclaw): deploy OpenClaw AI chatbot gateway on VM 120

- Add Docker Compose configs with security hardening (cap_drop ALL, non-root, read-only FS)
- Add Prometheus node_exporter scrape target for 192.168.2.120:9100
- Update services/README.md, INDEX.md, and CLAUDE_STATUS.md with VM 120
- Image pinned to v2026.2.1 (patches CVE-2026-25253)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-03 18:07:09 -07:00
parent e481c95da4
commit e08951de21
9 changed files with 1031 additions and 20 deletions

View File

@@ -321,7 +321,7 @@ The Twingate connector is configured via the Twingate Admin Console:
- Proxmox Web UI (192.168.2.200:8006)
- Grafana Monitoring (192.168.2.114:3000)
- Nginx Proxy Manager (192.168.2.101:81)
- n8n Workflows (192.168.2.107:5678)
- n8n Workflows (192.168.2.113:5678)
- Development VMs and services
**Access Policies**:
@@ -331,6 +331,39 @@ The Twingate connector is configured via the Twingate Admin Console:
---
## OpenClaw - AI Chatbot Gateway
**Directory**: `openclaw/`
**Deployment**: VM 120 (openclaw) at 192.168.2.120
**Ports**:
- 18789 (Gateway WebSocket + UI)
- 18790 (Bridge)
- 1455 (OAuth)
**Description**: Multi-platform AI chatbot gateway bridging messaging platforms (Discord, Telegram, Slack, WhatsApp) with LLM providers (Anthropic, OpenAI, Ollama)
**Image**: ghcr.io/openclaw/openclaw:2026.2.1
**Key Features**:
- Multi-provider LLM support (Anthropic, OpenAI, Ollama)
- Multi-platform messaging integration
- WebSocket gateway with web UI
- Pairing-based DM security policy
- Hardened container (cap_drop ALL, non-root, read-only filesystem)
**Security Note**: Version must be >= 2026.2.1 (CVE-2026-25253 patch). All ports bound to localhost only; access via Nginx Proxy Manager reverse proxy at openclaw.apophisnetworking.net.
**Deployment**:
```bash
cd openclaw
cp .env.example .env
# Edit .env: add GATEWAY_TOKEN (openssl rand -hex 32) and at least one LLM API key
docker compose up -d
```
**Complete Documentation**: See `services/openclaw/README.md`
---
## General Deployment Instructions
### Prerequisites
@@ -413,6 +446,10 @@ docker compose down -v
```
services/
├── README.md # This file
├── openclaw/
│ ├── docker-compose.yml # OpenClaw main configuration
│ ├── docker-compose.override.yml # Security hardening overlay
│ └── .env.example # Environment variable template
├── bytestash/
│ ├── docker-compose.yaml
│ └── .gitkeep

View File

@@ -0,0 +1,35 @@
# OpenClaw Configuration
# Copy to .env and fill in values: cp .env.example .env
# IMPORTANT: Never commit .env to git
# =============================================================================
# OpenClaw Version (must be >= 2026.2.1 due to CVE-2026-25253)
# =============================================================================
OPENCLAW_VERSION=2026.2.1
# =============================================================================
# Gateway Authentication
# Generate with: openssl rand -hex 32
# =============================================================================
GATEWAY_TOKEN=
# =============================================================================
# LLM Provider API Keys (configure at least one)
# =============================================================================
ANTHROPIC_API_KEY=
OPENAI_API_KEY=
OLLAMA_BASE_URL=http://192.168.1.81:11434
# =============================================================================
# Messaging Platform Tokens (configure as needed)
# =============================================================================
DISCORD_TOKEN=
TELEGRAM_TOKEN=
SLACK_TOKEN=
WHATSAPP_TOKEN=
# =============================================================================
# Application Settings
# =============================================================================
LOG_LEVEL=info
DM_POLICY=pairing

View File

@@ -0,0 +1,241 @@
# OpenClaw - Getting Started
This guide picks up after the base deployment on VM 120 is complete. It walks through configuring LLM providers, messaging platforms, reverse proxy, remote access, and monitoring.
## Prerequisites
Before proceeding, confirm the following are in place:
- VM 120 running at `192.168.2.120` (cloned from template 107)
- Docker and Docker Compose installed
- OpenClaw container deployed and healthy (`docker ps --filter name=openclaw` shows `healthy`)
- `.env` file created from `.env.example` with `GATEWAY_TOKEN` populated
- Data directories exist at `/opt/openclaw/{data,sessions,logs}` owned by `1001:1001`
If any of the above are missing, refer to the Deployment section in `/home/jramos/homelab/services/openclaw/README.md`.
---
## Step 1: Configure an LLM Provider
The bot will not respond to messages until at least one LLM provider is configured.
SSH to VM 120 and edit the environment file:
```bash
ssh jramos@192.168.2.120
sudo nano /opt/openclaw/.env
```
Set one or more of the following:
| Variable | Notes |
|----------|-------|
| `ANTHROPIC_API_KEY` | Anthropic API key from https://console.anthropic.com/ |
| `OPENAI_API_KEY` | OpenAI API key from https://platform.openai.com/api-keys |
| `OLLAMA_BASE_URL` | Pre-configured to `http://192.168.1.81:11434` (local Ollama instance) |
If you are using the local Ollama instance, no changes are needed -- the default `.env.example` already points to `http://192.168.1.81:11434`. Verify Ollama is reachable from VM 120:
```bash
curl -sf http://192.168.1.81:11434/api/tags | head -5
```
After editing, restart the container:
```bash
cd /opt/openclaw && sudo docker compose down && sudo docker compose up -d
```
Verify the provider is loaded:
```bash
sudo docker exec openclaw env | grep -E 'ANTHROPIC|OPENAI|OLLAMA'
```
---
## Step 2: Configure Messaging Platforms (Optional)
Add platform tokens to `/opt/openclaw/.env` as needed. Each platform requires its own bot/app registration.
### Discord
1. Go to https://discord.com/developers/applications and create a new application.
2. Navigate to **Bot** > **Add Bot**. Copy the bot token.
3. Under **Privileged Gateway Intents**, enable **Message Content Intent**.
4. Set `DISCORD_TOKEN=<your-token>` in `.env`.
5. Invite the bot to your server using the OAuth2 URL Generator (scopes: `bot`, permissions: `Send Messages`, `Read Message History`).
### Telegram
1. Message [@BotFather](https://t.me/BotFather) on Telegram and run `/newbot`.
2. Follow the prompts to name your bot. Copy the token provided.
3. Set `TELEGRAM_TOKEN=<your-token>` in `.env`.
### Slack
1. Go to https://api.slack.com/apps and click **Create New App** > **From scratch**.
2. Under **OAuth & Permissions**, add bot scopes: `chat:write`, `channels:history`, `im:history`.
3. Install the app to your workspace and copy the Bot User OAuth Token.
4. Set `SLACK_TOKEN=xoxb-<your-token>` in `.env`.
### WhatsApp
1. Set up a WhatsApp Business API account via https://developers.facebook.com/.
2. Configure a webhook URL pointing to `https://openclaw.apophisnetworking.net` (requires Step 3 first).
3. Set `WHATSAPP_TOKEN=<your-token>` in `.env`.
After adding any tokens, restart the container:
```bash
cd /opt/openclaw && sudo docker compose down && sudo docker compose up -d
```
Confirm platform connections in the logs:
```bash
sudo docker logs openclaw 2>&1 | grep -iE 'connect|discord|telegram|slack|whatsapp'
```
---
## Step 3: Set Up Reverse Proxy (NPM)
OpenClaw binds all ports to `127.0.0.1`, so a reverse proxy is required for external access.
1. Access Nginx Proxy Manager at **http://192.168.2.101:81**.
2. Click **Proxy Hosts** > **Add Proxy Host**.
3. Configure:
| Field | Value |
|-------|-------|
| **Domain Names** | `openclaw.apophisnetworking.net` |
| **Scheme** | `http` |
| **Forward Hostname/IP** | `192.168.2.120` |
| **Forward Port** | `18789` |
| **Websockets Support** | Enabled (required -- gateway uses WebSockets) |
4. Under the **SSL** tab:
- Select **Request a new SSL Certificate** via Let's Encrypt.
- Enable **Force SSL** and **HTTP/2 Support**.
5. (Optional) To add TinyAuth protection, go to the **Advanced** tab and paste the `auth_request` configuration block documented in `/home/jramos/homelab/services/tinyauth/README.md` (Nginx Proxy Manager Configuration section), adjusting the `proxy_pass` target to your TinyAuth instance.
6. Save and verify:
```bash
curl -sf https://openclaw.apophisnetworking.net
```
---
## Step 4: Add Twingate Resource
To enable zero-trust remote access to VM 120:
1. Log into the Twingate Admin Console.
2. Navigate to **Resources** > **Add Resource**.
3. Add a resource with address `192.168.2.120`.
4. Add the following ports:
- `18789` (Gateway WS+UI)
- `18790` (Bridge)
- `1455` (OAuth)
5. Assign the resource to the appropriate user groups.
---
## Step 5: Deploy Prometheus Config to VM 101
Add the OpenClaw host to Prometheus so node-level metrics appear in Grafana.
1. Access VM 101 (monitoring-docker) console via the Proxmox web UI at `https://192.168.2.100:8006`.
2. Edit the Prometheus configuration:
```bash
sudo nano /opt/prometheus/prometheus.yml
```
3. Add the following scrape job under `scrape_configs`:
```yaml
- job_name: 'openclaw-node'
static_configs:
- targets: ['192.168.2.120:9100']
labels:
instance: 'openclaw'
vm_id: '120'
```
4. Restart the Prometheus container:
```bash
cd /opt/prometheus && sudo docker compose restart prometheus
```
5. Verify the target is up at **http://192.168.2.114:9090/targets** -- look for `openclaw-node` with state `UP`.
---
## Step 6: Verify Everything Works
Run through this checklist from VM 120 (unless noted otherwise):
```bash
# Container healthy
sudo docker ps --filter name=openclaw
# STATUS column should show "healthy"
# Gateway responding
curl -sf http://localhost:18789/health
# Should return JSON with 200 status
# Node exporter serving metrics
curl -sf http://localhost:9100/metrics | head -5
# Should return Prometheus metric lines
# Version check
sudo docker logs openclaw 2>&1 | head -10
# Confirm version >= 2026.2.1
# NPM proxy (from any machine with DNS access, after Step 3)
curl -sf https://openclaw.apophisnetworking.net
# Should return the web UI or a redirect to login
# Prometheus target (after Step 5)
# Open http://192.168.2.114:9090/targets in a browser
# openclaw-node should show state UP
```
---
## Common Operations
```bash
# View logs (live)
sudo docker logs -f openclaw
# Restart
cd /opt/openclaw && sudo docker compose restart
# Update to a new version
cd /opt/openclaw && sudo docker compose pull && sudo docker compose up -d
# Backup application data
sudo -u openclaw /opt/openclaw/backup.sh
```
---
## Security Reminders
- **Never commit `.env` to git.** It is excluded via `.gitignore`, but verify before pushing.
- **Keep version >= 2026.2.1.** CVE-2026-25253 (1-click RCE, CVSS 8.8) is patched in this release. Do not downgrade.
- **Only install vetted skills.** Use the `skill-vetter` tool to audit any skill before installation. Avoid skills that require shell access, computer-use, or deployment capabilities.
- **Keep `DM_POLICY=pairing`.** This prevents unauthorized users from interacting with the bot via direct messages.
- **File permissions.** The `.env` file must be `chmod 600` (owner-only read/write).
---
**Maintained by**: Homelab Infrastructure Team
**Last Updated**: 2026-02-03

367
services/openclaw/README.md Normal file
View File

@@ -0,0 +1,367 @@
# OpenClaw - Multi-Platform AI Chatbot Gateway
## Overview
OpenClaw (formerly Moltbot/Clawdbot) is a multi-platform AI chatbot gateway deployed as a Docker service on VM 120. It bridges messaging platforms with LLM providers through a WebSocket gateway, allowing unified conversational AI access across multiple channels from a single deployment.
**Key Benefits**:
- Multi-platform messaging support (Discord, Telegram, Slack, WhatsApp)
- Multi-provider LLM backend (Anthropic, OpenAI, Ollama)
- WebSocket gateway with integrated web UI
- Secure pairing-based DM policy (prevents unauthorized direct messages)
- OAuth integration for platform authentication
## Infrastructure Details
| Property | Value |
|----------|-------|
| **VM** | 120 (QEMU/KVM on Vault ZFS) |
| **IP Address** | 192.168.2.120 |
| **Ports** | 18789 (Gateway WS+UI), 18790 (Bridge), 1455 (OAuth) |
| **Domain** | openclaw.apophisnetworking.net |
| **Docker Image** | ghcr.io/openclaw/openclaw:2026.2.1 |
| **Template** | Cloned from 107 (ubuntu-docker) |
| **Resources** | 4 vCPUs, 16 GB RAM, 50 GB disk |
| **Deployment Date** | 2026-02-03 |
## Integration Architecture
```
+-------------------------------------+
| INTERNET |
+------------------+------------------+
|
+----------------------+----------------------+
| | |
v v v
+-----------+ +-----------+ +-----------+
| Discord | | Telegram | | Slack / |
| Gateway | | Bot API | | WhatsApp |
+-----+-----+ +-----+-----+ +-----+-----+
| | |
+----------------------+----------------------+
|
| Tokens
v
+-------------------------------------------------------------------------------+
| CT 102 - Nginx Proxy Manager (192.168.2.101) |
| +-------------------------------------------------------------------------+ |
| | SSL Termination, Reverse Proxy, WebSocket Upgrade, TinyAuth | |
| +-------------------------------+-----------------------------------------+ |
+----------------------------------+--------------------------------------------+
|
v
+-------------------------------+
| VM 120 - OpenClaw |
| (192.168.2.120) |
| |
| :18789 Gateway (WS + UI) |
| :18790 Bridge |
| :1455 OAuth |
| |
| +-------------------------+ |
| | LLM Providers | |
| | - Anthropic API | |
| | - OpenAI API | |
| | - Ollama (local) | |
| +-------------------------+ |
+-------------------------------+
```
### Request Flow
1. **User sends a message** on a connected platform (Discord, Telegram, Slack, WhatsApp)
2. **Platform delivers** the message to OpenClaw via bot tokens and webhooks
3. **DM policy check**: If `DM_POLICY=pairing`, the user must be paired before interaction is allowed
4. **OpenClaw routes** the message to the configured LLM provider
5. **LLM responds** and OpenClaw relays the response back to the originating platform
6. **Web UI access**: Users can also interact directly via the gateway at `https://openclaw.apophisnetworking.net`
## Security Considerations
**CRITICAL**: CVE-2026-25253 (1-click RCE, CVSS 8.8) is patched in v2026.1.29. The deployed version MUST be >= 2026.2.1. Do not downgrade below this version under any circumstances.
### Hardening Measures
**Network**:
- All ports bound to `127.0.0.1` (localhost only); reverse proxy required for external access
- UFW firewall: default deny-all inbound, whitelist `192.168.2.0/24` and `192.168.1.91`
- Twingate zero-trust access (no direct internet exposure to management interfaces)
**Docker**:
- `cap_drop: ALL` -- no Linux capabilities granted
- `security_opt: no-new-privileges:true` -- prevents privilege escalation
- `read_only: true` -- read-only root filesystem (writable tmpfs at `/tmp`)
- Non-root user (`1001:1001`)
- No Docker socket mounted
- Resource limits enforced (3.5 CPUs, 14 GB memory)
**Host**:
- fail2ban on SSH (3 retries before ban)
- `unattended-upgrades` enabled for automatic security patches
- `.env` file permissions set to `chmod 600` (owner-only read/write)
- Secrets never committed to git
**Application**:
- `DM_POLICY=pairing` (secure default; users must be explicitly paired)
- `NODE_ENV=production`
- Log rotation via Docker json-file driver (50 MB x 5 files)
### Skills Policy
Only install vetted, read-only skills from the curated skills list. Use the `skill-vetter` tool to audit any new skill before installation. Avoid skills that require:
- Computer-use or screen interaction
- Shell/bash command execution
- Deployment or infrastructure modification capabilities
## Configuration
### Docker Compose
The deployment uses two Compose files:
**File**: `/home/jramos/homelab/services/openclaw/docker-compose.yml`
Defines the core service including image, ports (all bound to `127.0.0.1`), volumes, environment variables, healthcheck, and logging configuration.
**File**: `/home/jramos/homelab/services/openclaw/docker-compose.override.yml`
Applies security hardening: drops all capabilities, enables `no-new-privileges`, enforces a read-only filesystem, sets the non-root user, and configures resource limits.
Docker Compose automatically merges the override file when running `docker compose up`.
### Environment Variables
**File**: `/home/jramos/homelab/services/openclaw/.env` (create from `.env.example`)
```bash
cp .env.example .env
chmod 600 .env
```
| Variable Group | Variables | Notes |
|----------------|-----------|-------|
| **Version** | `OPENCLAW_VERSION` | Must be >= `2026.2.1` (CVE-2026-25253) |
| **Gateway Auth** | `GATEWAY_TOKEN` | Required. Generate with `openssl rand -hex 32` |
| **LLM Providers** | `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `OLLAMA_BASE_URL` | Configure at least one provider |
| **Messaging** | `DISCORD_TOKEN`, `TELEGRAM_TOKEN`, `SLACK_TOKEN`, `WHATSAPP_TOKEN` | Configure per platform as needed |
| **App Settings** | `LOG_LEVEL`, `DM_POLICY` | Defaults: `info`, `pairing` |
**Critical Notes**:
- `GATEWAY_TOKEN` is mandatory -- the service will not start without it
- At least one LLM provider key must be configured for the bot to respond
- `DM_POLICY=pairing` is the secure default; do not change to `open` in production
- The `.env` file must never be committed to git (it is excluded via `.gitignore`)
### Nginx Proxy Manager Configuration
**Proxy Host**: `openclaw.apophisnetworking.net`
- **Scheme**: http
- **Forward Hostname/IP**: 192.168.2.120
- **Forward Port**: 18789
- **WebSocket Support**: Enabled (required for gateway functionality)
- **Force SSL**: Enabled
- **HTTP/2 Support**: Enabled
- **SSL Certificate**: Let's Encrypt (auto-renewed)
**TinyAuth Protection**: Apply the same `auth_request` pattern used for other protected services. See `/home/jramos/homelab/services/tinyauth/README.md` for the Nginx advanced configuration template.
## Deployment
### Quick Start
1. **Create environment file**:
```bash
cd /home/jramos/homelab/services/openclaw
cp .env.example .env
chmod 600 .env
```
2. **Generate gateway token**:
```bash
GATEWAY_TOKEN=$(openssl rand -hex 32)
sed -i "s/^GATEWAY_TOKEN=$/GATEWAY_TOKEN=${GATEWAY_TOKEN}/" .env
```
3. **Configure at least one LLM provider** by editing `.env` and adding an API key (e.g., `ANTHROPIC_API_KEY`).
4. **Create data directories** on VM 120:
```bash
sudo mkdir -p /opt/openclaw/{data,sessions,logs,config}
sudo chown -R 1001:1001 /opt/openclaw
```
5. **Start the service**:
```bash
docker compose up -d
```
6. **Verify health**:
```bash
curl -f http://127.0.0.1:18789/health
# Expected: HTTP 200 with JSON status
```
### Volume Mounts
| Host Path | Container Path | Purpose |
|-----------|---------------|---------|
| `/opt/openclaw/data` | `/app/data` | Persistent application data |
| `/opt/openclaw/sessions` | `/app/sessions` | User session storage |
| `/opt/openclaw/logs` | `/app/logs` | Application logs |
## Monitoring
- **Prometheus**: Scrapes `node_exporter` at `192.168.2.120:9100` for host-level metrics
- **Grafana**: VM resource utilization dashboards available at `http://192.168.2.114:3000`
- **Healthcheck**: Docker built-in healthcheck polls `http://localhost:18789/health` every 30 seconds
- **Logs**: Structured JSON logs with rotation (50 MB x 5 files)
## Backup
### Proxmox Backup Server
- **Schedule**: Daily at 02:00
- **Mode**: Snapshot
- **Compression**: zstd
- **Storage**: PBS-Backups
### Application-Level Backup
```bash
# Weekly tar of application data (run on VM 120)
tar czf /tmp/openclaw-backup-$(date +%Y%m%d).tar.gz \
/opt/openclaw/data \
/opt/openclaw/sessions \
/opt/openclaw/config
# Backup .env file separately (contains secrets)
cp /home/jramos/homelab/services/openclaw/.env \
/home/jramos/homelab/services/openclaw/.env.backup-$(date +%Y%m%d)
```
## Maintenance
### Logs
```bash
# Live container logs
docker logs -f openclaw
# Last 100 lines
docker logs --tail 100 openclaw
# Filter for errors
docker logs openclaw 2>&1 | grep -i error
# Application logs on disk
ls -la /opt/openclaw/logs/
```
### Health Check
```bash
# Container status
docker ps | grep openclaw
# Health endpoint
curl -f http://127.0.0.1:18789/health
# Check resource usage
docker stats openclaw --no-stream
```
### Restart
```bash
cd /home/jramos/homelab/services/openclaw
docker compose restart
```
### Updates
```bash
cd /home/jramos/homelab/services/openclaw
# Update version in .env
# Edit OPENCLAW_VERSION to the new version (must be >= 2026.2.1)
# Pull and recreate
docker compose pull
docker compose down
docker compose up -d
# Verify health after update
curl -f http://127.0.0.1:18789/health
```
**Before updating**: Check the OpenClaw release notes for breaking changes. Always verify the new version is not affected by known CVEs.
## Troubleshooting
### Symptoms: Service fails to start
**Check**:
1. `GATEWAY_TOKEN` is set in `.env`: `grep GATEWAY_TOKEN .env`
2. Data directories exist and are owned by `1001:1001`: `ls -la /opt/openclaw/`
3. Port conflicts: `ss -tlnp | grep -E '18789|18790|1455'`
**Commands**:
```bash
docker compose logs openclaw
docker inspect openclaw | grep -A 5 "State"
```
### Symptoms: Bot does not respond to messages
**Check**:
1. At least one LLM provider key is configured in `.env`
2. Platform tokens are valid and not expired
3. Health endpoint returns 200: `curl -f http://127.0.0.1:18789/health`
4. Container is healthy: `docker ps | grep openclaw`
**Commands**:
```bash
# Check which providers are configured
docker exec openclaw env | grep -E 'ANTHROPIC|OPENAI|OLLAMA'
# Check platform connections
docker logs openclaw 2>&1 | grep -iE 'connect|discord|telegram|slack|whatsapp'
```
### Symptoms: WebSocket connection fails through reverse proxy
**Check**:
1. NPM proxy host has WebSocket support enabled
2. SSL certificate is valid for `openclaw.apophisnetworking.net`
3. Gateway port is accessible from NPM: `curl -f http://192.168.2.120:18789/health` (from CT 102)
**Fix**: Ensure WebSocket upgrade headers are passed in NPM configuration.
### Symptoms: "Unauthorized" or "Pairing required" errors
**Check**:
1. `DM_POLICY` setting in `.env` (default is `pairing`)
2. User has been paired via the web UI or admin commands
3. `GATEWAY_TOKEN` matches between client and server
### Symptoms: High memory or CPU usage
**Check**:
1. Resource limits are applied: `docker inspect openclaw | grep -A 10 "Resources"`
2. Log volume is not excessive: `du -sh /opt/openclaw/logs/`
3. Number of active sessions: check `/opt/openclaw/sessions/`
**Commands**:
```bash
docker stats openclaw --no-stream
docker compose logs --tail 50 openclaw
```
## References
- **OpenClaw GitHub**: https://github.com/openclaw/openclaw
- **CVE-2026-25253 Advisory**: https://github.com/openclaw/openclaw/security/advisories/CVE-2026-25253
- **TinyAuth Integration**: `/home/jramos/homelab/services/tinyauth/README.md`
- **Nginx Proxy Manager**: https://nginxproxymanager.com/
- **Docker Compose Security**: https://docs.docker.com/compose/compose-file/05-services/#security_opt
---
**Maintained by**: Homelab Infrastructure Team
**Last Updated**: 2026-02-03
**Status**: Operational - Deployed with CVE-2026-25253 patched (v2026.2.1)

View File

@@ -0,0 +1,20 @@
services:
openclaw:
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp:size=256m
- /.openclaw:size=64m
privileged: false
user: "1001:1001"
deploy:
resources:
limits:
cpus: "3.5"
memory: 14G
reservations:
cpus: "0.5"
memory: 512M

View File

@@ -0,0 +1,42 @@
services:
openclaw:
container_name: openclaw
image: ghcr.io/openclaw/openclaw:${OPENCLAW_VERSION:-2026.2.1}
restart: unless-stopped
ports:
- "127.0.0.1:18789:18789" # Gateway WS+UI (localhost only, use reverse proxy)
- "127.0.0.1:18790:18790" # Bridge
- "127.0.0.1:1455:1455" # OAuth
volumes:
- /opt/openclaw/data:/app/data
- /opt/openclaw/sessions:/app/sessions
- /opt/openclaw/logs:/app/logs
command: ["node", "openclaw.mjs", "gateway", "--allow-unconfigured"]
env_file:
- .env
environment:
- NODE_ENV=production
- GATEWAY_PORT=18789
- BRIDGE_PORT=18790
- OAUTH_PORT=1455
- LOG_LEVEL=${LOG_LEVEL:-info}
- DM_POLICY=${DM_POLICY:-pairing}
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
- OPENAI_API_KEY=${OPENAI_API_KEY:-}
- OLLAMA_BASE_URL=${OLLAMA_BASE_URL:-}
- DISCORD_TOKEN=${DISCORD_TOKEN:-}
- TELEGRAM_TOKEN=${TELEGRAM_TOKEN:-}
- SLACK_TOKEN=${SLACK_TOKEN:-}
- WHATSAPP_TOKEN=${WHATSAPP_TOKEN:-}
- OPENCLAW_GATEWAY_TOKEN=${GATEWAY_TOKEN}
healthcheck:
test: ["CMD", "node", "-e", "require('http').get('http://localhost:18789/health', r => process.exit(r.statusCode === 200 ? 0 : 1)).on('error', () => process.exit(1))"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
logging:
driver: json-file
options:
max-size: "50m"
max-file: "5"