Expose your local development environment with Cloudflare Tunnels
Need to expose your local development environment to someone outside of your network? Cloudflare Tunnels is a free and fast alternative to popular tools like ngrok and localtunnel. You can easily access your local machine from anywhere. Plus, it outperforms the competition in terms of speed.
Have you ever needed to show your local development environment to someone who is not in the same network as you? Most likely to show something to a Product Owner or to test if a social media integration worked correctly.
Because of NAT and firewalls, you can't just send your machine's IP to someone else to access it. This is where tunneling tools come into play. The most known ones are ngrok and localtunnel.
They work but their free tiers slow or block parallel requests. A capability that has become a must have with modern bundlers like Vite as they create a plethora of parallel requests.
What's the alternative?
Cloudflare tunnels can also expose your local dev setup. It's free, faster and works without having to register.
To get it running, you'll need to install their cli tool.
Install cloudflared
On MacOS, the easiest way to cloudflared
is with brew.
brew install cloudflared
For windows and linux based operating systems, there are binaries available here.
Forwarding a local port
To forward a specific port running on your machine, execute the following line
cloudflared --url http://localhost:8000
replace 8000
with the port you want to forward. cloudflared
will then output the URL you can use to access your local machine. In our case it's https://recreation-camps-usr-continental.trycloudflare.com
The full output of the command is
cloudflared --url http://localhost:8000
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
Requesting new quick Tunnel on trycloudflare.com...
+--------------------------------------------------------------------------------------------+
| Your quick Tunnel has been created! Visit it at (it may take some time to be reachable): |
| https://recreation-camps-usr-continental.trycloudflare.com |
+--------------------------------------------------------------------------------------------+
Cannot determine default configuration path. No file [config.yml config.yaml] in [~/.cloudflared ~/.cloudflare-warp ~/cloudflare-warp /etc/cloudflared /usr/local/etc/cloudflared]
Version 2023.5.0
GOOS: darwin, GOVersion: go1.19.8, GoArch: arm64
Settings: map[ha-connections:1 protocol:quic url:http://localhost:8000]
Generated Connector ID: 48eb60ba-646f-4847-9173-c4ed98d5e326
cloudflared will not automatically update if installed by a package manager.
Initial protocol quic
ICMP proxy will use 192.168.20.116 as source for IPv4
ICMP proxy will use fe80::109a:88d9:c4f:7dda in zone en0 as source for IPv6
Created ICMP proxy listening on 192.168.20.116:0
Created ICMP proxy listening on [fe80::109a:88d9:c4f:7dda%en0]:0
Starting metrics server on 127.0.0.1:54026/metrics
Registered tunnel connection connIndex=0 connection=8e16208a-4334-451a-bfba-19e82e90c934 event=0 ip=198.41.200.193 location=SIN protocol=quic
How much better is it?
To compare the performance, I set up a test scenario serving a 30kb text file through each tunnel and requested it 100 times with a concurrency of 5 using Apache Bench:
ab -n 100 -c 5 [URL]
The results confirm my suspicion of cloudflared
being faster than the competition:
Service | time to completion | failed requests | median time | longest request |
---|---|---|---|---|
cloudflared | 8.895s | 0 | 445ms | 762ms |
localtunnel | 48.171s | 0 | 2408ms | 5331ms |
ngrok | 10.181s | 70 | 509ms | 4411ms |
While ngrok
is also quite fast, it starts blocking requests quickly in their free tier whereas localtunnel
just starts to slow you down. With cloudflared
no slowdown occurs and no requests are blocked. The concrete test results can be found at the bottom of this article.
Conclusion
- faster responses
- easy to set up
- no time limitation (as with ngrok)
Using cloudflared
is faster and it's easy to set up. Try out Cloudflare Tunnels today and experience the benefits for yourself!
If you found this article helpful, please share it with your colleagues and friends!
Bonus: Shorthand
If cloudflared --url
is too long for you, here's a way to make it even shorter:
Mac OS
echo "alias tunnel='cloudflared --url'" >> ~/.zshrc
Linux / WSL
echo "alias tunnel='cloudflared --url'" >> ~/.bashrc
To forward a port, just type
tunnel http://localhost:8000
Testdata
Cloudflared
Concurrency Level: 5
Time taken for tests: 8.895 seconds
Complete requests: 100
Failed requests: 0
Total transferred: 3047200 bytes
HTML transferred: 3022600 bytes
Requests per second: 11.24 [#/sec] (mean)
Time per request: 444.775 [ms] (mean)
Time per request: 88.955 [ms] (mean, across all concurrent requests)
Transfer rate: 334.53 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 79 159 65.4 151 607
Processing: 107 253 116.7 205 589
Waiting: 98 183 87.0 147 520
Total: 237 412 139.8 380 762
Percentage of the requests served within a certain time (ms)
50% 380
66% 458
75% 514
80% 544
90% 635
95% 713
98% 747
99% 762
100% 762 (longest request)
Localtunnel
Concurrency Level: 5
Time taken for tests: 48.171 seconds
Complete requests: 100
Failed requests: 0
Total transferred: 3055200 bytes
HTML transferred: 3022600 bytes
Requests per second: 2.08 [#/sec] (mean)
Time per request: 2408.552 [ms] (mean)
Time per request: 481.710 [ms] (mean, across all concurrent requests)
Transfer rate: 61.94 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 834 1026 254.9 916 1897
Processing: 869 1258 538.1 1176 4422
Waiting: 566 671 187.9 608 1726
Total: 1752 2284 611.3 2097 5331
Percentage of the requests served within a certain time (ms)
50% 2097
66% 2272
75% 2518
80% 2622
90% 3040
95% 3757
98% 4240
99% 5331
100% 5331 (longest request)
ngrok
Concurrency Level: 5
Time taken for tests: 10.181 seconds
Complete requests: 100
Failed requests: 70
(Connect: 0, Receive: 0, Length: 70, Exceptions: 0)
Non-2xx responses: 70
Total transferred: 1013080 bytes
HTML transferred: 987420 bytes
Requests per second: 9.82 [#/sec] (mean)
Time per request: 509.031 [ms] (mean)
Time per request: 101.806 [ms] (mean, across all concurrent requests)
Transfer rate: 97.18 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 149 240 428.0 179 3249
Processing: 44 241 718.6 66 4236
Waiting: 42 142 426.7 60 4168
Total: 201 482 880.0 252 4411
Percentage of the requests served within a certain time (ms)
50% 252
66% 272
75% 335
80% 356
90% 471
95% 3861
98% 4402
99% 4411
100% 4411 (longest request)