Hills 🏔 and Skills, What's Common?

They both need you to be on top.

Cohort-1 just ended. You will get:

All yours, just at:


Cloudflare Tunnel Tutorial — A better alternative to ngrok

Updated on
friendship ended with ngrok, cloudflare tunnel is my new best friend

Finally a good alternative to ngrok.

No public IP address? No problem. Cloudflare Tunnel has your back.

In this tutorial we will learn how to easily install and setup Cloudflare Tunnel / Cloudflared CLI on your Windows, Linux or macOS. You’ll also learn how to setup custom domains to route traffic to your local server without exposing your IP address.

What is Cloudflare Tunnel?

Cloudflare Tunnel is service which allows your local network to be exposed on the internet. Previously we had services like ngrok and localhost.run, now we have Cloudflare Tunnel as an alternative to ngrok.

What do you need to use Cloudflare Tunnel?

Not even a Cloudflare account.

All you need is to install Cloudflared CLI, the CLI which connects our local server to Cloudflare server.

Install Cloudflared CLI

Installing Cloudflared or Cloudflare tunnel CLI is fast as light.

Install Cloudflared CLI on Linux

Arch Linux

sudo pacman -Syu cloudflared


Show instructions
  1. Add Cloudflare GPG key:
sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
  1. Add this repo to your apt repositories:
echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared jammy main' | sudo tee /etc/apt/sources.list.d/cloudflared.list
  1. Install cloudflared:
sudo apt-get update && sudo apt-get install cloudflared

Other Linux installation

Install Cloudflared CLI on MacOS

With Homebrew it’s just one command to rule:

brew install cloudflare/cloudflare/cloudflared

Install Cloudflared CLI on Windows

With winget it’s never been this easy to install packages:

winget install --id Cloudflare.cloudflared

Expose local server with Cloudflare Tunnel CLI

Once you have the cloudflared CLI installed, all you need is this command to expose your local server:

cloudflared tunnel --url localhost:8080

Replace localhost:8080 with your server address and port.

Test hello world server

If you don’t have a server running and you just want to see if Cloudflare tunnel works in your system, you can use the --hello-world argument to run the demo server.

cloudflared tunnel --hello-world

Command output

You’ll get your tunnel link just like ngrok and with other output like this from the cloudflared command:

INF Thank you for trying Cloudflare Tunnel. Doing so, without a Cloudflare account, is a quick way to experiment and try it out. However, be aware that these account-less Tunnels have no uptime guarantee. If you intend to use Tunnels in production you should use a pre-created named tunnel by following: https://developers.cloudflare.com/cloudflare-one/connections/connect-apps
INF Requesting new quick Tunnel on trycloudflare.com...
INF +--------------------------------------------------------------------------------------------+
INF |  Your quick Tunnel has been created! Visit it at (it may take some time to be reachable):  |
INF |  https://corporate-mention-tiles-coordinates.trycloudflare.com                             |
INF +--------------------------------------------------------------------------------------------+

If you open the link this is what you’ll see a page with Congrats! You created a tunnel!:

cloudflared hello world page

Login to Cloudflare to Get Custom Domains

Wouldn’t it be great if we could have tunnel.learnaw.io which will expose my local dev server?

We couldn’t get free custom or static domains before.

After the launch of Cloudflare Tunnel ngrok announced free static domain.

Setup website on Cloudflare

If you don’t a website setup on Cloudflare you’ll need to do that before we proceed.

  1. Create your free account on Cloudflare
  2. Create and setup your website DNS
  3. Update your nameservers to point to Cloudflare

Login to Cloudflare Tunnel CLI

Once we have setup our website on cloudlfare we can now login to cloudlared CLI with:

cloudflared tunnel login
  1. You’ll be redirected to Cloudflare dashboard, if not open the link manually.
  2. You’ll have to select your site by clicking on it.
  3. Authorize it by clicking on Authorize button.
cloudflared tunnel authorized

You’ll see You have successfully logged in:

 cloudflared tunnel login 
A browser window should have opened at the following URL:


If the browser failed to open, please visit the URL above directly in your browser.
2023-09-14T08:24:07Z INF Waiting for login...
You have successfully logged in.
If you wish to copy your credentials to a server, they have been saved to:

Create a tunnel and configure it

Create tunnel

Using the cloudflared tunnel create command we create a tunnel for us which will generate config file in ~/.cloudflared directory.

cloudflared tunnel create learnaws

This gives us the UUID of the tunnel as well:

❯ cloudflared tunnel create learnaws
Tunnel credentials written to /home/shivam/.cloudflared/7d1edf62-1efe-4a5c-a2ea-b66a5b6d34a8.json. cloudflared chose this file based on where your origin certificate was found. Keep this file secret. To revoke these credentials, delete the tunnel.

Created tunnel learnaws with id 7d1edf62-1efe-4a5c-a2ea-b66a5b6d34a8

Verify the tunnel you created by listing tunnels

With cloudflared tunnel list command you can see all the tunnels you’ve created.

 cloudflared tunnel list                                         
You can obtain more detailed information for each tunnel with `cloudflared tunnel info <name/uuid>`
ID                                   NAME     CREATED              CONNECTIONS               
7d1edf62-1efe-4a5c-a2ea-b66a5b6d34a8 learnaws 2023-09-14T08:38:26Z 1xbom06, 1xbom12, 2xdel03 

Add Subdomain for your tunnel

Now we need to add DNS record which will route traffic to our tunnel.

