Skip to content

Fix cloudflared quick tunnel startup in Docker#783

Merged
diegosouzapw merged 1 commit intodiegosouzapw:mainfrom
rdself:coder/cloudflared-exit1-fix
Mar 30, 2026
Merged

Fix cloudflared quick tunnel startup in Docker#783
diegosouzapw merged 1 commit intodiegosouzapw:mainfrom
rdself:coder/cloudflared-exit1-fix

Conversation

@rdself
Copy link
Copy Markdown
Contributor

@rdself rdself commented Mar 30, 2026

Summary

  • isolate the managed cloudflared runtime from ambient HOME / XDG_* config so Quick Tunnel startup is not broken by existing config.yml
  • let cloudflared use its default protocol auto-negotiation instead of forcing http2
  • add unit coverage for the isolated child environment and startup args

Root cause

Quick Tunnel startup can fail early when the parent process environment points cloudflared at an existing .cloudflared/config.yml. I reproduced the failure locally with an invalid config file in HOME, which exited immediately with code 1.

Validation

  • node --import tsx/esm --test tests/unit/cloudflaredTunnel.test.mjs
  • npm run typecheck:core
  • npx eslint src/lib/cloudflaredTunnel.ts tests/unit/cloudflaredTunnel.test.mjs
  • manual smoke test: start startCloudflaredTunnel() with an invalid parent HOME/.cloudflared/config.yml and confirm it still returns a trycloudflare.com/v1 URL after the fix

Copilot AI review requested due to automatic review settings March 30, 2026 02:30
@kilo-code-bot
Copy link
Copy Markdown

kilo-code-bot bot commented Mar 30, 2026

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 0

Analysis Summary

The PR correctly addresses the root cause described in the PR description - isolating the managed cloudflared runtime from ambient environment variables that could point it to an existing .cloudflared/config.yml file.

Changes reviewed:

  1. CloudflaredRuntimeDirs type (lines 27-37) - Properly defines all runtime directory paths needed for isolation

  2. getCloudflaredRuntimeDirs() function (lines 140-156) - Creates isolated directory paths under the managed tunnel directory with proper subdirectories for home, config, cache, data, temp, and Windows-specific paths

  3. ensureTunnelRuntimeDirs() function (lines 171-176) - Creates all runtime directories in parallel using fs.mkdir with { recursive: true }

  4. buildCloudflaredChildEnv() modification (lines 241-267) - Now properly overrides HOME, XDG_CONFIG_HOME, XDG_CACHE_HOME, XDG_DATA_HOME, USERPROFILE, APPDATA, LOCALAPPDATA, and TEMP* variables to isolate cloudflared from parent environment

  5. getCloudflaredStartArgs() function (lines 269-271) - Removes the forced --protocol http2 flag, allowing cloudflared to use its default protocol auto-negotiation as intended

  6. startCloudflaredTunnel() call site (lines 547-564) - Properly calls ensureTunnelRuntimeDirs() and uses the new getCloudflaredStartArgs() helper

  7. Unit tests - Added comprehensive tests for:

    • buildCloudflaredChildEnv with isolated runtime directories
    • getCloudflaredStartArgs to verify protocol auto-negotiation

Fix Verification

The fix correctly isolates cloudflared by:

  • Setting HOME to an isolated directory (preventing config.yml lookup)
  • Setting XDG_CONFIG_HOME, XDG_CACHE_HOME, XDG_DATA_HOME to isolated paths
  • Setting Windows-specific paths (USERPROFILE, APPDATA, LOCALAPPDATA)
  • Removing forced HTTP/2 protocol to allow auto-negotiation
Files Reviewed (2 files)
  • src/lib/cloudflaredTunnel.ts - Implementation
  • tests/unit/cloudflaredTunnel.test.mjs - Unit tests

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements runtime directory isolation for the cloudflared process by defining specific directories for configuration, cache, and data, and mapping them to environment variables. It also refactors the tunnel startup arguments to support protocol auto-negotiation. The review feedback suggests using the logical OR assignment operator (||=) for more concise assignment of temporary directory environment variables.

Comment on lines +262 to +264
if (!childEnv.TMPDIR) childEnv.TMPDIR = runtimeDirs.tempDir;
if (!childEnv.TMP) childEnv.TMP = runtimeDirs.tempDir;
if (!childEnv.TEMP) childEnv.TEMP = runtimeDirs.tempDir;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For conciseness, you can use the logical OR assignment operator (||=) to set these temporary directory environment variables. This operator assigns the right-hand side value only if the left-hand side is falsy (e.g., undefined or an empty string), which matches the current logic.

Suggested change
if (!childEnv.TMPDIR) childEnv.TMPDIR = runtimeDirs.tempDir;
if (!childEnv.TMP) childEnv.TMP = runtimeDirs.tempDir;
if (!childEnv.TEMP) childEnv.TEMP = runtimeDirs.tempDir;
childEnv.TMPDIR ||= runtimeDirs.tempDir;
childEnv.TMP ||= runtimeDirs.tempDir;
childEnv.TEMP ||= runtimeDirs.tempDir;

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes Cloudflare cloudflared Quick Tunnel startup in Docker by running cloudflared under an isolated, managed runtime environment (so ambient HOME/XDG_* config can’t interfere) and by letting cloudflared auto-negotiate its protocol rather than forcing http2.

Changes:

  • Add a managed runtime directory layout and ensure it exists before spawning cloudflared.
  • Build a sanitized child process environment that overrides HOME and relevant XDG_*/Windows profile directories to point at the managed runtime.
  • Factor tunnel start arguments into a helper and remove the forced --protocol http2, with unit coverage for env/args.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/lib/cloudflaredTunnel.ts Introduces managed runtime dirs, isolates cloudflared child env, and updates spawn args to rely on protocol auto-negotiation.
tests/unit/cloudflaredTunnel.test.mjs Adds/updates unit tests covering the isolated child env and start argument construction.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@diegosouzapw diegosouzapw merged commit 4d8c054 into diegosouzapw:main Mar 30, 2026
10 of 15 checks passed
@diegosouzapw
Copy link
Copy Markdown
Owner

Thanks @rdself for this excellent contribution! 🎉

The cloudflared quick tunnel isolation fix is clean, well-tested, and solves a real Docker deployment issue. The decision to remove the hardcoded --protocol http2 in favor of cloudflared's native auto-negotiation is spot-on.

This is now merged and will be part of the next release. We appreciate your effort!

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.

3 participants