Kirill Platonov
Kirill Platonov
Dec 22, 2021

Setting up Cloudflare Tunnel for development

Cloudflare Tunnel is a free alternative to Ngrok that allows publicly exposing your local web server. Usually, it’s used in development for testing webhooks or some third-party APIs that require public URLs. In my case, I use it for Shopify Apps development.

One of the biggest benefits of Cloudflare Tunnel is that it allows using custom domains with tunnels for free. This way you can have a permanent public URL which is much better than random URLs in Ngrok’s free plan. Another benefit is that you can store tunnel configuration inside git repository next to your app so your team members may start tunnels without any additional setup and without a Cloudflare account. Let’s take a look at how you can set things up.

Step 1: Domain

First thing first you’ll need a domain that will be used to start tunnels for development. I use separate platmart.dev domain for that and have tunnels on subdomains: [app-name].platmart.dev. Once you get it you’ll need to create a Cloudflare account and add you dev domain to it: Creating a Cloudflare account and adding a website

Step 2: Setup CLI

Next you’ll need to setup a CLI for Cloudflare Tunnel. It’s called cloudflared. For macOS you can install it via homebrew (for other operating systems check installation options):

brew install cloudflare/cloudflare/cloudflared

After that run:

cloudflared tunnel login

It will open browser and prompt you to login into you Cloudflare account. Select your dev domain from Step 1. This will generate account certificate in ~/cloudflared/cert.pem.

Step 3: Create tunnel

To create your first tunnel run:

cloudflared tunnel create <Tunnel-NAME>

This will create new tunnel and save it’s credentials in ~/.cloudflared/<Tunnel-UUID>.json. Now create a subdomain for this tunnel:

cloudflared tunnel route dns <Tunnel-NAME> <SUBDOMAIN>

It will create CNAME record for your dev domain and point it to tunnel.

Step 4: Connect to app

Time to connect tunnel to the app. Create .cloudflared folder inside app.

Add .cloudflared/credentials.json and copy tunnel credentials to it from ~/.cloudflared/<Tunnel-UUID>.json.

Create .cloudflared/config.yml file with the following content:

tunnel: <Tunnel-UUID>
credentials-file: .cloudflared/credentials.json
noTLSVerify: true

Add bin/tunnel file inside app with the following content:

#!/usr/bin/env bash

cloudflared tunnel --config .cloudflared/config.yml --url localhost:3000 run <Tunnel-NAME>

And set execute permissions for bin/tunnel:

chmod +x bin/tunnel

Replace 3000 port with your app’s port if needed. Commit these changes to git repository.

Step 5: Run the tunnel

To run the tunnel inside app folder call:

bin/tunnel

This command will start the tunnel. You team mates will only need to download cloudflared CLI tool. They won’t need to login to Cloudflare or have certificate to start a tunnel.

To view the list of all tunnels with their statuses you’ll need to create a free Cloudflare for Teams account here. Then go to “Access” > “Tunnels” page:

Bonus: Multiple tunnels per app

When working with team single tunnel won’t be enough. Not a big problem. We can create additional tunnels and use them in a similar way. Every new tunnel will have incremental suffix -N added to it’s name:

cloudflared tunnel create <Tunnel-NAME>-2
cloudflared tunnel route dns <Tunnel-NAME>-2 <SUBDOMAIN>-2

Credentials file will have a suffix too: .cloudflared/credentials-2.json.

And .cloudflared/config-2.yml as well:

tunnel: <Tunnel-UUID>-2
credentials-file: .cloudflared/credentials-2.json
noTLSVerify: true

The biggest change will be in bin/tunnel file:

#!/usr/bin/env bash

while getopts ":n:" opt; do
  case ${opt} in
    n)
      echo "Running tunnel #$OPTARG"
      suffix="-${OPTARG}"
      ;;
    :)
      echo "Invalid option -$OPTARG: specify a tunnel number" 1>&2
      exit 1
      ;;
  esac
done

cloudflared tunnel --config .cloudflared/config${suffix}.yml --url localhost:3000 run <Tunnel-NAME>${suffix}

With this setup we can start default tunnel using:

$ bin/tunnel

And to start additional tunnels we can add -n option with tunnel number:

$ bin/tunnel -n 2
Running tunnel #2

With this setup you can have as many tunnels as you need. All of them will have permanent public URL and they can be easily used by your team members without additional setup. And it’s all free!

If want to hear more from me follow me on Twitter. I tweet about my journey of building and growing Shopify apps and about Ruby on Rails development.