Skip to content

feat(webhook): add tunnel = "external" for externally-managed ingress#98

Merged
ephpm-claude[bot] merged 1 commit into
mainfrom
feat-webhook-external-tunnel
Jul 8, 2026
Merged

feat(webhook): add tunnel = "external" for externally-managed ingress#98
ephpm-claude[bot] merged 1 commit into
mainfrom
feat-webhook-external-tunnel

Conversation

@ephpm-claude

@ephpm-claude ephpm-claude Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

What

Adds tunnel = "external": a webhook mode for when a tunnel already exists but is managed outside ephemerd — e.g. a Cloudflare tunnel on another host forwarding a public hostname to ephemerd's webhook port.

In this mode ephemerd:

  • serves the /webhook/<provider> receiver and disables polling, but
  • does not create a tunnel or auto-register the GitHub webhook (ingress + registration are owned externally), and
  • requires a secret (unlike managed tunnels, we must not invent one — it has to match the external webhook config).

Also

Fixes a misleading startup log: with a secret set but tunnel = "none", ephemerd already ran webhook-only (polling disabled) yet logged polling mode enabled (tunnel disabled). The log now reflects the real discovery mode per setting, and the webhook port defaults to 8080 whenever a receiver is active.

Tests: external-requires-secret, external keeps the provided secret + defaults port, managed tunnel still auto-generates, none+secret defaults port.

Note

No Cloudflare creation code is added — external is for an externally-run tunnel. A managed cloudflare provider (shelling out to cloudflared) could be a follow-up if the host should self-serve the tunnel.

🤖 Generated with Claude Code

Adds a webhook tunnel mode for when a tunnel already exists but is
managed OUTSIDE ephemerd — e.g. a Cloudflare tunnel on another host
forwarding a public hostname to ephemerd's webhook port. In this mode
ephemerd serves the /webhook/<provider> receiver and disables polling,
but does NOT create a tunnel or auto-register the GitHub webhook (that
ingress and registration are owned externally). A matching secret is
required so incoming signatures can be verified — unlike managed tunnels
(ngrok/localtunnel) we must not invent one.

Also fixes a misleading log line: with a webhook secret set but
tunnel = "none", ephemerd already ran in webhook mode (polling disabled)
yet logged "polling mode enabled (tunnel disabled)". The startup log now
reflects the real discovery mode for each tunnel setting, and the webhook
port defaults to 8080 whenever a receiver is active.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ChVRC9ZrvQarrctDwSy1S5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant