If you’ve ever self-hosted services on your local network and wanted to expose them to the world, you would know that this is not a straightforward matter. This involves opening up your firewall by forwarding ports 80 (HTTP) and 443 (HTTPS) to a dedicated machine on your network. This has two main issues. Problem 1: your external IP address will be publically visible to the internet meaning that people could geolocate and collect information about you. Problem 2: depending on your ISP, your external IP may change from time to time meaning that you’ll have to periodlicly update your DNS records to point your domain to the right IP address.
One way to get round this would be to set up a public facing server with a static IP address (you can do this with DigitalOcean, Vultra, Linode, etc) and to expose services using WireGuard (to connect your servers) and a reverse proxy (to route traffic to the right service) such as nginx. While this solution does cost you a little bit of money, it also involves setting up a WireGuard VPN which isn’t exactly straightforward.
What if I told you there was an easier and more secure way of doing things which is both free and secure at the same time.
Introducing Cloudflare Tunnels
Cloudflare Tunnels is a feature provided by the Cloudflare DNS service. The benefits of this service is that its secure, easy to setup and it free! Because Cloudflare is so well known and has a good reputation, it’s fair to say that you’re in safe hands.
Much like the Wireguard solution mentioned earlier, Cloudflare tunnels use secure, outward connecting tunnels meaning that it is possible to expose services (such as a web server on a Raspberry Pi within your home network) to the rest of the world without putting your internal network at risk by modifying your firewall settings.
How to create a tunnel
Step 0: Intergrate domain with CloudFlare
If you’ve not done so already, make sure you set your domain nameservers to the ones used by Cloudflare. This can be done using the your domain registrar’s control panel. Click here to find out how to do this.
Step 1: Download and Install cloudflared
To get thing going, you will need to download and install the latest
cloudflared package from here. The installation process is fairly straightforward so I won’t be covering this here.
For Raspberry Pi only:
If you plan on using a Raspberry Pi, you will need to download the ARM-based binaries from this link. This can be done with the following commands.
<s>tar -xvzf cloudflared-stable-linux-arm.tgz</s>
<s>sudo cp ./cloudflared /usr/local/bin</s>
<s>sudo chmod +x /usr/local/bin/cloudflared</s>
EDIT: Cloudflare now support ARM64 binaries. Click here for the full releases and select
Step 2: Configure cloudflared
Before we start creating tunnels, we need to make sure that we’re running the latest version of cloudflared.
Once it has been updated, we need to associate cloudflared with our account.
cloudflared tunnel login
After running this you’ll be prompted to login into your account with a URL generated by
<kbd>cloudflared</kbd>. This will allow you to select the domain you which to use tunnels with.
Step 3: Create a Tunnel
Creating a tunnel is really easy. Just run the following and replace <NAME> with the name you wish to address your tunnel. You can create as many or as little as you want! There’s no limit to how many tunnels you can have with Cloudflare.
cloudflared tunnel create <NAME>
Step 4: Route a Tunnel
Now that we’ve created the tunnel, we need to route the tunnel to the domain name we which to host our service on. This can be done with the following where we replace <NAME> with the name we used previously and <DOMAIN NAME> with the specific domain (provided it is a domain within our DNS records).
cloudflared tunnel route dns <NAME> <DOMAIN NAME>
At this stage, you should get a UUID. Make a note of this as we’ll need it later. You’ll be able to find this in your DNS CNAME records against the domain you just used above.
To ensure that things are running smoothly, we can perform a test run by exposing a local service running on our machine. Again, you just need to replace <NAME> with your tunnel name and <PORT> with the port of the service you which to expose.
cloudflared tunnel run --url localhost:<PORT> <NAME>
If you head over to your domain name, we should find that it has now been exposed to the world. Congrats!
Step 5: Create a Config File
If you want to ensure that the tunnel starts on boot and runs in the background, we need to make a custom ingress config file. Feel free to use the template bellow to get things going. Make sure you replace the variables with your values where appropriate.
tunnel: <NAME> credentials-file: /root/.cloudflared/<UUID>.json ingress: - service: http://localhost:<PORT>
Make sure that you save this file in the following directory:
With this now set up, all we need to do is install the systemd service with the following
cloudflared --config /etc/cloudflared/config.yml service install
systemd, you can enable (start on boot) and start the tunnel using the following commands
systemctl enable cloudflared
systemctl start cloudflared
If you which to host more than one service on a device, click here for more complex ingress config files.
Overall, this blog post goes though everything you need to know about creating and running custom tunnels. If you followed these steps correctly you should have a successful tunnel up and running. Let your self-hosting journey begin! Let me know what you plan on hosting in the comments!