Getting started with Cloudflare Tunnel

Occasionally we need to expose our local development projects to the internet. Whether it's for testing webhooks, sharing our work with clients, or collaborating with remote team members, having a secure and reliable way to make our local projects accessible is crucial. For years, ngrok and Expose has been my go-to tools, but I recently discovered a powerful alternative: Cloudflare Tunnel.

Getting started with Cloudflare Tunnel

Why I Switched to Cloudflare Tunnel

I've used ngrok for tunneling for a long time. But when I recently was working on a Shopify project, I discovered Cloudflare Tunnel. Shopify extensions uses this by default for connecting you local development environment to your development test store. After looking into it more, I found some good reasons to use Cloudflare Tunnel:

  1. It's Completely Free: Unlike ngrok, which requires a paid plan for many features, like serving multiple projects at the same time, Cloudflare Tunnel is free to use, even for advanced features.
  2. Static URLs: With a domain configured on Cloudflare, I can set up static URLs for my projects. This makes sharing and remembering project URLs so much easier.
  3. Built-in Security: Cloudflare Tunnel uses outbound-only connections, which means I don't need to open any ports in my firewall. This gives me peace of mind when exposing local services.

Free to Use, Even for Advanced Features

One of the biggest draws of Cloudflare Tunnel is that it's free to use. This isn't just a basic free tier with limited functionality - you get access to all features without any cost. Here's what this means for developers:

  • No usage limits: You can create as many tunnels as you need without worrying about hitting a cap.
  • All features included: Unlike ngrok, where features like custom subdomains are locked behind a paywall, Cloudflare Tunnel gives you everything out of the box.

This makes Cloudflare Tunnel an excellent option for developers.

Static URLs Make Sharing Easier

