Cloudflare Argo Tunnel Setup - Self-Host with a CG-NAT

Self-Hosting Oct 16, 2021


What is a Cloudflare Argo Tunnel
How it works
Setting up Cloudflare Repositories
Temporary Argo Tunnel
Permanent Argo Tunnel
Run in the background and on boot
Adding more services

What is a Cloudflare Argo Tunnel?

Cloudflare Tunnel provides you with a secure way to connect your resources to Cloudflare without a publicly routable IP address. With Tunnel, you do not send traffic to an external IP — instead, a lightweight daemon in your infrastructure (cloudflared) creates outbound-only connections to Cloudflare’s edge. Cloudflare Tunnel can connect HTTP web servers, SSH servers, remote desktops, and other protocols safely to Cloudflare. This way, your origins can serve traffic through Cloudflare without being vulnerable to attacks that bypass Cloudflare. - Cloudflare

How it works

Cloudflared establishes outbound connections (tunnels) between your resources and the Cloudflare edge. Tunnels are persistent objects that route traffic to DNS records. Within the same tunnel, you can run as many cloudflared processes (connectors) as needed. These processes will establish connections to the Cloudflare edge and send traffic to the nearest Cloudflare data center. - Cloudflare

Cloudflare Argo Tunnel Diagram


As the IPv4 address space has been exhausted, many ISP's have reduced their usage by implementing a CG-NAT, this is where multiple customers share the same IPv4 address. This basically makes port-forwarding impossible.

Carrier Grade NAT Diagram

Using a Cloudflare Argo Tunnel removes the need to port forward, allowing users to self-host behind a CG-NAT, strict firewall or any ISP limitation.

Cloudflare Setup Docs


Setup Cloudflare Repositories

You can download the cloudflared binary from Cloudflare. I feel that setting up Cloudflare Repositories is a better solution as it can then be managed and updated via your package manager.

Follow the Official Setup Docs for your distribution.

Example setup for Debian 12 (Bookworm):

# Add cloudflare gpg key
sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null

# Add this repo to your apt repositories
echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] bookworm main' | sudo tee /etc/apt/sources.list.d/cloudflared.list

# install cloudflared
sudo apt-get update && sudo apt-get install cloudflared

Temporary Argo Tunnel (Cloudflare account not required!)

Run: cloudflared tunnel --url localhost:<PORT>
Example: cloudflared tunnel --url localhost:80


2021-10-14T21:01:42Z INF |  Your quick Tunnel has been created! Visit it at (it may take some time to be reachable):  |
2021-10-14T21:01:42Z INF |                               |
2021-10-14T21:01:42Z INF +--------------------------------------------------------------------------------------------+

Just head to the URL outputted:

It's that simple!

It's worth nothing there is some undocumented rate limiting that occurs on the this temporary setup, although you won't realise for dev project which it's designed for.

Permanent Argo Tunnel

  1. Login: cloudflared tunnel login

  2. Copy the URL and open in your browser

  3. Create a new tunnel: cloudflared tunnel create cyberhost

This can be viewed by running cloudflared tunnel list

ID                                   NAME      CREATED              CONNECTIONS 
28c78ae-9ba2-40cc-c187-1892be52da8b cyberhost 2021-10-14T12:10:05Z
  1. Navigate to .cloudflared you may find this in your home directory cd ~/.cloudflared.

  2. Create a configuration file within the .cloudflared directory:
    nano config.yml

  3. Use the following config:

tunnel: <Tunnel-UUID>
credentials-file: <PATH>/.cloudflared/<Tunnel-UUID>.json

  - hostname:
    service: http://localhost:80
  - service: http_status:404

Replace <PORT>, <Tunnel-UUID>, <PATH> and To find <PATH> run pwd in the .cloudflared directory.

  1. Connect the Argo tunnel with a hostname
    eg: cloudflared tunnel route dns <UUID or NAME>

  2. Now run the tunnel cloudflared tunnel run <UUID or NAME>

Run in the background and on boot

  1. Create a system service: sudo cloudflared --config ~/.cloudflared/config.yml service install

  2. Start and enable service at boot: sudo systemctl start cloudflared && sudo systemctl enable cloudflared

Adding more services

  1. Pair another hostname: cloudflared tunnel route dns <UUID or NAME>

  2. Add another ingress point to the config:

  - hostname:
    service: http://localhost:80
  - hostname:
    service: http://localhost:8080
  - service: http_status:404
  1. Remove the existing service config sudo rm /etc/cloudflared/config.yml
  2. Install the new config: sudo cloudflared --config ~/.cloudflared/config.yml service install
  3. Restart service: sudo systemctl restart cloudflared