DDEV and Cloudflare Tunnel cover image

DDEV and Cloudflare Tunnel

skeemer • March 29, 2024


I 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 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.


## Description: Share your project through Cloudflare Tunnel
## Usage: cloudflare
## Example: "ddev cloudflare"

cloudflared tunnel --url "$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.


Public hostname
Subdomain: loony-coon
Domain: leolutz.com
Path: stripe/webhook

URL: raccoon.ddev.site

Additional application settings
HTTP Settings
HTTP Host Header: raccoon.ddev.site