fix(app-router): loopback bind + OpenClaw webhook routing with bearer injection#124
fix(app-router): loopback bind + OpenClaw webhook routing with bearer injection#124TechNickAI wants to merge 2 commits into
Conversation
Without bind 127.0.0.1 ::1, Caddy's :8080 block binds to all interfaces, exposing the auth-service to anyone on the local network (home LAN, office LAN) who bypasses the Tailscale path entirely. Loopback-only binding means only Tailscale Serve (which proxies to 127.0.0.1:8080) can reach Caddy. Co-Authored-By: Claude <noreply@anthropic.com>
- Caddyfile.example: add commented-out /hooks/* block that reverse-proxies
to the OpenClaw gateway (127.0.0.1:18789) and injects Authorization bearer
via {env.OPENCLAW_HOOK_TOKEN} — callers (AgentMail Svix, iOS Shortcuts)
don't need to send auth themselves
- restore-tailscale-serve.sh: optional APP_ROUTER_HOOKS_PATH env mounts a
path on the default :443 tailscale-serve for legacy webhook URL preservation;
optional APP_ROUTER_ROOT_UPSTREAM mounts a second upstream at /
- launchd plist: add commented-out EnvironmentVariables entries for both
new optional env keys
- README: add "Fronting OpenClaw Webhooks" section explaining setup and
legacy URL preservation
Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b80d4d584c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| the PM2 ecosystem env block in `ecosystem.config.js`: | ||
| ```js | ||
| env: { | ||
| OPENCLAW_HOOK_TOKEN: "your-token-here"; |
There was a problem hiding this comment.
Use valid JS syntax in PM2 env example
The new setup snippet shows OPENCLAW_HOOK_TOKEN with a trailing semicolon inside an object literal, which is invalid JavaScript in ecosystem.config.js. If users copy this block as written, PM2 will fail to parse the config and Caddy won’t receive OPENCLAW_HOOK_TOKEN, so the webhook bearer-injection flow described in this section will not work.
Useful? React with 👍 / 👎.
Summary
Security fix (original motivation): Caddy's
:8080block was binding to all interfaces — on hosts with a home or office LAN, this exposed Caddy and the auth-service it fronts to anyone on that network, bypassing the Tailscale path entirely. Addedbind 127.0.0.1 ::1as the first directive inside the server block to restrict to loopback only. Tailscale Serve still works because it proxies to127.0.0.1:8080.New feature —
/hooks/*bearer injection: Added an optional commented-outhandle /hooks/* { ... }block inCaddyfile.examplethat reverse-proxies to the OpenClaw gateway hooks server (127.0.0.1:18789) and injectsAuthorization: Bearer <token>via{env.OPENCLAW_HOOK_TOKEN}(Caddy env-var syntax). External callers like AgentMail Svix and iOS Shortcuts canPOSTwithout sending auth headers themselves.Optional tailscale-serve mounts: Extended
restore-tailscale-serve.shwith two opt-in env-driventailscale serve --set-pathmounts —APP_ROUTER_HOOKS_PATHfor legacy webhook URLs on the default:443mount, andAPP_ROUTER_ROOT_UPSTREAMfor a second upstream at/. Matching commented-out entries added to the launchd plist.README: New
## Fronting OpenClaw Webhooks (optional)section after## Auth Modelcovering the why (bearer injection problem), how (PM2 env + uncomment block), caller URL, and legacy URL preservation viaAPP_ROUTER_HOOKS_PATH.Design Decisions
{env.OPENCLAW_HOOK_TOKEN}rather than hardcoded in the template — keeps secrets out of the repo and config files entirely./hooks/*block is commented out by default — zero behavior change for existing installs.:4242 → :8080mount is untouched.Complexity
balanced — 4 files, clear requirements, no architectural decisions required.
Validation
caddy validatestep:caddynot on PATH in this environment; template renders correctly —bind 127.0.0.1 ::1is valid Caddy syntax per docs.