SelfHostCorner

SelfHostCorner is a community of amazing hobbyists

We're a place where self hosters share, stay up-to-date and expand their knowledge. Join 41 of us!

Create account Log in
Cover image for Self Hosting and Securing Web Services Out of Your Home With Cloudflare Tunnel
Abe Hanoka
Abe Hanoka

Posted on • Originally published at habet.dev

Self Hosting and Securing Web Services Out of Your Home With Cloudflare Tunnel

Why a tunnel?

  • Opening up a port on a home network isn’t the greatest idea. It is a security risk, a hole waiting for a hacker/bot to sneak in using a known vulnerability.
  • Many ISP‘s and routers prevent you from opening up ports 80 and 443.
  • Another challenge you will face is setting up a dynamic DNS.
  • Finally, when your domain is pointing to your home IP address it is very easy to determine your home location.

Cloudflare’s Tunnel

This is where Cloudflare’s tunnel comes in. It builds a tunnel to cloudflares network. Now all request to your domain get directed through this tunnel to your web-server. all without opening any ports! and your domain simply points to cloudflare.

cloudflare logo

Pre-requisites

  • Assumes you already have a domain name configured to use Cloudflare’s DNS service. This is a totally free service.
  • Assumes you already have a Linux server with Nginx and Let’s Encrypt.

1. Install

First we will get cloudflared installed as a package to get everything going. Then we will transfer it over to a service that automatically runs on boot in the background and establishes a tunnel.

$ wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64.deb
$ sudo dkpg -i cloudflared-linux-arm64.deb
Enter fullscreen mode Exit fullscreen mode

*Note this link is for a raspberry pi, for other binaries see here.

This will create a folder in the home directory ~/.cloudflared.

2. Authenticate

Next, we need to authenticate with Cloudflare.

$ cloudflared tunnel login
Enter fullscreen mode Exit fullscreen mode

This will generate a URL which will take you to login into your dashboard on Cloudflare.

3. Create tunnel

$ cloudflared tunnel create <NAME>
Enter fullscreen mode Exit fullscreen mode

Replace <NAME> with any name of your choice.

Running this command will:

Confirm that the tunnel has been successfully created by running:

$ cloudflared tunnel list
Enter fullscreen mode Exit fullscreen mode

4. Create a configuration file

Now, create a configuration file in your .cloudflared directory. Using your favorite editor create a file config.yml, the content should look like this:

tunnel: <Tunnel-UUID>
credentials-file: /home/username/.cloudflared/<tunnel-UUID>.json
originRequest:
  originServerName: mydomain.com
ingress:
  - hostname: mydomain.com
    service: https://localhost:443
  - service: http_status:404 
Enter fullscreen mode Exit fullscreen mode

A couple of things to note, here:

  • Once the tunnel is up and traffic is being routed, Nginx will present the certificate for mydomain.com but cloudflared will forward the traffic to localhost which causes a certificate mismatch error. This is corrected by adding the originRequest and originServerName modifiers just below the credentials-file
  • Cloudflare’s docs only provide examples for HTTP requests, and also suggests using the url http://localhost:80. Although Nginx can handle 80 to 443 redirects, our ingress rules and ARGO will handle that for us. It’s not necessary to include any port 80 stuff.
  • if you want to host additional services via subdomain, just simply list them with port 443, like so:
 - hostname: subdomain1.mydomain.com
    service: https://localhost:443
  - hostname: subdomain2.mydomain.com
    service: https://localhost:443
Enter fullscreen mode Exit fullscreen mode

Just insure the last line is - service: http_status:404.

5. Modify your DNS zone

Now, we need to setup a CNAME for the TLD and any services we want. The cloudflared app handles this easily. The format of the command is:

$ cloudflared tunnel route dns <UUID or NAME> <hostname> 
Enter fullscreen mode Exit fullscreen mode

Do this for each service you want (i.e., subdomain1, subdomain2, etc) hosted through ARGO.

cloudflare dashboard

Cloudfalres DNS dashboard

6. Test the Tunnel

Run the tunnel to proxy incoming traffic from the tunnel to any number of services running locally on your origin.

$ cloudflared tunnel run <UUID or NAME>
Enter fullscreen mode Exit fullscreen mode

The above command as written (without specifying a config.yml path) will look in the default cloudflared configuration folder ~/.cloudflared and look for a config.yml file to setup the tunnel.

If everything’s working, the end of the output should be:

...
...
<timestamp> INF Connection <redacted> registered connIndex=0 location=ATL
<timestamp> INF Connection <redacted> registered connIndex=1 location=IAD
<timestamp> INF Connection <redacted> registered connIndex=2 location=ATL
<timestamp> INF Connection <redacted> registered connIndex=3 location=IAD
Enter fullscreen mode Exit fullscreen mode

Now, try to access your website and your service from outside your network – for example, a smart phone on cellular connection is an easy way to do this. If your webpage loads, SUCCESS!

7. Convert to a system service

You’ll notice if you Ctrl+C out of this last command, the tunnel goes down! That’s not great! We want it up all the time. To do that we turn cloudflared into a service.

$ sudo cloudflared service install
Enter fullscreen mode Exit fullscreen mode

Move the files to /etc/cloudflared

$ sudo mv ~/.cloudflared/* /etc/cloudflared/
Enter fullscreen mode Exit fullscreen mode

Check ownership with ls -la, should be root:root.

Now we need to fix the config file, replace the line:

$ credentials-file: /home/username/.cloudflared/<tunnel-UUID>.json
Enter fullscreen mode Exit fullscreen mode

with

$ credentials-file: /etc/cloudflared/<tunnel-UUID>.json
Enter fullscreen mode Exit fullscreen mode

Then, start the system service with the following command:

$ sudo systemctl start cloudflared
Enter fullscreen mode Exit fullscreen mode

And start on boot with:

$ sudo systemctl enable cloudflared
Enter fullscreen mode Exit fullscreen mode

Check the status with:

$ sudo systemctl status cloudflared
Enter fullscreen mode Exit fullscreen mode

The output should be similar to that shown in Step 6 above. You can safely delete your ~/.cloudflared directory.

Final Thoughts

We now have a web-server serving the internet without opening any ports on our network.

Credits:

Top comments (0)