Setting up static URLs is really useful, especially when you're often sharing your work with clients or team members. Here's why it's great:

  • Same URL every time: Once you set up a static URL, it stays the same whenever you start your tunnel. You don't need to send new URLs and ports each time you restart your project.
  • Looks better: Custom subdomains (like https://preview.einarhansen.dev) look nicer and are easier to remember than random strings from other tunneling services.
  • Easier setup: For things like webhooks that need a fixed URL, you only need to set it up once.
  • Works well with Shopify: In my case, I don't need to change the dev store URL in the Shopify Partners dashboard every time the tunnel restarts or gets a new port.

This feature has saved me a lot of time and made working with others much smoother.

Built-in Security with Outbound-Only Connections

Security is paramount when exposing local services to the internet, and this is where Cloudflare Tunnel really shines. The outbound-only connection model provides several security benefits:

  • No open inbound ports: Traditional methods often require you to open ports in your firewall, which can be a security risk. Cloudflare Tunnel eliminates this need entirely.
  • Encrypted connections: All traffic between your local environment and Cloudflare's edge network is encrypted using TLS.
  • Reduced attack surface: By not exposing your origin server directly to the internet, you significantly reduce the potential attack vectors.

This security model gives me peace of mind when I need to expose internal services temporarily to the internet.

Setting Up Cloudflare Tunnel: A Step-by-Step Guide

Let's walk through the complete process of setting up Cloudflare Tunnel for your local development environment. This guide assumes you're using macOS, but the steps are similar for other operating systems.

Step 1: Sign Up for a Cloudflare Account

If you don't already have one, start by signing up for a free Cloudflare account at https://dash.cloudflare.com/sign-up.

Step 2: Transfer Your Domain to Cloudflare

To use Cloudflare Tunnel with a custom domain, you'll need to transfer your domain's DNS management to Cloudflare:

  1. Log in to your Cloudflare account.
  2. Click "Add a Site" and enter your domain name.
  3. Select the free plan.
  4. Follow the instructions to update your domain's nameservers with your domain registrar.

This process can take up to 24 hours to complete, but from my experience it takes about 15 minutes.

Step 3: Install cloudflared

Now, let's install the cloudflared daemon. On macOS, you can use Homebrew. For other operating systems, check the official Cloudflare documentation.

bash
brew install cloudflared

Step 4: Authenticate cloudflared

Run the following command to authenticate cloudflared with your Cloudflare account:

bash
cloudflared tunnel login

This will open a browser window where you can log in to your Cloudflare account and authorize the tunnel.

Step 5: Create a Tunnel

Now, let's create a named tunnel, in this case for einarhansen.dev:

bash
cloudflared tunnel create <project-name>
# example:
cloudflared tunnel create einarhansen.dev

This command will create a tunnel and generate a credentials file.

Step 6: Create a DNS Route

Create a DNS route for your tunnel using the CLI:

bash
cloudflared tunnel route dns <project-name> <hostname>
# example:
cloudflared tunnel route dns einarhansen.dev preview.einarhansen.dev

This command creates a CNAME record in your Cloudflare DNS settings, pointing your chosen subdomain to your tunnel.

Step 7: Configure Your Tunnel

Next, you need to find the tunnel ID and the credentials file for your project. Here's how:

  1. List your tunnels by running:
bash
cloudflared tunnel list

Copy the UUID from the ID column for your tunnel.

  1. Find the credentials file by listing the contents of the Cloudflare directory:
bash
ls -la ~/.cloudflared

Look for a file named <tunnel-id>.json. This is your credentials file.

Step 8: Create Your Configuration File

Now it's time to create the configuration file for your tunnel. Follow these steps:

  1. Navigate to your ~/.cloudflared directory (remember to show hidden files if you are using Finder).

  2. Create a new file named config.yml using any text editor you prefer. This file will configure the tunnel to route traffic from a given origin to the hostname of your choice.

  3. Add the following content to your config.yml file:

~/.cloudflared/config.yml
yaml
tunnel: <YOUR-TUNNEL-ID>
credentials-file: /path/to/your/credentials-file.json

ingress:
- hostname: <hostname>
  service: http://localhost:8000
- service: http_status:404
  1. Replace <YOUR-TUNNEL-ID> with the UUID you copied in Step 7.

  2. Update the credentials-file path to match the location of your .json credentials file (also from Step 7). Use the full path, e.g., /Users/einar/.cloudflared/<tunnel-id>.json.

  3. Adjust the hostname to match your desired subdomain and domain. It should match the CNAME record you created in Step 6. In my case, it's preview.einarhansen.dev.

  4. Modify the service URL to match the local address and port where your application is running.

Here's an example of a config.yml file if we are running a Next.js project on port 3000 and a static site on port 8880. Remember to run Step 6 to create a DNS record for all the domains you add in the config:

~/.cloudflared/config.yml
yaml
tunnel: <YOUR-TUNNEL-ID>
credentials-file: /path/to/your/credentials-file.json
tunnel: de43418a-5173-476c-9a8f-2f68b567f2ed
credentials-file: /Users/einar/.cloudflared/de43418a-5173-476c-9a8f-2f68b567f2ed.json

ingress:
- hostname: <hostname>
  service: http://localhost:8000
- hostname: preview.einarhansen.dev
  service: http://localhost:8080
- hostname: nextjs.einarhansen.dev
  service: http://localhost:3000
- service: http_status:404

This configuration allows you to route traffic to multiple local services using different subdomains.

Step 9: Start Your Tunnel

With your configuration file in place, you can now start your tunnel. Run the following command:

bash
cloudflared tunnel --config ~/.cloudflared/config.yml run

And there you have it! Your local project is now accessible at https://preview.einarhansen.dev. You can share this URL with anyone, and they'll be able to access your local project securely.

Wrapping Up

Cloudflare Tunnel has become an indispensable tool in my development workflow. It's free, secure, and offers the flexibility of static URLs, making it a compelling alternative to ngrok. The initial setup might seem a bit more involved compared to ngrok, but the benefits are well worth it, especially for long-term projects or when you need persistent, custom subdomains.

Give it a try in your next project, and let me know on x.com how it works for you! Remember, while Cloudflare Tunnel is powerful, always be cautious about what you expose to the internet. Ensure you're not accidentally sharing sensitive information, and don't run your app in debug mode while exposing it to the internet.

Happy tunneling!

Stay up to date

Get notified when I publish something new, and unsubscribe at any time.