With cloudflared CLI we can easily do that with tunnel route dns command:

cloudflared tunnel route dns learnaws tunnel

On successful DNS creation you’ll receive the message saying: Added CNAME tunnel.learnaws.io which will route to this tunnel tunnelID=7d1edf62-1efe-4a5c-a2ea-b66a5b6d34a8

Create tunnel config file

Default cloudflared directory location for config file:

OSPath to default directory
macOS and Unix-like systems~/.cloudflared, /etc/cloudflared, and /usr/local/etc/cloudflared, in this order.

Inside the cloudflared config directory we create a config file config.yaml and specify where to route the traffic.

  1. cd ~/.cloudflared/
  2. vim config.yaml
  3. Edit your config in the format below
  4. Save your file :wq
tunnel: your-tunnel-uuid
credentials-file: /home/shivam/.cloudflared/your-tunnel-uuid.json
# define hostname matching 
  - hostname: tunnel.learnaws.io
	# proxy request to localhost:3000
	service: http://localhost:3000
	# if nothing is matched return 404
  - service: http_status:404

Read more on config files and syntax on the Cloudflare docs.

Ingress Supported services

Cloudflare tunnel supports many protocols including HTTP/S, you can use the list below to see what services you can connect with it. Learn more about Ingress configuration on the official docs.

ServiceDescriptionExample service value
HTTP/SIncoming HTTP requests are proxied directly to your local service.https://localhost:8000
HTTP over Unix socketJust like HTTP, but using a Unix socket instead.unix:/home/production/echo.sock
HTTPS over Unix socketJust like HTTPS, but using a Unix socket instead.unix+tls:/home/production/echo.sock
TCPTCP connections are proxied to your local service.tcp://localhost:2222
SSHSSH connections are proxied to your local service. https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/use-cases/ssh/.ssh://localhost:22
RDPRDP connections are proxied to your local service. https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/use-cases/rdp/.rdp://localhost:3389
kubectl bastion modecloudflared will act like a jumphost, allowing access to any local address.bastion
Hello WorldTest server for validating your Cloudflare Tunnel setup.hello_world
HTTP statusResponds to all requests with the given HTTP status.http_status:404

Start Cloudflare Tunnel

To start serving request use cloudflared tunnel run and it’ll start proxy server on your custom domain.

❯ cloudflared tunnel run                                     
Starting tunnel tunnelID=7d1edf62-1efe-4a5c-a2ea-b66a5b6d34a8
Version 2023.8.2
GOOS: linux, GOVersion: go1.20.7, GoArch: amd64
Settings: map[cred-file:/home/shivam/.cloudflared/7d1edf62-1efe-4a5c-a2ea-b66a5b6d34a8.json credentials-file:/home/shivam/.cloudflared/7d1edf62-1efe-4a5c-a2ea-b66a5b6d34a8.json]
cloudflared will not automatically update if installed by a package manager.
Generated Connector ID: a50c77ff-bbb0-41ff-9ae2-f112a54c2245
Initial protocol quic
ICMP proxy will use as source for IPv4
ICMP proxy will use 2405:201:4028:e83f:5fb6:484f:25b:5322 in zone enp58s0 as source for IPv6
Starting metrics server on
Registered tunnel connection connIndex=0 connection=cc36911b-

Now if you go to your subdomain eg. tunnel.learnaws.io you’ll see the output from server:

learnaws.io tunnel output from json server

Here I am simply running a server which returns JSON.

Run Cloudflare Tunnel all the time as a service

If we close our terminal our tunnel will be stopped as well, if we want to keep the tunnel running we can use cloudflared service.

Install cloudflared service

sudo cloudflared --config ~/.cloudflared/config.yml service install

On successful install you’ll see the message:

2023-09-14T09:23:07Z INF Using Systemd
2023-09-14T09:23:09Z INF Linux service for cloudflared installed successfully

Update config file

The service might take config file from /etc/cloudflared/config.yml, to change the location you can edit the service config file with your default location eg. ~/.cloudflared/config.yml).

sudo vim /etc/systemd/system/cloudflared.service;

Make sure to reload daemon and restart your service after updating the service file:

sudo systemctl daemon-reload
sudo systemctl restart cloudflared

Start cloudflared service

systemctl start cloudflared

Check the service status

systemctl status cloudflared

You should see it as active and running:

cloudflared.service - cloudflared
     Loaded: loaded (/etc/systemd/system/cloudflared.service; enabled; preset: disabled)
     Active: active (running) since Thu 2023-09-14 14:53:09 IST; 4min 15s ago
   Main PID: 48301 (cloudflared)
      Tasks: 16 (limit: 18921)
     Memory: 21.1M
        CPU: 201ms
     CGroup: /system.slice/cloudflared.service
             └─48301 /usr/bin/cloudflared --no-autoupdate --config /etc/cloudflared/config.yml tunnel run

Now even if you restart your system or close all your terminals your tunnel will keep running in the background.

MacOS and Windows service

You can find documentation on how to configure the services on your OS:

Cloudflared CLI commands to Keep Handy

You might be experimenting with Cloudflare Tunnels by creating them, setting up multiple routes and tunnels, listing the tunnels and what not.

Head over to the official page for useful tunnel commands to see the complete list for commands.

Spit out your coffee NOW!

When are you sharing this amazing tool with your dev circle? It’s now or never. They’ll thank you for making their life so much easier.

Tried out my guide and have some insights to share? Comment below and I’ll reply fast.

No more ngrok!