Skip to content

Add Cloudflare Tunnel support for development - #119

Merged
richardthe3rd merged 1 commit into
mainfrom
richardthe3rd/cloudflare-tunnel
Dec 8, 2025
Merged

Add Cloudflare Tunnel support for development#119
richardthe3rd merged 1 commit into
mainfrom
richardthe3rd/cloudflare-tunnel

Conversation

@richardthe3rd

Copy link
Copy Markdown
Owner

Summary

Adds Cloudflare Tunnel support to enable secure public HTTPS access to local development servers at tunnel.cambeerfestival.app. This improves the development workflow by providing:

  • Secure HTTPS access to local development environment via a persistent named tunnel
  • Public accessibility for testing on real devices and sharing with stakeholders
  • Automated setup tasks using mise for tunnel configuration and management

Changes

Infrastructure

  • .cloudflared/config.yml - Cloudflare Tunnel configuration for cbf-dev-tunnel routing to localhost:8080
  • .gitignore - Added exclusions for tunnel credentials and certificates

CORS Configuration

  • cloudflare-worker/worker.js - Added tunnel.cambeerfestival.app to allowed origins and support for quick tunnels (*.trycloudflare.com)

Development Tools

  • mise.dev.toml - Added cloudflared tool and new mise tasks:
    • tunnel-setup - One-time tunnel configuration (login, create, route DNS)
    • dev-tunnel - Runs both tunnel and Flutter dev server together
    • Moved existing dev task here from mise.toml (developer-only)
  • mise.toml - Removed dev task (now in mise.dev.toml)

Usage

First-time setup:

MISE_ENV=dev ./bin/mise run tunnel-setup

Daily development:

MISE_ENV=dev ./bin/mise run dev-tunnel

This will start both the Cloudflare Tunnel and Flutter dev server, accessible at:

Test plan

  • Verify tunnel setup task completes successfully
  • Verify dev-tunnel task starts both services
  • Access the app via tunnel.cambeerfestival.app in a browser
  • Test CORS functionality from the tunnel domain
  • Verify graceful shutdown when stopping the dev-tunnel task

🤖 Generated with Claude Code

- Add tunnel.cambeerfestival.app to worker CORS allowed origins
- Add *.trycloudflare.com wildcard support for quick tunnels
- Create dev and dev-tunnel tasks in mise.dev.toml
- Add tunnel-setup task for one-time tunnel configuration
- Add .cloudflared/config.yml for tunnel configuration
- Update .gitignore to exclude tunnel credentials

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings December 8, 2025 09:59
@github-actions

github-actions Bot commented Dec 8, 2025

Copy link
Copy Markdown
Contributor

LCOV of commit c040001 during Flutter App CI/CD #583

Summary coverage rate:
  lines......: 60.9% (1513 of 2486 lines)
  functions..: no data found
  branches...: no data found

Files changed coverage rate: n/a

@codecov

codecov Bot commented Dec 8, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions

github-actions Bot commented Dec 8, 2025

Copy link
Copy Markdown
Contributor

🚀 Cloudflare Pages Preview

Your preview deployment is ready!

Preview URL: https://richardthe3rd-cloudflare-tun.staging-cambeerfestival.pages.dev

This preview will be automatically updated when you push new commits to this PR.

@richardthe3rd
richardthe3rd merged commit 33859b1 into main Dec 8, 2025
19 checks passed
@richardthe3rd
richardthe3rd deleted the richardthe3rd/cloudflare-tunnel branch December 8, 2025 10:06

Copilot AI left a comment

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.

Pull request overview

This PR adds Cloudflare Tunnel support to enable secure public HTTPS access to local development servers. The implementation provides automated setup tasks via mise and adds CORS configuration to support the tunnel domain. However, the PR introduces security concerns and portability issues that should be addressed before merging.

Key changes:

  • Adds Cloudflare Tunnel configuration with automated mise tasks for setup and running
  • Updates CORS configuration to allow the tunnel domain and quick tunnels
  • Moves the dev task from global to developer-specific configuration

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
.cloudflared/config.yml New tunnel configuration with hardcoded developer-specific credentials path
.gitignore Excludes tunnel credentials and certificates from version control
cloudflare-worker/worker.js Adds tunnel domain and wildcard quick tunnel CORS allowance to production worker
mise.toml Removes dev task (moved to mise.dev.toml)
mise.dev.toml Adds cloudflared tool, tunnel setup task, and combined dev-tunnel task

