Overview

Exposing your local network services to the public is a common requirement. For example, you might want to access the qBittorrent management web interface to launch new download tasks while away from home. To achieve this, you can use Cloudflare Tunnel, a mostly free and secure solution! This post will guide you through setting up Cloudflare Tunnel step by step.

Prerequisite

  1. You have a registered domain name (e.g., nicklin.work).
  2. You have a Cloudflare account.
  3. Your domain is managed through Cloudflare.
  4. You have docker installed on your local server.

Guide

  1. Firstly, create a directory to store all required files for cloudflared. cloudflared is a command-line tool to manage Cloudflare resources. We will use it to create and set up a tunnel. Replace /somewhere/to/place/your/files with the actual path on your local server.

    bash
    mkdir -p /somewhere/to/place/your/files
    chmod 777 /somewhere/to/place/your/files
  2. Next, use a Docker container to run cloudflared. Here, I use a small trick: aliasing cloudflared as a Docker command. This is very convenient since we will use this command multiple times. I’m using the latest version at the time of writing this post. You can find the image you prefer here.

    bash
    docker pull cloudflare/cloudflared:1759-f9c2bd51ae24
    alias cloudflared="docker run --rm -it -v /somewhere/to/place/your/files:/home/nonroot/.cloudflared cloudflare/cloudflared:1759-f9c2bd51ae24"
  3. Log in to your Cloudflare account:

    bash
    cloudflared login

    Your terminal will likely display the following: cloudflared-login Open the link in your browser and log in. After that, you should see a cert.pem file in your cloudflared folder.

  4. Create a tunnel with the following command:

    bash
    cloudflared tunnel create YourTunnelName

    You should see a result like this. Copy the ID:

    Created tunnel YourTunnelName with id some-random-id-xxxxxxxxxxxx-xxxxx

  5. To access your local network from the public network, you need a domain name and must configure it to resolve to your tunnel. For example, use tunnel.test.com. Run the following command to let Cloudflare resolve the domain to a specific tunnel. Ensure you have management access to test.com on Cloudflare first!

    bash
    cloudflared tunnel route dns YourTunnelName tunnel.test.com

    This command creates a CNAME record pointing tunnel.test.com to the tunnel’s domain, which is usually: some-random-id-xxxxxxxxxxxx-xxxxx.cfargotunnel.com.

  6. Now that the tunnel and DNS are set up, configure the tunnel. Create a config.yml file in your cloudflared folder and copy the following:

    yaml
    tunnel: some-random-id-xxxxxxxxxxxx-xxxxx
    credentials-file: ~/.cloudflared/some-random-id-xxxxxxxxxxxx-xxxxx.json
    
    ingress:
    - hostname: tunnel.test.com
      service: http://192.168.1.100:8080
    - service: http_status:404

    This configuration tells Cloudflare to redirect requests to http://192.168.1.100:8080 when accessing tunnel.test.com. Ensure you include http_status:404 as the last line, as it is always required.

  7. Test your tunnel by running the following command. Access tunnel.test.com to verify that you can reach your local web service:

    bash
    cloudflared tunnel run YourTunnelName

    cloudflared-tunnel-running

  8. Finally, create a Docker Compose file for easier tunnel management. Below is an example:

    yaml
    services:
      cloudflared:
        container_name: cloudflare-tunnel
        image: cloudflare/cloudflared:1759-f9c2bd51ae24
        restart: unless-stopped
        command: tunnel --no-autoupdate run
        volumes:
        - /host_data/cloudflared:/home/nonroot/.cloudflared
        networks:
        - web

    If you want to expose a web service running in a container, ensure that your tunnel is on the same network as the container.

Reference

  1. Cloudflare Documentation: Create a Locally-Managed Tunnel
  2. Cloudflare Documentation: Cloudflared Configuration File