Merge branch 'main' into nanogpt
This commit is contained in:
44 files changed
+1024
-113
No files matched your search
@@ -83,6 +83,8 @@ Notes:
|
||||
- Per-hook `model`/`thinking` in the mapping still overrides these defaults.
|
||||
- Fallback order: `hooks.gmail.model` → `agents.defaults.model.fallbacks` → primary (auth/rate-limit/timeouts).
|
||||
- If `agents.defaults.models` is set, the Gmail model must be in the allowlist.
|
||||
- Gmail hook content is wrapped with external-content safety boundaries by default.
|
||||
To disable (dangerous), set `hooks.gmail.allowUnsafeExternalContent: true`.
|
||||
|
||||
To customize payload handling further, add `hooks.mappings` or a JS/TS transform module
|
||||
under `hooks.transformsDir` (see [Webhooks](/automation/webhook)).
|
||||
|
||||
@@ -96,6 +96,8 @@ Mapping options (summary):
|
||||
- TS transforms require a TS loader (e.g. `bun` or `tsx`) or precompiled `.js` at runtime.
|
||||
- Set `deliver: true` + `channel`/`to` on mappings to route replies to a chat surface
|
||||
(`channel` defaults to `last` and falls back to WhatsApp).
|
||||
- `allowUnsafeExternalContent: true` disables the external content safety wrapper for that hook
|
||||
(dangerous; only for trusted internal sources).
|
||||
- `clawdbot webhooks gmail setup` writes `hooks.gmail` config for `clawdbot webhooks gmail run`.
|
||||
See [Gmail Pub/Sub](/automation/gmail-pubsub) for the full Gmail watch flow.
|
||||
|
||||
@@ -148,3 +150,6 @@ curl -X POST http://127.0.0.1:18789/hooks/gmail \
|
||||
- Keep hook endpoints behind loopback, tailnet, or trusted reverse proxy.
|
||||
- Use a dedicated hook token; do not reuse gateway auth tokens.
|
||||
- Avoid including sensitive raw payloads in webhook logs.
|
||||
- Hook payloads are treated as untrusted and wrapped with safety boundaries by default.
|
||||
If you must disable this for a specific hook, set `allowUnsafeExternalContent: true`
|
||||
in that hook's mapping (dangerous).
|
||||
@@ -2867,21 +2867,22 @@ Notes:
|
||||
- `gateway.port` controls the single multiplexed port used for WebSocket + HTTP (control UI, hooks, A2UI).
|
||||
- OpenAI Chat Completions endpoint: **disabled by default**; enable with `gateway.http.endpoints.chatCompletions.enabled: true`.
|
||||
- Precedence: `--port` > `CLAWDBOT_GATEWAY_PORT` > `gateway.port` > default `18789`.
|
||||
- Non-loopback binds (`lan`/`tailnet`/`auto`) require auth. Use `gateway.auth.token` (or `CLAWDBOT_GATEWAY_TOKEN`).
|
||||
- Gateway auth is required by default (token/password or Tailscale Serve identity). Non-loopback binds require a shared token/password.
|
||||
- The onboarding wizard generates a gateway token by default (even on loopback).
|
||||
- `gateway.remote.token` is **only** for remote CLI calls; it does not enable local gateway auth. `gateway.token` is ignored.
|
||||
|
||||
Auth and Tailscale:
|
||||
- `gateway.auth.mode` sets the handshake requirements (`token` or `password`).
|
||||
- `gateway.auth.mode` sets the handshake requirements (`token` or `password`). When unset, token auth is assumed.
|
||||
- `gateway.auth.token` stores the shared token for token auth (used by the CLI on the same machine).
|
||||
- When `gateway.auth.mode` is set, only that method is accepted (plus optional Tailscale headers).
|
||||
- `gateway.auth.password` can be set here, or via `CLAWDBOT_GATEWAY_PASSWORD` (recommended).
|
||||
- `gateway.auth.allowTailscale` allows Tailscale Serve identity headers
|
||||
(`tailscale-user-login`) to satisfy auth when the request arrives on loopback
|
||||
with `x-forwarded-for`, `x-forwarded-proto`, and `x-forwarded-host`. When
|
||||
`true`, Serve requests do not need a token/password; set `false` to require
|
||||
explicit credentials. Defaults to `true` when `tailscale.mode = "serve"` and
|
||||
auth mode is not `password`.
|
||||
with `x-forwarded-for`, `x-forwarded-proto`, and `x-forwarded-host`. Clawdbot
|
||||
verifies the identity by resolving the `x-forwarded-for` address via
|
||||
`tailscale whois` before accepting it. When `true`, Serve requests do not need
|
||||
a token/password; set `false` to require explicit credentials. Defaults to
|
||||
`true` when `tailscale.mode = "serve"` and auth mode is not `password`.
|
||||
- `gateway.tailscale.mode: "serve"` uses Tailscale Serve (tailnet only, loopback bind).
|
||||
- `gateway.tailscale.mode: "funnel"` exposes the dashboard publicly; requires auth.
|
||||
- `gateway.tailscale.resetOnExit` resets Serve/Funnel config on shutdown.
|
||||
@@ -3174,6 +3175,20 @@ Auto-generated certs require `openssl` on PATH; if generation fails, the bridge
|
||||
}
|
||||
```
|
||||
|
||||
### `discovery.mdns` (Bonjour / mDNS broadcast mode)
|
||||
|
||||
Controls LAN mDNS discovery broadcasts (`_clawdbot-gw._tcp`).
|
||||
|
||||
- `minimal` (default): omit `cliPath` + `sshPort` from TXT records
|
||||
- `full`: include `cliPath` + `sshPort` in TXT records
|
||||
- `off`: disable mDNS broadcasts entirely
|
||||
|
||||
```json5
|
||||
{
|
||||
discovery: { mdns: { mode: "minimal" } }
|
||||
}
|
||||
```
|
||||
|
||||
### `discovery.wideArea` (Wide-Area Bonjour / unicast DNS‑SD)
|
||||
|
||||
When enabled, the Gateway writes a unicast DNS-SD zone for `_clawdbot-bridge._tcp` under `~/.clawdbot/dns/` using the standard discovery domain `clawdbot.internal.`
|
||||
|
||||
@@ -37,7 +37,7 @@ pnpm gateway:watch
|
||||
- `--force` uses `lsof` to find listeners on the chosen port, sends SIGTERM, logs what it killed, then starts the gateway (fails fast if `lsof` is missing).
|
||||
- If you run under a supervisor (launchd/systemd/mac app child-process mode), a stop/restart typically sends **SIGTERM**; older builds may surface this as `pnpm` `ELIFECYCLE` exit code **143** (SIGTERM), which is a normal shutdown, not a crash.
|
||||
- **SIGUSR1** triggers an in-process restart when authorized (gateway tool/config apply/update, or enable `commands.restart` for manual restarts).
|
||||
- Gateway auth: set `gateway.auth.mode=token` + `gateway.auth.token` (or pass `--token <value>` / `CLAWDBOT_GATEWAY_TOKEN`) to require clients to send `connect.params.auth.token`.
|
||||
- Gateway auth is required by default: set `gateway.auth.token` (or `CLAWDBOT_GATEWAY_TOKEN`) or `gateway.auth.password`. Clients must send `connect.params.auth.token/password` unless using Tailscale Serve identity.
|
||||
- The wizard now generates a token by default, even on loopback.
|
||||
- Port precedence: `--port` > `CLAWDBOT_GATEWAY_PORT` > `gateway.port` > default `18789`.
|
||||
|
||||
|
||||
+53
-10
@@ -280,22 +280,63 @@ The Gateway multiplexes **WebSocket + HTTP** on a single port:
|
||||
|
||||
Bind mode controls where the Gateway listens:
|
||||
- `gateway.bind: "loopback"` (default): only local clients can connect.
|
||||
- Non-loopback binds (`"lan"`, `"tailnet"`, `"custom"`) expand the attack surface. Only use them with `gateway.auth` enabled and a real firewall.
|
||||
- Non-loopback binds (`"lan"`, `"tailnet"`, `"custom"`) expand the attack surface. Only use them with a shared token/password and a real firewall.
|
||||
|
||||
Rules of thumb:
|
||||
- Prefer Tailscale Serve over LAN binds (Serve keeps the Gateway on loopback, and Tailscale handles access).
|
||||
- If you must bind to LAN, firewall the port to a tight allowlist of source IPs; do not port-forward it broadly.
|
||||
- Never expose the Gateway unauthenticated on `0.0.0.0`.
|
||||
|
||||
### 0.4.1) mDNS/Bonjour discovery (information disclosure)
|
||||
|
||||
The Gateway broadcasts its presence via mDNS (`_clawdbot-gw._tcp` on port 5353) for local device discovery. In full mode, this includes TXT records that may expose operational details:
|
||||
|
||||
- `cliPath`: full filesystem path to the CLI binary (reveals username and install location)
|
||||
- `sshPort`: advertises SSH availability on the host
|
||||
- `displayName`, `lanHost`: hostname information
|
||||
|
||||
**Operational security consideration:** Broadcasting infrastructure details makes reconnaissance easier for anyone on the local network. Even "harmless" info like filesystem paths and SSH availability helps attackers map your environment.
|
||||
|
||||
**Recommendations:**
|
||||
|
||||
1. **Minimal mode** (default, recommended for exposed gateways): omit sensitive fields from mDNS broadcasts:
|
||||
```json5
|
||||
{
|
||||
discovery: {
|
||||
mdns: { mode: "minimal" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. **Disable entirely** if you don't need local device discovery:
|
||||
```json5
|
||||
{
|
||||
discovery: {
|
||||
mdns: { mode: "off" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. **Full mode** (opt-in): include `cliPath` + `sshPort` in TXT records:
|
||||
```json5
|
||||
{
|
||||
discovery: {
|
||||
mdns: { mode: "full" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
4. **Environment variable** (alternative): set `CLAWDBOT_DISABLE_BONJOUR=1` to disable mDNS without config changes.
|
||||
|
||||
In minimal mode, the Gateway still broadcasts enough for device discovery (`role`, `gatewayPort`, `transport`) but omits `cliPath` and `sshPort`. Apps that need CLI path information can fetch it via the authenticated WebSocket connection instead.
|
||||
|
||||
### 0.5) Lock down the Gateway WebSocket (local auth)
|
||||
|
||||
Gateway auth is **only** enforced when you set `gateway.auth`. If it’s unset,
|
||||
loopback WS clients are unauthenticated — any local process can connect and call
|
||||
`config.apply`.
|
||||
Gateway auth is **required by default**. If no token/password is configured,
|
||||
the Gateway refuses WebSocket connections (fail‑closed).
|
||||
|
||||
The onboarding wizard now generates a token by default (even for loopback) so
|
||||
local clients must authenticate. If you skip the wizard or remove auth, you’re
|
||||
back to open loopback.
|
||||
The onboarding wizard generates a token by default (even for loopback) so
|
||||
local clients must authenticate.
|
||||
|
||||
Set a token so **all** WS clients must authenticate:
|
||||
|
||||
@@ -333,9 +374,11 @@ Rotation checklist (token/password):
|
||||
|
||||
When `gateway.auth.allowTailscale` is `true` (default for Serve), Clawdbot
|
||||
accepts Tailscale Serve identity headers (`tailscale-user-login`) as
|
||||
authentication. This only triggers for requests that hit loopback and include
|
||||
`x-forwarded-for`, `x-forwarded-proto`, and `x-forwarded-host` as injected by
|
||||
Tailscale.
|
||||
authentication. Clawdbot verifies the identity by resolving the
|
||||
`x-forwarded-for` address through the local Tailscale daemon (`tailscale whois`)
|
||||
and matching it to the header. This only triggers for requests that hit loopback
|
||||
and include `x-forwarded-for`, `x-forwarded-proto`, and `x-forwarded-host` as
|
||||
injected by Tailscale.
|
||||
|
||||
**Security rule:** do not forward these headers from your own reverse proxy. If
|
||||
you terminate TLS or proxy in front of the gateway, disable
|
||||
|
||||
@@ -25,9 +25,12 @@ Set `gateway.auth.mode` to control the handshake:
|
||||
|
||||
When `tailscale.mode = "serve"` and `gateway.auth.allowTailscale` is `true`,
|
||||
valid Serve proxy requests can authenticate via Tailscale identity headers
|
||||
(`tailscale-user-login`) without supplying a token/password. Clawdbot only
|
||||
treats a request as Serve when it arrives from loopback with Tailscale’s
|
||||
`x-forwarded-for`, `x-forwarded-proto`, and `x-forwarded-host` headers.
|
||||
(`tailscale-user-login`) without supplying a token/password. Clawdbot verifies
|
||||
the identity by resolving the `x-forwarded-for` address via the local Tailscale
|
||||
daemon (`tailscale whois`) and matching it to the header before accepting it.
|
||||
Clawdbot only treats a request as Serve when it arrives from loopback with
|
||||
Tailscale’s `x-forwarded-for`, `x-forwarded-proto`, and `x-forwarded-host`
|
||||
headers.
|
||||
To require explicit credentials, set `gateway.auth.allowTailscale: false` or
|
||||
force `gateway.auth.mode: "password"`.
|
||||
|
||||
|
||||
+1
-2
@@ -566,7 +566,6 @@ Remote access: [Gateway remote](/gateway/remote).
|
||||
We keep a **hosting hub** with the common providers. Pick one and follow the guide:
|
||||
|
||||
- [VPS hosting](/vps) (all providers in one place)
|
||||
- [Railway](/railway) (one‑click, browser‑based setup)
|
||||
- [Fly.io](/platforms/fly)
|
||||
- [Hetzner](/platforms/hetzner)
|
||||
- [exe.dev](/platforms/exe-dev)
|
||||
@@ -1451,7 +1450,7 @@ Have Bot A send a message to Bot B, then let Bot B reply as usual.
|
||||
|
||||
**CLI bridge (generic):** run a script that calls the other Gateway with
|
||||
`clawdbot agent --message ... --deliver`, targeting a chat where the other bot
|
||||
listens. If one bot is on Railway/VPS, point your CLI at that remote Gateway
|
||||
listens. If one bot is on a remote VPS, point your CLI at that remote Gateway
|
||||
via SSH/Tailscale (see [Remote access](/gateway/remote)).
|
||||
|
||||
Example pattern (run from a machine that can reach the target Gateway):
|
||||
|
||||
@@ -90,10 +90,10 @@ The wizard will walk you through:
|
||||
clawdbot status
|
||||
|
||||
# Check service
|
||||
systemctl status clawdbot
|
||||
systemctl --user status clawdbot-gateway.service
|
||||
|
||||
# View logs
|
||||
journalctl -u clawdbot -f
|
||||
journalctl --user -u clawdbot-gateway.service -f
|
||||
```
|
||||
|
||||
## 6) Access the Dashboard
|
||||
@@ -108,18 +108,30 @@ ssh -L 18789:localhost:18789 root@YOUR_DROPLET_IP
|
||||
# Then open: http://localhost:18789
|
||||
```
|
||||
|
||||
**Option B: Tailscale (easier long-term)**
|
||||
**Option B: Tailscale Serve (HTTPS, loopback-only)**
|
||||
```bash
|
||||
# On the droplet
|
||||
curl -fsSL https://tailscale.com/install.sh | sh
|
||||
tailscale up
|
||||
|
||||
# Configure gateway to bind to Tailscale
|
||||
# Configure Gateway to use Tailscale Serve
|
||||
clawdbot config set gateway.tailscale.mode serve
|
||||
clawdbot gateway restart
|
||||
```
|
||||
|
||||
Open: `https://<magicdns>/`
|
||||
|
||||
Notes:
|
||||
- Serve keeps the Gateway loopback-only and authenticates via Tailscale identity headers.
|
||||
- To require token/password instead, set `gateway.auth.allowTailscale: false` or use `gateway.auth.mode: "password"`.
|
||||
|
||||
**Option C: Tailnet bind (no Serve)**
|
||||
```bash
|
||||
clawdbot config set gateway.bind tailnet
|
||||
clawdbot gateway restart
|
||||
```
|
||||
|
||||
Then access via your Tailscale IP: `http://100.x.x.x:18789`
|
||||
Open: `http://<tailscale-ip>:18789` (token required).
|
||||
|
||||
## 7) Connect Your Channels
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ Native companion apps for Windows are also planned; the Gateway is recommended v
|
||||
## VPS & hosting
|
||||
|
||||
- VPS hub: [VPS hosting](/vps)
|
||||
- Railway (one-click): [Railway](/railway)
|
||||
- Fly.io: [Fly.io](/platforms/fly)
|
||||
- Hetzner (Docker): [Hetzner](/platforms/hetzner)
|
||||
- GCP (Compute Engine): [GCP](/platforms/gcp)
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
---
|
||||
summary: "VPS hosting hub for Clawdbot (Railway/Fly/Hetzner/exe.dev)"
|
||||
summary: "VPS hosting hub for Clawdbot (Fly/Hetzner/GCP/exe.dev)"
|
||||
read_when:
|
||||
- You want to run the Gateway in the cloud
|
||||
- You need a quick map of VPS/hosting guides
|
||||
@@ -11,7 +11,6 @@ deployments work at a high level.
|
||||
|
||||
## Pick a provider
|
||||
|
||||
- **Railway** (one‑click + browser setup): [Railway](/railway)
|
||||
- **Fly.io**: [Fly.io](/platforms/fly)
|
||||
- **Hetzner (Docker)**: [Hetzner](/platforms/hetzner)
|
||||
- **GCP (Compute Engine)**: [GCP](/platforms/gcp)
|
||||
@@ -24,6 +23,8 @@ deployments work at a high level.
|
||||
- The **Gateway runs on the VPS** and owns state + workspace.
|
||||
- You connect from your laptop/phone via the **Control UI** or **Tailscale/SSH**.
|
||||
- Treat the VPS as the source of truth and **back up** the state + workspace.
|
||||
- Secure default: keep the Gateway on loopback and access it via SSH tunnel or Tailscale Serve.
|
||||
If you bind to `lan`/`tailnet`, require `gateway.auth.token` or `gateway.auth.password`.
|
||||
|
||||
Remote access: [Gateway remote](/gateway/remote)
|
||||
Platforms hub: [Platforms](/platforms)
|
||||
|
||||
@@ -70,10 +70,11 @@ Open:
|
||||
|
||||
By default, Serve requests can authenticate via Tailscale identity headers
|
||||
(`tailscale-user-login`) when `gateway.auth.allowTailscale` is `true`. Clawdbot
|
||||
only accepts these when the request hits loopback with Tailscale’s
|
||||
`x-forwarded-*` headers. Set `gateway.auth.allowTailscale: false` (or force
|
||||
`gateway.auth.mode: "password"`) if you want to require a token/password even
|
||||
for Serve traffic.
|
||||
verifies the identity by resolving the `x-forwarded-for` address with
|
||||
`tailscale whois` and matching it to the header, and only accepts these when the
|
||||
request hits loopback with Tailscale’s `x-forwarded-*` headers. Set
|
||||
`gateway.auth.allowTailscale: false` (or force `gateway.auth.mode: "password"`)
|
||||
if you want to require a token/password even for Serve traffic.
|
||||
|
||||
### Bind to tailnet + token
|
||||
|
||||
|
||||
+2
-1
@@ -91,7 +91,8 @@ Open:
|
||||
|
||||
## Security notes
|
||||
|
||||
- Binding the Gateway to a non-loopback address **requires** auth (`gateway.auth` or `CLAWDBOT_GATEWAY_TOKEN`).
|
||||
- Gateway auth is required by default (token/password or Tailscale identity headers).
|
||||
- Non-loopback binds still **require** a shared token/password (`gateway.auth` or env).
|
||||
- The wizard generates a gateway token by default (even on loopback).
|
||||
- The UI sends `connect.params.auth.token` or `connect.params.auth.password`.
|
||||
- With Serve, Tailscale identity headers can satisfy auth when
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ Status: the macOS/iOS SwiftUI chat UI talks directly to the Gateway WebSocket.
|
||||
## Quick start
|
||||
1) Start the gateway.
|
||||
2) Open the WebChat UI (macOS/iOS app) or the Control UI chat tab.
|
||||
3) Ensure gateway auth is configured if you are not on loopback.
|
||||
3) Ensure gateway auth is configured (required by default, even on loopback).
|
||||
|
||||
## How it works (behavior)
|
||||
- The UI connects to the Gateway WebSocket and uses `chat.history`, `chat.send`, and `chat.inject`.
|
||||
|
||||
Reference in new issue
Block a user