OpenClaw with VeilNet

Run the OpenClaw personal AI gateway behind VeilNet (beta integration—not fully tested) for private remote access to the Control UI and CLI.

Beta This guide is experimental. VeilNet has not fully tested this layout with every OpenClaw version, channel, or upgrade path. Treat it as a starting point; rely on OpenClaw’s documentation for product behavior, security, and supported install flows.

Prerequisites

  • Docker and Docker Compose installed
  • VeilNet registration token and Guardian access
  • At least one Conflux taint (required so this node can communicate with others in your realm)
  • Sufficient disk and RAM (OpenClaw’s image build path needs ~2 GB RAM; using the pre-built image below avoids local builds)
  • Model provider credentials (API keys or OAuth) as required by OpenClaw—see Getting started

Overview

OpenClaw is an open-source personal AI assistant: a Gateway control plane (WebSocket, Control UI, channels, tools) you run yourself. The upstream project uses stable, beta, and dev release channels; this VeilNet guide is still beta on our side and has not been validated end-to-end for every combination of OpenClaw version and feature. Official install paths include npm and Docker; full Docker details are in the OpenClaw Docker guide.

This guide places the OpenClaw Gateway in the same network namespace as VeilNet Conflux (like the other app guides here), so:

  • The gateway listens on the host VeilNet stack (e.g. Control UI on port 18789).
  • You reach OpenClaw from other VeilNet peers via http://<veilnet-ip>:18789/ without publishing the service to the public internet.

Pre-built images: ghcr.io/openclaw/openclaw (tags such as latest or dated releases).

Step 1: Create Docker Compose configuration

Create a docker-compose.yml file:

services:
  veilnet-conflux:
    container_name: veilnet-conflux
    restart: unless-stopped
    env_file:
      - .env
    image: veilnet/conflux:Beta-v1.0.8
    pull_policy: always
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/net/tun
    network_mode: host

  openclaw-gateway:
    image: ${OPENCLAW_IMAGE:-ghcr.io/openclaw/openclaw:latest}
    pull_policy: always
    network_mode: "container:veilnet-conflux"
    depends_on:
      - veilnet-conflux
    restart: unless-stopped
    environment:
      HOME: /home/node
      TERM: xterm-256color
      TZ: ${OPENCLAW_TZ:-UTC}
      OPENCLAW_GATEWAY_TOKEN: ${OPENCLAW_GATEWAY_TOKEN:-}
      OPENCLAW_ALLOW_INSECURE_PRIVATE_WS: ${OPENCLAW_ALLOW_INSECURE_PRIVATE_WS:-}
    volumes:
      - ${OPENCLAW_CONFIG_DIR}:/home/node/.openclaw
      - ${OPENCLAW_WORKSPACE_DIR}:/home/node/.openclaw/workspace
    init: true
    command:
      - node
      - dist/index.js
      - gateway
      - --bind
      - ${OPENCLAW_GATEWAY_BIND:-lan}
      - --port
      - "18789"
    healthcheck:
      test:
        [
          "CMD",
          "node",
          "-e",
          "fetch('http://127.0.0.1:18789/healthz').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))",
        ]
      interval: 30s
      timeout: 5s
      retries: 5
      start_period: 20s

  openclaw-cli:
    profiles:
      - cli
    image: ${OPENCLAW_IMAGE:-ghcr.io/openclaw/openclaw:latest}
    pull_policy: always
    network_mode: "service:openclaw-gateway"
    cap_drop:
      - NET_RAW
      - NET_ADMIN
    security_opt:
      - no-new-privileges:true
    environment:
      HOME: /home/node
      TERM: xterm-256color
      TZ: ${OPENCLAW_TZ:-UTC}
      OPENCLAW_GATEWAY_TOKEN: ${OPENCLAW_GATEWAY_TOKEN:-}
      BROWSER: echo
    volumes:
      - ${OPENCLAW_CONFIG_DIR}:/home/node/.openclaw
      - ${OPENCLAW_WORKSPACE_DIR}:/home/node/.openclaw/workspace
    stdin_open: true
    tty: true
    init: true
    entrypoint: ["node", "dist/index.js"]
    depends_on:
      - openclaw-gateway

The cli profile keeps openclaw-cli from starting on a plain docker compose up -d; use it for one-off commands (onboarding, channels, doctor). This mirrors upstream’s split between long-running gateway and CLI containers.

