Featured image of post Using Cloudflared for Tunneling to Internal Resources

Using Cloudflared for Tunneling to Internal Resources


Introduction

This guide explains how to set up a Cloudflared container within your Docker environment, creating a secure tunnel from Cloudflare to your internal network resources. Once set up, this tunnel eliminates the need to expose ports 80 and 443.

This guide presumes you have an operational internal network with a configured reverse proxy like Nginx Proxy Manager. It also assumes you possess a Cloudflare account with DNS management capabilities for your domain.


UPDATE 04/17/2023

There’s now a simplified method for running Cloudflared containers that streamlines the process described below. Cloudflare allows you to store the configuration in the cloud, eliminating the need for local credential files and simplifying the setup. All you need is a tunnel token from the Cloudflare Zero Trust dashboard.

You can now build the entire tunnel locally using docker-compose. Here’s an updated docker-compose.yml file that simplifies the process. Just replace YOUR_TOKEN_FROM_CLOUDFLARE with your actual tunnel token from the Cloudflare dashboard:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
version: '3'
services:
  cloudflared-tunnel:
    image: cloudflare/cloudflared:latest
    container_name: cloudflared
    environment:
      - TZ=America/New_York
      - TUNNEL_TOKEN=YOUR_TOKEN_FROM_CLOUDFLARE
    restart: always
    command: tunnel run
    network_mode: "host"

If you prefer to set up the tunnel manually, continue reading the original guide below. A more comprehensive tutorial for the cloud-based method will be available in the future.


The Cloudflared Project

This project utilizes Docker-Compose and Docker on a Ubuntu VM. Initially, this was set up on an Unraid system using the _aeleos/cloudflared_ container, instructions for which can be found at https://github.com/aeleos/cloudflared. The setup has since migrated to Ubuntu for hosting and site independence, but the Unraid instructions remain relevant for those using Unraid.

For simplicity, the necessary files will be stored at _/docker-host/cloudflared-whitemattertech/_. If you have multiple domains requiring tunneling, create separate folders like _/docker-host/cloudflared-domain2/_ and _/docker-host/cloudflared-domain3/_. Each step needs to be performed individually for each domain.

Begin by logging into Cloudflare from your terminal:

1
docker run --rm -v /.cloudflared:/home/nonroot/.cloudflared/ cloudflare/cloudflared:latest tunnel login

After running the command, you’ll see output similar to the image below:

Use the generated URL from the terminal output to log into your Cloudflare account. Upon successful login, the required certificate will be saved to your /docker-host/cloudflared-whitemattertech/.cloudflared directory.

Next, create a new tunnel using this terminal command, replacing TUNNELNAMEHERE with your desired name:

1
docker run --rm -v /docker-host/cloudflared-whitemattertech/.cloudflared:/home/nonroot/.cloudflared/ cloudflare/cloudflared:latest tunnel create TUNNELNAMEHERE

Verify the tunnel’s status by running:

1
docker run --rm -v /docker-host/cloudflared-whitemattertech/.cloudflared:/home/nonroot/.cloudflared/ cloudflare/cloudflared:latest tunnel list

Make note of the tunnel ID from the output for later use.

Now, create and edit a configuration file named _config.yaml_:

1
2
touch /docker-host/cloudflared-whitemattertech/.cloudflared/config.yaml
nano /docker-host/cloudflared-whitemattertech/.cloudflared/config.yaml

Paste the following content into config.yaml, replacing the _xxx…_ with your copied tunnel ID:

1
2
3
4
5
6
7
tunnel: xxxxxxxxxxxxxxxxxxxxxxxxxx
credentials-file: /home/nonroot/.cloudflared/xxxxxxxxxxxxxxxxxxxxxxxx.json

ingress:
  - service: https://localhost:443
    originRequest:
      originServerName: whitematter.tech

Under “ingress”, service refers to your reverse proxy host. If different from the example, replace localhost:443 with your reverse proxy IP. originServerName should be your root domain. If you encounter issues starting the container, try using a subdomain like auth.whitematter.tech as the originServerName. A single subdomain is sufficient, regardless of how many you plan to use with the tunnel.

Next, create the docker-compose.yml file:

1
2
touch /docker-host/cloudflared-whitemattertech/docker-compose.yml
nano /docker-host/cloudflared-whitemattertech/docker-compose.yml

For your convenience, the example below includes commented-out configurations for additional domains. If you’re using more than one domain, uncomment and update those lines with your specific paths.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
version: "3"
services:
  cloudflared-whitematter:
    image: cloudflare/cloudflared:latest
    container_name: cloudflared-whitematter
    environment:
      - TZ=America/New_York
    volumes:
      - /docker-host/cloudflared-whitematter/:/home/nonroot/.cloudflared/
    restart: always
    command: tunnel run
    network_mode: "host"
#  cloudflared-domain1:
#    image: cloudflare/cloudflared:latest
#    container_name: cloudflared-domain1
#    environment:
#      - TZ=America/New_York
#    volumes:
#      - /docker-host/cloudflared-domain1/:/home/nonroot/.cloudflared/
#    restart: always
#    command: tunnel run
#    network_mode: "host"
#  cloudflared-domain2:
#    image: cloudflare/cloudflared:latest
#    container_name: cloudflared-domain2
#    environment:
#      - TZ=America/New_York
#    volumes:
#      - /docker-host/cloudflared-domain2/:/home/nonroot/.cloudflared/
#    restart: always
#    command: tunnel run
#    network_mode: "host"
#  cloudflared-domain3:
#    image: cloudflare/cloudflared:latest
#    container_name: cloudflared-domain3
#    environment:
#      - TZ=America/New_York
#    volumes:
#      - /docker-host/cloudflared-domain3/:/home/nonroot/.cloudflared/
#    restart: always
#    command: tunnel run
#    network_mode: "host"

Finally, start your container(s) with this command:

1
docker-compose up -d

Cloudflare DNS Modifications

In your Cloudflare DNS settings, replace any existing A records with CNAME records. The Name field should point to your root domain (@), and the Value field should be set to TUNID.cfargotunnel.com, replacing TUNID with your actual tunnel ID.

For subdomains, create a CNAME record for each. Set the Name field to the subdomain (e.g., auth, plex, unraid) and the Value field to “_@_”. After saving, Cloudflare will automatically replace “_@_” with your root domain name. For reference, see the image below:

Once these changes are saved, your internal applications should be accessible through the Cloudflare tunnel. You can now disable port forwarding for ports 80 and 443 to your reverse proxy. Performing a _dig_ command on your domain or subdomain will confirm that your services no longer point to your external IP, enhancing the privacy of your self-hosted applications.


Wrapping Up

Hopefully, this guide has provided you with the necessary steps to successfully set up your own Cloudflare tunnel.

Licensed under CC BY-NC-SA 4.0