Skip to content

feat(tunnels): named cloudflared tunnel via CLOUDFLARED_CONFIG - #11561

Merged
diegosouzapw merged 1 commit into
diegosouzapw:release/v3.8.51from
ggiak:feat/cloudflared-named-tunnel
Aug 26, 2026
Merged

diegosouzapw merged 1 commit into
diegosouzapw:release/v3.8.51from
ggiak:feat/cloudflared-named-tunnel

Conversation

@ggiak

@ggiak ggiak commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds an opt-in named/persistent Cloudflare tunnel mode to the cloudflared
integration, so operators can expose OmniRoute on a stable, named hostname
(e.g. ai.example.com) instead of the ephemeral *.trycloudflare.com URL that
changes on every restart.

This targets the locally-managed cloudflared flow (cloudflared tunnel login
→ create → route dns → a ~/.cloudflared/config.yml with tunnel:,
credentials-file:, ingress:) — no Zero Trust dashboard / connector token is
required
.

How it works

  • Set CLOUDFLARED_CONFIG=/path/to/config.yml to switch into named-tunnel mode.
    OmniRoute then runs cloudflared tunnel --no-autoupdate --config <path> run.
    run reads credentials from the config's absolute credentials-file path, so
    it works even with OmniRoute's isolated HOME and needs no cert.pem.
  • Named tunnels emit no public URL to scrape, so readiness is detected from
    cloudflared's Registered tunnel connection log line
    .
  • publicUrl / apiUrl are reported from CLOUDFLARED_HOSTNAME, or — when that
    override is unset — auto-read from the config's first ingress hostname.
  • Default quick-tunnel behavior is unchanged: mode is selected purely by
    whether CLOUDFLARED_CONFIG is set. With it unset, the code path is byte-for-byte
    the previous quick-tunnel path.
  • Fails fast with a clear error if the config path is missing (instead of a 30s
    readiness timeout).

Also documents the previously-undocumented CLOUDFLARED_PROTOCOL.

Files

  • src/lib/cloudflaredTunnel.ts — named-tunnel config resolution, config-file
    args, ingress-hostname parser, connection-ready detection, start wiring.
  • tests/unit/cloudflaredTunnel.test.ts — pure-function unit tests (arg builder,
    config resolution, hostname normalizer, ingress parser, readiness matcher).
  • tests/unit/cloudflaredTunnel-extended.test.ts — behavioral test driving the
    real startCloudflaredTunnel state machine via a fake child that emits a
    registered-connection log line; asserts args, publicUrl/apiUrl, state.
  • .env.example, docs/ops/TUNNELS_GUIDE.md, docs/reference/ENVIRONMENT.md.

Testing

  • Unit + behavioral: node --import tsx/esm --test tests/unit/cloudflaredTunnel.test.ts tests/unit/cloudflaredTunnel-extended.test.ts → 33/33 pass.
  • Real-environment validation (Hard Rule fix(ci): add environment for npm token access #18) against a live cloudflared 2026.8.2:
    • The binary accepts the flag ordering tunnel --no-autoupdate --config <path> run (failure was on config content, not flag parsing).
    • The readiness regex matches real tunnel logs (Registered tunnel connection connIndex=… protocol=quic).
    • The ingress-hostname parser extracts the correct host from a real config.yml.
  • npm run lint, npm run typecheck:core (my files), check:env-doc-sync, and Prettier are clean on the changed files.

Notes

  • Pre-existing typecheck errors in open-sse/services/compression/omniglyph*
    (an omniglyph package API/version mismatch) exist on the base tip and are
    unrelated to this change — no files under open-sse/ are touched here.

Adds an opt-in named/persistent tunnel mode to the cloudflared integration,
alongside the existing ephemeral quick tunnel. When CLOUDFLARED_CONFIG points at
a locally-managed cloudflared config.yml (tunnel / credentials-file / ingress),
OmniRoute runs `cloudflared tunnel --no-autoupdate --config <path> run` to expose
a stable, named hostname instead of a random *.trycloudflare.com URL. No Zero
Trust dashboard token is required.

- Readiness is detected from cloudflared's "Registered tunnel connection" log
  line, since named tunnels emit no public URL to scrape.
- publicUrl/apiUrl are reported from CLOUDFLARED_HOSTNAME, or auto-read from the
  config's first ingress hostname when the override is unset.
- Default quick-tunnel behavior is unchanged: the mode is selected purely by
  whether CLOUDFLARED_CONFIG is set.
- Fails fast with a clear error when the config path is missing, instead of a
  30s readiness timeout.

Validated against a real cloudflared 2026.8.2 setup: the binary accepts the flag
ordering, the readiness regex matches real tunnel logs, and the hostname parser
extracts the configured ingress host. Unit + behavioral tests exercise the full
start state machine via a fake child process.

Docs: TUNNELS_GUIDE.md (named-tunnel setup), .env.example, ENVIRONMENT.md.
@ggiak
ggiak requested a review from diegosouzapw as a code owner August 25, 2026 22:56
@diegosouzapw
diegosouzapw merged commit c63e519 into diegosouzapw:release/v3.8.51 Aug 26, 2026
10 of 16 checks passed
diegosouzapw added a commit that referenced this pull request Aug 26, 2026
…11630)

Merged via /merge-batch (lote 2026-08-26, v3.8.51). check:file-size confirmado OK após o rebaseline.
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…IG (diegosouzapw#11561)

Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…apw#11495/diegosouzapw#11561 growth (diegosouzapw#11630)

Merged via /merge-batch (lote 2026-08-26, v3.8.51). check:file-size confirmado OK após o rebaseline.
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.

2 participants