Comment thread .cloudflared/config.yml
Comment on lines +11 to +13

tunnel: cbf-dev-tunnel
credentials-file: /home/vscode/.cloudflared/be8d5634-735e-4637-b030-6f818e739b77.json

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

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

The hardcoded UUID in the credentials file path (be8d5634-735e-4637-b030-6f818e739b77.json) appears to be developer-specific and will differ for each developer who runs cloudflared tunnel create. This will cause the tunnel to fail for other developers.

The tunnel-setup task creates a tunnel, which generates a unique UUID for each tunnel instance. Since this UUID is different for every developer, the config file should either:

  1. Use a dynamic path that cloudflared can resolve automatically, or
  2. Include instructions in the config file comments for developers to update this value after running tunnel-setup, or
  3. Have the tunnel-setup task automatically update the config file with the correct UUID

Option 3 would provide the best developer experience.

Suggested change
tunnel: cbf-dev-tunnel
credentials-file: /home/vscode/.cloudflared/be8d5634-735e-4637-b030-6f818e739b77.json
# The credentials file is auto-resolved by cloudflared; do not hardcode the path.
tunnel: cbf-dev-tunnel

Copilot uses AI. Check for mistakes.
Comment thread .cloudflared/config.yml
Comment on lines +5 to +9
# 1. Login to Cloudflare: cloudflared tunnel login
# 2. Create the tunnel: cloudflared tunnel create cbf-dev-tunnel
# 3. Route DNS: cloudflared tunnel route dns cbf-dev-tunnel tunnel.cambeerfestival.app
# 4. Run the tunnel: cloudflared tunnel run cbf-dev-tunnel
#

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

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

[nitpick] The setup instructions in the comments reference manual cloudflared commands, but developers are expected to use the tunnel-setup mise task instead. The comments should be updated to reference the mise task for consistency:

# Setup instructions:
# Run the automated setup: MISE_ENV=dev ./bin/mise run tunnel-setup
#
# Or set up manually:
# 1. Login to Cloudflare: cloudflared tunnel login
# 2. Create the tunnel: cloudflared tunnel create cbf-dev-tunnel
# 3. Route DNS: cloudflared tunnel route dns cbf-dev-tunnel tunnel.cambeerfestival.app
# 4. Update credentials-file path below with your tunnel UUID
# 5. Run the tunnel: MISE_ENV=dev ./bin/mise run dev-tunnel
Suggested change
# 1. Login to Cloudflare: cloudflared tunnel login
# 2. Create the tunnel: cloudflared tunnel create cbf-dev-tunnel
# 3. Route DNS: cloudflared tunnel route dns cbf-dev-tunnel tunnel.cambeerfestival.app
# 4. Run the tunnel: cloudflared tunnel run cbf-dev-tunnel
#
# Recommended: Run the automated setup task:
# MISE_ENV=dev ./bin/mise run tunnel-setup
#
# Or set up manually (if needed):
# 1. Login to Cloudflare: cloudflared tunnel login
# 2. Create the tunnel: cloudflared tunnel create cbf-dev-tunnel
# 3. Route DNS: cloudflared tunnel route dns cbf-dev-tunnel tunnel.cambeerfestival.app
# 4. Update the credentials-file path below with your tunnel UUID
# 5. Run the tunnel: MISE_ENV=dev ./bin/mise run dev-tunnel
#

Copilot uses AI. Check for mistakes.
Comment thread mise.dev.toml
Comment on lines +53 to +55
echo ""
echo "Step 3: Setting up DNS route for tunnel.cambeerfestival.app..."
cloudflared tunnel route dns cbf-dev-tunnel tunnel.cambeerfestival.app

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

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

The DNS routing step runs unconditionally on every tunnel-setup execution, which could cause issues or confusion if the route already exists. Consider adding a check similar to the tunnel existence check:

# Check if DNS route already exists
if cloudflared tunnel route list 2>/dev/null | grep -q "tunnel.cambeerfestival.app"; then
  echo "✓ DNS route for tunnel.cambeerfestival.app already exists"
