diff --git a/doc/DEVELOPING.md b/doc/DEVELOPING.md index c73d22e5..ffbb7fa3 100644 --- a/doc/DEVELOPING.md +++ b/doc/DEVELOPING.md @@ -298,3 +298,9 @@ State behavior for this smoke script: - defaults to isolated config dir `~/.openclaw-paperclip-smoke` - resets smoke agent state each run by default (`OPENCLAW_RESET_STATE=1`) to avoid stale provider/auth drift + +Networking behavior for this smoke script: + +- auto-detects and prints a Paperclip host URL reachable from inside OpenClaw Docker +- default container-side host alias is `host.docker.internal` (override with `PAPERCLIP_HOST_FROM_CONTAINER` / `PAPERCLIP_HOST_PORT`) +- if Paperclip rejects container hostnames in authenticated/private mode, allow `host.docker.internal` via `pnpm paperclipai allowed-hostname host.docker.internal` and restart Paperclip diff --git a/docs/guides/openclaw-docker-setup.md b/docs/guides/openclaw-docker-setup.md index 50de462b..bf8d1496 100644 --- a/docs/guides/openclaw-docker-setup.md +++ b/docs/guides/openclaw-docker-setup.md @@ -42,6 +42,7 @@ What this command does: - writes isolated smoke config under `~/.openclaw-paperclip-smoke/openclaw.json` and Docker `.env` - pins agent model defaults to OpenAI (`openai/gpt-5.2` with OpenAI fallback) - starts `openclaw-gateway` via Compose (with required `/tmp` tmpfs override) +- probes and prints a Paperclip host URL that is reachable from inside OpenClaw Docker - waits for health and prints: - `http://127.0.0.1:18789/#token=...` - disables Control UI device pairing by default for local smoke ergonomics @@ -60,6 +61,8 @@ Environment knobs: - `OPENCLAW_MODEL_FALLBACK` (default `openai/gpt-5.2-chat-latest`) - `OPENCLAW_CONFIG_DIR` (default `~/.openclaw-paperclip-smoke`) - `OPENCLAW_RESET_STATE=1` (default) resets smoke agent state on each run to avoid stale auth/session drift +- `PAPERCLIP_HOST_PORT` (default `3100`) +- `PAPERCLIP_HOST_FROM_CONTAINER` (default `host.docker.internal`) ### Authenticated mode @@ -74,6 +77,15 @@ PAPERCLIP_COOKIE="your_session_cookie=..." pnpm smoke:openclaw-join ### Network topology tips - Local same-host smoke: default callback uses `http://127.0.0.1:/webhook`. +- Inside OpenClaw Docker, `127.0.0.1` points to the container itself, not your host Paperclip server. +- For invite/onboarding URLs consumed by OpenClaw in Docker, use the script-printed Paperclip URL (typically `http://host.docker.internal:3100`). +- If Paperclip rejects the container-visible host with a hostname error, allow it from host: + +```bash +pnpm paperclipai allowed-hostname host.docker.internal +``` + +Then restart Paperclip and rerun the smoke script. - Docker/remote OpenClaw: prefer a reachable hostname (Docker host alias, Tailscale hostname, or public domain). - Authenticated/private mode: ensure hostnames are in the allowed list when required: diff --git a/scripts/smoke/openclaw-docker-ui.sh b/scripts/smoke/openclaw-docker-ui.sh index c86348c8..234d7d91 100755 --- a/scripts/smoke/openclaw-docker-ui.sh +++ b/scripts/smoke/openclaw-docker-ui.sh @@ -39,6 +39,8 @@ OPENCLAW_DISABLE_DEVICE_AUTH="${OPENCLAW_DISABLE_DEVICE_AUTH:-1}" OPENCLAW_MODEL_PRIMARY="${OPENCLAW_MODEL_PRIMARY:-openai/gpt-5.2}" OPENCLAW_MODEL_FALLBACK="${OPENCLAW_MODEL_FALLBACK:-openai/gpt-5.2-chat-latest}" OPENCLAW_RESET_STATE="${OPENCLAW_RESET_STATE:-1}" +PAPERCLIP_HOST_PORT="${PAPERCLIP_HOST_PORT:-3100}" +PAPERCLIP_HOST_FROM_CONTAINER="${PAPERCLIP_HOST_FROM_CONTAINER:-host.docker.internal}" case "$OPENCLAW_DISABLE_DEVICE_AUTH" in 1|true|TRUE|True|yes|YES|Yes) @@ -138,6 +140,8 @@ services: openclaw-gateway: tmpfs: - /tmp:exec,size=512M + extra_hosts: + - "host.docker.internal:host-gateway" openclaw-cli: tmpfs: - /tmp:exec,size=512M @@ -150,6 +154,20 @@ compose() { "$@" } +detect_paperclip_base_url() { + local bridge_gateway candidate health_url + bridge_gateway="$(docker network inspect openclaw-docker_default --format '{{(index .IPAM.Config 0).Gateway}}' 2>/dev/null || true)" + for candidate in "$PAPERCLIP_HOST_FROM_CONTAINER" "$bridge_gateway"; do + [[ -n "$candidate" ]] || continue + health_url="http://${candidate}:${PAPERCLIP_HOST_PORT}/api/health" + if compose exec -T openclaw-gateway node -e "fetch('${health_url}').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))" >/dev/null 2>&1; then + echo "http://${candidate}:${PAPERCLIP_HOST_PORT}" + return 0 + fi + done + return 1 +} + log "starting OpenClaw gateway container" compose up -d openclaw-gateway @@ -168,6 +186,7 @@ if [[ "$READY" != "1" ]]; then fail "gateway did not become healthy in ${OPENCLAW_WAIT_SECONDS}s" fi +paperclip_base_url="$(detect_paperclip_base_url || true)" dashboard_output="$(compose run --rm openclaw-cli dashboard --no-open)" dashboard_url="$(grep -Eo 'https?://[^[:space:]]+#token=[^[:space:]]+' <<<"$dashboard_output" | head -n1 || true)" if [[ -z "$dashboard_url" ]]; then @@ -192,6 +211,23 @@ Model: ${OPENCLAW_MODEL_PRIMARY} (fallback: ${OPENCLAW_MODEL_FALLBACK}) State: OPENCLAW_RESET_STATE=$OPENCLAW_RESET_STATE +Paperclip URL for OpenClaw container: +EOF + if [[ -n "$paperclip_base_url" ]]; then + cat <