Configuration
Ports and networking#
The ports#
| Port | Service | Default binding |
|---|---|---|
8900 | The dashboard | 127.0.0.1 |
4100 | The enforcement proxy | 127.0.0.1 |
| ephemeral | The daemon's query server | 127.0.0.1, token-authenticated |
18789 | The OpenClaw gateway | Not ClawMetry's — read, not served |
The daemon's query server picks an ephemeral port and advertises it in
~/.clawmetry/local_query.json along with a bearer token and its pid.
Why loopback is the default#
The dashboard renders your agents' transcripts. Those contain whatever your agents read and wrote — source code, API responses, and any secret that ended up in a tool result.
Binding it to a routable interface publishes all of that. It is a deliberate default, not a limitation.
clawmetry --host 127.0.0.1 --port 8900 # default
clawmetry --host 0.0.0.0 --port 8900 # exposed — read the rest of this pageExposing it safely#
The pattern that works: keep ClawMetry on loopback and put an authenticating reverse proxy in front of it.
server {
listen 443 ssl;
server_name clawmetry.internal.example.com;
ssl_certificate /etc/ssl/certs/internal.crt;
ssl_certificate_key /etc/ssl/private/internal.key;
auth_basic "ClawMetry";
auth_basic_user_file /etc/nginx/.htpasswd;
location / {
proxy_pass http://127.0.0.1:8900;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
# Server-Sent Events: no buffering, long timeouts
proxy_buffering off;
proxy_read_timeout 3600s;
}
}The SSE settings matter. The Activity feed, the health stream and the log stream are all Server-Sent Events, and a proxy that buffers them shows you nothing while appearing to work.
API tokens#
For programmatic access, or as a second layer behind a proxy:
export CLAWMETRY_API_TOKENS=<token-a>,<token-b>TOKEN=<token-a>
curl -s -H "Authorization: Bearer $TOKEN" localhost:8900/api/local/sessionsComma-separated so you can rotate: add the new token, move clients over, remove the old one.
Origin checks#
The control endpoints — pause, stop, kill — are origin-checked, because they signal real processes. A reverse proxy must forward the origin correctly or those requests are refused.
That refusal is the correct behaviour: a cross-origin request that can kill your agent's process is exactly the thing the check exists to stop.
OTLP ingestion#
The OTLP receivers accept untrusted data that lands in your store, so they are authenticated. For a local-only setup where the receiver is not reachable off-box:
CLAWMETRY_OTLP_ALLOW_UNAUTH=1 clawmetryDo not set that on anything with a routable address.
Outbound#
In the default local install, nothing. With cloud sync connected:
| Destination | Purpose |
|---|---|
The ingest endpoint (default ingest.clawmetry.com) | Encrypted snapshots |
| PyPI | Update checks, unless disabled |
export CLAWMETRY_OFFLINE=1 # no network calls at all
export CLAWMETRY_AUTO_UPDATE=0 # no update checksThrough a TLS-inspecting corporate proxy:
export CLAWMETRY_CA_BUNDLE=/etc/ssl/certs/corporate-ca.pemDo not reach for CLAWMETRY_TLS_NO_VERIFY except while actively diagnosing a
TLS problem you intend to fix.
Firewall rules#
For a locked-down host, the minimum:
- Inbound: none, if you use the dashboard locally. Port 8900 from your admin
network if you expose it behind a proxy.
- Outbound: 443 to the ingest endpoint, if cloud sync is on. 443 to PyPI, if
updates are on. Nothing otherwise.
Multiple instances#
clawmetry --port 8901 --workspace ~/agents/stagingEach instance needs its own CLAWMETRY_HOME, or they will contend for the same
store:
CLAWMETRY_HOME=~/.clawmetry-staging clawmetry --port 8901