Step 2: Create environment file

Create a .env next to docker-compose.yml:

# VeilNet Conflux (see Docker deployment doc for details)
VEILNET_REGISTRATION_TOKEN=<YOUR_REGISTRATION_TOKEN>
VEILNET_GUARDIAN=<YOUR_GUARDIAN_URL>
VEILNET_CONFLUX_TAG=<YOUR_CONFLUX_TAG>
VEILNET_CONFLUX_TAINTS=<YOUR_TAINTS>
VEILNET_CONFLUX_IP=<YOUR_VEILNET_IP>

# OpenClaw paths on the host (create dirs in Step 3)
OPENCLAW_IMAGE=ghcr.io/openclaw/openclaw:latest
OPENCLAW_CONFIG_DIR=./openclaw-config
OPENCLAW_WORKSPACE_DIR=./openclaw-workspace
OPENCLAW_GATEWAY_BIND=lan
OPENCLAW_TZ=UTC

# Optional: set after onboarding if you use token auth for the Control UI
# OPENCLAW_GATEWAY_TOKEN=<your-secret>

Replace the VeilNet placeholders (same meanings as in the other guides):

  • <YOUR_REGISTRATION_TOKEN>, <YOUR_GUARDIAN_URL>, <YOUR_CONFLUX_TAG>, <YOUR_TAINTS>, <YOUR_VEILNET_IP>
  • Optional: VEILNET_CONFLUX_PORTAL=true for portal mode when you need it; most single-host OpenClaw setups omit it.

Taints and VEILNET_CONFLUX_IP: see Taint-based access control and Docker deployment.

Step 3: Create data directories

mkdir -p openclaw-config openclaw-workspace

The gateway runs as user node (uid 1000) in the image. If you hit permission errors on the bind mounts, fix ownership (see OpenClaw Docker — Permissions):

sudo chown -R 1000:1000 openclaw-config openclaw-workspace

Step 4: Deploy the stack

docker compose up -d

This starts veilnet-conflux and openclaw-gateway only.

Step 5: Onboarding and Control UI

Complete provider auth, workspace, and gateway setup using OpenClaw’s flows. The upstream project recommends openclaw onboard for interactive setup; in Docker, run onboarding through the gateway or CLI container as in Docker install (e.g. setup.sh from the repo, or the documented docker compose run / onboard commands for your image tag).

After the gateway is healthy:

  • Locally: open http://127.0.0.1:18789/ (with OPENCLAW_GATEWAY_BIND=lan and Conflux using host networking, this matches the published port in the container network namespace).
  • Over VeilNet: http://<veilnet-ip>:18789/ from another peer in the same realm (with compatible taints).

Use the shared secret or token from your OpenClaw config (see OpenClaw docs for Control UI and Settings).

One-off CLI examples (after the gateway is up):

docker compose --profile cli run --rm openclaw-cli doctor
docker compose --profile cli run --rm openclaw-cli dashboard --no-open

Channel setup (examples from upstream):

docker compose --profile cli run --rm openclaw-cli channels login

Step 6: Verify

docker compose ps
docker logs veilnet-conflux -f
docker logs openclaw-gateway -f

Health checks:

curl -fsS http://127.0.0.1:18789/healthz

Updating

docker compose pull
docker compose up -d

Follow Updating for OpenClaw-specific notes (openclaw doctor, channels, etc.).

Stopping and removing

docker compose down

To delete OpenClaw data on disk, remove the openclaw-config and openclaw-workspace directories after backup.

FAQ

Why not use OpenClaw’s stock docker-compose.yml alone?

Stock Compose publishes ports on the Docker host. This guide attaches the gateway to Conflux’s namespace so VeilNet addressing and policy match your other workloads. You can still adapt variables and volumes from the official compose file.

Do I need agent sandboxing?

Sandboxing uses additional Docker options (socket mounts, images). See Sandboxing. It is independent of putting the gateway behind VeilNet.

Where is the full CLI reference?

See OpenClaw Docs (gateway, channels, security, models).

Why use NET_ADMIN on Conflux only?

Conflux needs NET_ADMIN for the TUN device; the openclaw-cli service explicitly drops NET_ADMIN and NET_RAW per upstream’s security defaults.

VeilNet • © 2026 All rights reserved