Traefik + OpenClaw + ClawMetry (Internal Setup)
This guide shows how to run OpenClaw and ClawMetry together on a Raspberry Pi or home-lab machine using Traefik as a reverse proxy. Both services are served from a single local hostname on HTTPS, protected by a login password:
| URL | Service |
|---|---|
https://openclaw.local | OpenClaw gateway (Control UI) |
https://openclaw.local/stats | ClawMetry dashboard |
Internal use only. Traefik generates a self-signed TLS certificate automatically — no public IP, no domain registration, and no Let's Encrypt required. Your browser will show a security warning on first visit; add a certificate exception once and you will not see it again.
What you'll build
LAN
│
▼
Traefik (port 80 → 443 redirect, HTTPS with self-signed cert)
│ — password protected (HTTP Basic Auth) —
├─ openclaw.local ──▶ OpenClaw gateway (port 18789)
└─ openclaw.local/stats ──▶ ClawMetry dashboard (port 8900)
Both services share ~/.openclaw (read-only for ClawMetry)Prerequisites
- A Linux machine on your local network (e.g. a Raspberry Pi)
- Docker Engine ≥ 24 and Docker Compose v2
htpasswd(fromapache2-utils) or Docker (to generate the password hash)
Step 1 — Run the OpenClaw onboarding wizard
ClawMetry reads data written by the OpenClaw gateway. Before using the Traefik compose file you need to configure OpenClaw with its interactive setup wizard.
Clone the OpenClaw repository and enter the directory:
bashgit clone https://github.com/openclaw/openclaw cd openclawSet the image tag and run the wizard:
bashexport OPENCLAW_IMAGE="alpine/openclaw:latest" ./docker-setup.shThe wizard asks you to:
- Choose an AI model (e.g. OpenAI Codex via OAuth)
- Select a messaging channel (Telegram, WhatsApp, Discord, …)
- Generate and save a gateway token
Once setup is complete, stop the wizard-started containers. You will start them again via the Traefik compose file:
bashdocker compose downThe wizard has written your configuration to
~/.openclaw/. Confirm it exists:bashls ~/.openclaw
Troubleshooting: If the wizard shows no models with
latest, switch to themaintag and rerun:bashexport OPENCLAW_IMAGE="alpine/openclaw:main" ./docker-setup.sh
Step 2 — Create the project directory
Create a dedicated folder for the Traefik setup and change into it:
mkdir ~/clawmetry-traefik && cd ~/clawmetry-traefikStep 3 — Generate a password hash
Traefik uses bcrypt-hashed credentials for HTTP Basic Auth. Generate a hash for your chosen username and password:
Option A — Using Docker (no extra packages needed):
docker run --rm httpd:alpine htpasswd -nB adminOption B — Using htpasswd directly:
# Install if needed: sudo apt install apache2-utils
htpasswd -nB adminBoth commands prompt for a password and print a line like:
admin:$2y$05$someLongHashStringHere...Important: Every
$in the hash must be escaped as$$when placed in your.envfile (Docker Compose variable substitution). Example:$2y$05$abc→$$2y$$05$$abcin.env
Copy the output and note it for the next step.
Step 4 — Make the hostname reachable on the network
Traefik routes requests by hostname. You have two options:
Option A — Bonjour / mDNS (recommended for Raspberry Pi)
If you set the Pi's hostname to openclaw, other devices on the same local network (macOS, modern Linux, Windows 10/11 with Bonjour installed) will automatically resolve openclaw.local — no manual /etc/hosts editing required.
Set the Pi's hostname:
bashsudo hostnamectl set-hostname openclawMake sure
avahi-daemonis installed and running (it is enabled by default on Raspberry Pi OS):bashsudo apt install avahi-daemon # only needed if not already installed sudo systemctl enable --now avahi-daemonAfter a few seconds, every device on the same LAN can reach the Pi at
openclaw.local.
Windows note: mDNS support is built into Windows 10 (1903+) and Windows 11. If
openclaw.localdoes not resolve, install Bonjour Print Services from Apple.
Option B — Static /etc/hosts entry
If you prefer not to change the Pi's hostname, add one line to /etc/hosts on every machine that needs access (replace 192.168.1.100 with your Pi's actual LAN IP address):
192.168.1.100 openclaw.localOn Linux and macOS: sudo nano /etc/hosts
On Windows: edit C:\Windows\System32\drivers\etc\hosts as Administrator.
You can choose a different hostname — just keep it in sync with DOMAIN in your .env file.
Step 5 — Create the .env file
Copy the example file from this repository:
cp /path/to/clawmetry-docker/.env.traefik.example .envFill in your values (paste the escaped hash from Step 3 into TRAEFIK_BASICAUTH_USERS):
# Local hostname — must match the entry you added to /etc/hosts
DOMAIN=openclaw.local
# Basic auth: paste your escaped bcrypt hash here ($ replaced with $$)
TRAEFIK_BASICAUTH_USERS=admin:$$2y$$05$$yourHashHere...
# Optional: your display name in the ClawMetry Flow tab
OPENCLAW_USER=Tip: Add
.envto your.gitignoreto avoid accidentally committing it.
Step 6 — Create the docker-compose.yml
Copy docker-compose.traefik.yml from this repository and rename it:
cp /path/to/clawmetry-docker/docker-compose.traefik.yml docker-compose.ymlOr create it with this content:
services:
# ─── Traefik reverse proxy ──────────────────────────────────────────────
traefik:
image: traefik:v3.0
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
# Redirect HTTP → HTTPS
- "--entrypoints.web.address=:80"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
# HTTPS with auto-generated self-signed certificate (no certresolver)
- "--entrypoints.websecure.address=:443"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
labels:
# Enable label scanning on Traefik itself to define the shared auth middleware
- "traefik.enable=true"
# Shared basic-auth middleware — use $$ instead of $ in the hash (Compose escaping)
- "traefik.http.middlewares.auth.basicauth.users=${TRAEFIK_BASICAUTH_USERS}"
restart: unless-stopped
networks:
- proxy
# ─── OpenClaw gateway ───────────────────────────────────────────────────
openclaw-gateway:
image: alpine/openclaw:latest
user: "1000:1000"
volumes:
- ~/.openclaw:/home/node/.openclaw
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
- "traefik.http.routers.openclaw.rule=Host(`${DOMAIN}`)"
- "traefik.http.routers.openclaw.entrypoints=websecure"
- "traefik.http.routers.openclaw.tls=true"
- "traefik.http.routers.openclaw.middlewares=auth@docker"
- "traefik.http.services.openclaw.loadbalancer.server.port=18789"
restart: unless-stopped
networks:
- proxy
- internal
deploy:
resources:
limits:
cpus: "1.0"
memory: 1G
# ─── ClawMetry dashboard ────────────────────────────────────────────────
clawmetry:
image: stritti/clawmetry:latest
volumes:
- ~/.openclaw:/home/clawmetry/.openclaw:ro
environment:
OPENCLAW_DATA_DIR: /home/clawmetry/.openclaw
OPENCLAW_USER: "${OPENCLAW_USER:-}"
# Tells ClawMetry it is mounted at /stats (for correct URL generation)
SCRIPT_NAME: "/stats"
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
# PathPrefix rule has higher priority than the bare Host rule above
- "traefik.http.routers.clawmetry.rule=Host(`${DOMAIN}`) && PathPrefix(`/stats`)"
- "traefik.http.routers.clawmetry.entrypoints=websecure"
- "traefik.http.routers.clawmetry.tls=true"
# Strip /stats before forwarding to ClawMetry
- "traefik.http.middlewares.stats-strip.stripprefix.prefixes=/stats"
# Apply the shared basic-auth middleware (defined on the traefik service)
- "traefik.http.routers.clawmetry.middlewares=auth@docker,stats-strip"
- "traefik.http.services.clawmetry.loadbalancer.server.port=8900"
restart: unless-stopped
networks:
- proxy
- internal
networks:
proxy:
internal:
internal: trueStep 7 — Fix file permissions
Both containers run as user 1000. If your ~/.openclaw directory was created by a different user, fix the ownership before starting the stack:
sudo chown -R 1000:1000 ~/.openclawStep 8 — Start the stack
docker compose up -dCheck that all three containers are running:
docker compose psExpected output:
NAME IMAGE STATUS
clawmetry-traefik-traefik-1 traefik:v3.0 Up
clawmetry-traefik-openclaw-gateway-1 alpine/openclaw:latest Up
clawmetry-traefik-clawmetry-1 stritti/clawmetry:latest UpStep 9 — Accept the self-signed certificate
Open https://openclaw.local in your browser. Because Traefik uses a self-signed certificate, your browser will show a security warning ("Your connection is not private" or similar).
Click Advanced → Proceed (Chrome) or Accept the Risk and Continue (Firefox) to add a permanent exception. You only need to do this once per browser.
Step 10 — Connect OpenClaw to the gateway
Fetch the Control UI URL and paste your gateway token into Settings → Token:
docker compose exec openclaw-gateway node openclaw.mjs dashboard --no-openOpen the printed URL in your browser. When prompted by your browser (HTTP Basic Auth from Traefik), enter the username and password you set in Step 3. Once authenticated, you'll reach the OpenClaw Control UI — enter the gateway token from Step 1 in Settings → Token.
Step 11 — Open the ClawMetry dashboard
Navigate to https://openclaw.local/stats (replace openclaw.local with the DOMAIN you set).
Your browser will show the same login prompt — enter the username and password from Step 3.
The ClawMetry dashboard shows live metrics, session recordings, and logs streamed from the shared ~/.openclaw directory.
Security considerations
| Topic | Recommendation |
|---|---|
| Password protection | Both services are protected by Traefik HTTP Basic Auth — always set a strong password. |
| Self-signed certificate | The TLS certificate is self-signed and will trigger a browser warning. Add an exception once. Never expose this setup on a public network. |
| Non-root containers | Both ClawMetry and OpenClaw run as user 1000 — never add privileged: true. |
| Read-only volume | ClawMetry mounts ~/.openclaw with :ro — it cannot modify agent data. |
| Internal network | The internal Docker network is used only for inter-container communication and is not published directly on the host; in this setup, services are exposed to your LAN only through Traefik’s ports. |
| Direct port exposure | Never bind ports 8900 or 18789 directly on the host — always route through Traefik. |
| Resource limits | The deploy.resources.limits block prevents a runaway agent from consuming all available CPU and memory. |
| Traefik dashboard | The Traefik API/dashboard is disabled by default in this configuration. Enable it only temporarily and protect it with basic auth if needed. |
Useful commands
# View logs for all services
docker compose logs -f
# View ClawMetry logs only
docker compose logs -f clawmetry
# Restart a single service
docker compose restart clawmetry
# Stop the stack (containers are removed, bind-mounted data like ~/.openclaw is preserved)
docker compose down
# Stop the stack and remove Docker-managed (named/anonymous) volumes.
# NOTE: This does NOT delete your ~/.openclaw directory (bind-mount data); remove it manually if desired.
docker compose down -vNext steps
- See the Configuration reference for all supported environment variables.
- See Docker Compose for a simpler single-service setup without Traefik.