else
  echo ""
  echo "Step 3: Setting up DNS route for tunnel.cambeerfestival.app..."
  cloudflared tunnel route dns cbf-dev-tunnel tunnel.cambeerfestival.app
fi

This prevents duplicate route creation attempts and provides clearer feedback to developers.

Suggested change
echo ""
echo "Step 3: Setting up DNS route for tunnel.cambeerfestival.app..."
cloudflared tunnel route dns cbf-dev-tunnel tunnel.cambeerfestival.app
# Check if DNS route already exists
if cloudflared tunnel route list 2>/dev/null | grep -q "tunnel.cambeerfestival.app"; then
echo "✓ DNS route for tunnel.cambeerfestival.app already exists"
else
echo ""
echo "Step 3: Setting up DNS route for tunnel.cambeerfestival.app..."
cloudflared tunnel route dns cbf-dev-tunnel tunnel.cambeerfestival.app
fi

Copilot uses AI. Check for mistakes.
Comment thread mise.dev.toml
Comment on lines +68 to +83
# Wait for tunnel to be ready
echo "Waiting for tunnel to start..."
sleep 3

echo ""
echo "✅ Tunnel running at: https://tunnel.cambeerfestival.app"
echo ""
echo "Starting Flutter dev server on http://localhost:8080"
echo "Press Ctrl+C to stop both services."
echo ""

# Cleanup function
cleanup() {
echo ""
echo "Stopping tunnel..."
kill $TUNNEL_PID 2>/dev/null

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

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

The dev-tunnel task uses kill $TUNNEL_PID 2>/dev/null which may not properly clean up the cloudflared process if it has spawned child processes. Consider using kill -- -$TUNNEL_PID to kill the entire process group, or use a more robust cleanup mechanism.

Additionally, the 3-second sleep is arbitrary and may not be sufficient for the tunnel to fully start, especially on slower systems. Consider adding a retry loop that checks if the tunnel is actually responding:

# Wait for tunnel to be ready
echo "Waiting for tunnel to start..."
max_attempts=10
attempt=0
while ! curl -s -o /dev/null -w "%{http_code}" https://tunnel.cambeerfestival.app/health | grep -q "200"; do
  attempt=$((attempt + 1))
  if [ $attempt -ge $max_attempts ]; then
    echo "Tunnel failed to start after ${max_attempts} seconds"
    kill $TUNNEL_PID 2>/dev/null
    exit 1
  fi
  sleep 1
done

Copilot uses AI. Check for mistakes.
Comment on lines +240 to +250
// Allow Cloudflare Tunnel quick tunnels (*.trycloudflare.com)
// Used for local development with cloudflared tunnel
// Security note: These are temporary development tunnels controlled by Cloudflare.
// Only enable this in development/staging workers, not production.
if (origin.endsWith('.trycloudflare.com')) {
return {
'Access-Control-Allow-Origin': origin,
'Access-Control-Allow-Credentials': 'true',
};
}

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

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

The wildcard CORS allowance for *.trycloudflare.com is being added to the worker without any environment checks. According to the security note in the comment, this should "only enable this in development/staging workers, not production."

However, looking at cloudflare-worker/wrangler.toml, there's only one worker environment configured (ENVIRONMENT = "production"), and this worker is deployed directly to production via the GitHub workflow when changes are merged to main.

This creates a security risk where the production worker will allow CORS from any *.trycloudflare.com origin, which could potentially be exploited.

Recommended solutions:

  1. Remove this wildcard allowance if there's no separate dev/staging worker deployment, or
  2. Set up separate worker environments (dev/staging/production) with different CORS configurations, or
  3. Add runtime environment checks in the worker code to only enable this for non-production environments
Suggested change
// Allow Cloudflare Tunnel quick tunnels (*.trycloudflare.com)
// Used for local development with cloudflared tunnel
// Security note: These are temporary development tunnels controlled by Cloudflare.
// Only enable this in development/staging workers, not production.
if (origin.endsWith('.trycloudflare.com')) {
return {
'Access-Control-Allow-Origin': origin,
'Access-Control-Allow-Credentials': 'true',
};
}

Copilot uses AI. Check for mistakes.
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