DDEV and Cloudflare Tunnel
skeemer • March 29, 2024
developmentI have finally figured out how to make DDEV and Cloudflare Tunnel work nicely together, thanks to stumbling across a year-old Reddit post by nzkller (Reddit).
What are they?
Cloudflare Tunnel is a free and easy way to expose locally run services to the internet. DDEV is an open source development environment (hosting), that I use every day to work on PHP projects.
Why Cloudflare when DDEV already has ngrok built-in?
The easy one is that Cloudflare is free while ngrok has been going through many pricing/feature changes the last couple of years. I've also found that Cloudflare offers me all the features I need without being unduly complicated to get set up.
How I use it
There are two ways that I use it, quick tunnels and named tunnels. I use quick tunnels for short-term sharing with colleagues. I use named tunnels for exposing webhooks, so I don't have to update the webhook address every time I work on a project.
1) Getting started
Follow the cloudflare guide to get your account set up, cloudflared installed and authenticated.
2a) Quick Tunnels
You can run cloudflared directly or create a command for DDEV to make it even easier.
cloudflared
cloudflared tunnel --url https://mysite.ddev.site --http-host-header mysite.ddev.site
As you can see, you have to duplicate the hostname to make it work. The --http-host-header option makes it possible for the ddev-router to understand the incoming request is for that particular project. Otherwise, you will just get a 404.
DDEV command
I created the file ~/.ddev/commands/host/cloudflare to make it much easier.
#!/bin/bash
## Description: Share your project through Cloudflare Tunnel
## Usage: cloudflare
## Example: "ddev cloudflare"
cloudflared tunnel --url "https://127.0.0.1/$DDEV_HOST_HTTPS_PORT" --http-host-header "$DDEV_SITENAME.$DDEV_TLD"
2b) Named Tunnels
For this, you do need a domain name available. In the Zero Trust dashboard, you can create a tunnel that is tied to your domain name and make multiple connections on that tunnel. This means that I can create loony-coon.leolutz.com that always tunnels to https://raccoon.ddev.site whenever the project is up. I primarily use this for webhooks, especially since they even allow restricting the path, for example /stripe/webhook. That means, whenever the project is running, my webhooks will work without changing any settings and the rest of the project isn't publicly available.
As with using --http-host-header for quick tunnels, you need to set up the HTTP host header for the named tunnels. On the Public Hostname Page, where you define the connection, you have to open Additional application settings and then HTTP Settings. Set the HTTP host header field with the local hostname.
Example
Public hostname
Subdomain: loony-coon
Domain: leolutz.com
Path: stripe/webhook
Service
Type: HTTPS
URL: raccoon.ddev.site
Additional application settings
HTTP Settings
HTTP Host Header: raccoon.ddev.site