Cloudflare tunnel + Laravel Herd = đź’–

Published on Feb 8, 2025

The Need and the Problem

When developing an application, there often comes a time when you need to connect to another service. Typically you usually have to specify a URL where the responses from that service will be sent. What if you're still in development and working from a laptop? How do you handle this?

With services like NGROK or Expose, you can solve this. Essentially, these services create a temporary link (URL) that connects your local network to the internet. This way, anyone with that link can access your application.

The problem with a temporary link is exactly that—it’s temporary. This means that every time the link changes, you have to manually update the URL in each service you're using.

If you just need to test a webhook once, this is fine—it’s quick and easy. However, if you have multiple integrations and frequently debug, it’s not practical to go through each service and update the temporary URL every time.

Recently, NGROK introduced the option to have a static URL, and most similar services offer this feature for a small subscription fee of $10-$20/month.

Personally, I’ve always found the idea of paying a monthly subscription for this a bit silly and wanted to avoid it. That’s why I explored the following solution with Herd and Cloudflare tunnel!

Laravel Herd

There are many ways to set up a development environment, and having tried most of them, I recently gave Laravel Herd Pro a chance. It promises a range of features and conveniences. The reasons I chose it are clear:

  • Everything I write is in Laravel.
  • I primarily work on a laptop, so the significant battery savings were a big deal.
  • It’s by far the easiest to use, with simple PHP version switching per project.
  • It allows you to easily set up and include databases like MongoDB, which I also needed.
  • With a click of a button you got valid SSL.
  • It has an embedded, very simple email catcher to view your emails, so I could get rid of similar dependencies.
  • Having easy access to the x-debugger is also a huge plus. When the time comes where x-debug is the only way to figure out what’s going wrong, you appreciate not having to struggle to install it.
  • The projects I work on are simple, and I don’t collaborate with other developers.

Is Herd the solution for everything?

Of course not.

As with everything in life, there’s no such thing as "the best solution for everything." It always depends on the problem you’re trying to solve.

At this point in time, given the way I work on my side projects, Laravel Herd Pro is simply sweet and to the point.

For example, ten years ago, when I was working intensively with Drupal CMS and needed an instant snapshot restore mechanism, a VirtualBox VM served me very well—anything else would have been the wrong choice for my situation. Similarly, if you’re working on a large or distributed project with microservices, Kafka, etc., and collaborating with ten other developers, you obviously need a solution like Docker.

Cloudflare Tunnel

I wasn’t aware of Cloudflare tunnel until recently. It was suggested to me by the Claude Sonnet AI model, and after taking a closer look, I realized it was exactly what I was looking for. It allows you to serve content from your laptop using an actual domain name, simply by running a command that opens a connection with cloudflare. And after a bit of effort, that’s exactly what I managed to do.

In case you are using a mac, I can share some setup instructions. If you use Linux please follow the official docs.

Install the cloudflare tunnel locally with this and login to cloudflare

brew install cloudflared
cloudflared login

Create a tunnel

cloudflared tunnel create tunnelName

Get the ID that was generated by using this command

cloudflared tunnel list

Configure the tunnel by updating the config.yml file that was generated

tunnel: <your-tunnel-id> 
credentials-file: /Users/<your-username>/.cloudflared/<tunnel-id>.json 

ingress: 
	- hostname: yourdomain.com 
    - service: http://yourdomain.test:80 
	- service: http_status:404

Finally create the CNAME record by executing this command

cloudflared tunnel route dns tunnelName yourdomain.com

Check that the record is there.

Only thing left is one command on your laptop that will instruct Laravel Herd to understand the incoming request and serve it the right way. Go to your laravel project folder and run

herd link yourdomain.com

You will see this link as yourdomain.com.test in your HERD UI, but ignore it.

Also if Cloudflare doesn't like that you don't have an SSL, just instruct HERD to make it secure.

Ready to rock and roll! From now on when you run

cloudflared tunnel run tunnelName

you are serving your development to the world under a real domain so you don't have to remember or change the temporary urls each time.

This is really sweet! Let's focus to the important things now!