Exposing local development environments, self-hosted web applications, or remote SSH servers to the internet traditionally required configuring complex router port forwarding, setting up dynamic DNS records, and exposing home IP addresses directly to public network scanners. Cloudflare Tunnels, powered by the open-source cloudflared daemon, revolutionise this paradigm by establishing outbound-only, encrypted connections between your Linux host and the global Cloudflare edge network.
By routing inbound traffic through authenticated outbound tunnels, you can publish internal HTTP web services, reverse proxies, and administrative consoles without opening a single inbound port on your firewall or router. This comprehensive guide walks you through installing cloudflared on Linux, authenticating your host, configuring persistent named tunnels, routing custom DNS subdomains, and running the daemon as a resilient background systemd service.
Prerequisites and Environment Verification
Before installing and configuring cloudflared, verify that your environment satisfies the following operational requirements:
- Supported Linux Distribution: Ubuntu 22.04/24.04 LTS, Debian 11/12, Fedora 39/40, RHEL/Rocky Linux 9, or Arch Linux running on
x86_64orarm64hardware. - Cloudflare Account and Active Domain: A free or paid Cloudflare account managing an active domain whose nameservers point to Cloudflare DNS.
- Administrative Privileges: Root or
sudoaccess to install system binaries and managesystemdsystem services. - Local Service to Expose: An active local service listening on
localhost(such as Nginx on port 80, a Docker container on port 8080, or a Node.js development server on port 3000).
Step 1: Installing Cloudflared on Linux
Cloudflare publishes official precompiled binaries and package repositories across all primary Linux distributions. Select the appropriate installation method for your system.
Method A: On Ubuntu and Debian Systems
Add Cloudflare’s official GPG key and APT repository to ensure automated security updates via standard package management:
# Create the keyrings directory
sudo mkdir -p --mode=0755 /etc/apt/keyrings
# Download and import the Cloudflare GPG key
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /etc/apt/keyrings/cloudflare-main.gpg > /dev/null
# Add the official cloudflared repository to your APT sources
echo 'deb [signed-by=/etc/apt/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared jammy main' | sudo tee /etc/apt/sources.list.d/cloudflared.list
# Update package lists and install cloudflared
sudo apt update
sudo apt install -y cloudflared
Method B: On Fedora, RHEL, and CentOS Stream
Download and install the official RPM package directly from Cloudflare’s package mirror:
# Install cloudflared via DNF/RPM
sudo dnf install -y https://pkg.cloudflare.com/cloudflared-ascii.repo
sudo dnf install -y cloudflared
Method C: Standalone Binary (Universal)
If you prefer a direct standalone binary or run an alternative distribution such as Alpine or Arch Linux:
# Download the latest 64-bit Linux binary
curl -L --output cloudflared https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64
# Grant execution permissions and move to system path
chmod +x cloudflared
sudo mv cloudflared /usr/local/bin/cloudflared
Confirm successful installation by checking the installed version string:
cloudflared --version
Step 2: Authenticating Cloudflared with Your Cloudflare Account
To authorize cloudflared to generate tunnels and update DNS records across your domain, authenticate the client against your Cloudflare account:
cloudflared tunnel login
Executing this command produces an interactive authentication URL in your terminal:
Please open the following URL and log in with your Cloudflare account:
https://dash.cloudflare.com/argotunnel?callback=https%3A%2F%2Flogin.cloudflareaccess.org%2F...
Leave cloudflared running to download the cert flag.
- Copy the displayed link and paste it into any web browser.
- Log in to your Cloudflare dashboard and select the authoritative domain you wish to associate with your tunnels.
- Click Authorise to grant the certificate permissions.
Once authenticated in your browser, cloudflared automatically downloads an origin certificate and saves it to ~/.cloudflared/cert.pem. Verify that the file exists:
ls -l ~/.cloudflared/cert.pem
Step 3: Creating a Named Persistent Tunnel
Ephemeral, ad-hoc tunnels (such as cloudflared tunnel --url localhost:8080) generate temporary random URLs. For reliable, production-ready hosting, create a persistent named tunnel:
cloudflared tunnel create web-production
The command output displays your unique Tunnel UUID and saves an associated tunnel credentials JSON file:
Tunnel credentials written to /home/user/.cloudflared/a1b2c3d4-e5f6-7890-abcd-1234567890ab.json.
Created tunnel web-production with id a1b2c3d4-e5f6-7890-abcd-1234567890ab
Record your Tunnel ID (UUID), as you will reference it in your configuration and routing rules. You can inspect all registered tunnels at any time:
cloudflared tunnel list
Step 4: Configuring Ingress Routing Rules
Cloudflared uses a structured YAML configuration file to map incoming public hostnames to internal network services. Create the configuration file at ~/.cloudflared/config.yml:
nano ~/.cloudflared/config.yml
Populate the file with your Tunnel ID, credentials path, and ingress definitions:
tunnel: a1b2c3d4-e5f6-7890-abcd-1234567890ab
credentials-file: /home/user/.cloudflared/a1b2c3d4-e5f6-7890-abcd-1234567890ab.json
ingress:
# Map subdomains to specific internal services
- hostname: app.yourdomain.com
service: http://localhost:8080
originRequest:
connectTimeout: 30s
noTLSVerify: false
# Optional admin dashboard on another local port
- hostname: monitor.yourdomain.com
service: http://localhost:9090
# Mandatory catch-all rule for unmatched requests
- service: http_status:404
Save and close the file. Note that Cloudflare ingress rules evaluate sequentially; the final catch-all rule (service: http_status:404) is strictly required to handle unrouted traffic gracefully.
Step 5: Routing DNS Traffic to Your Tunnel
Now configure Cloudflare DNS to point your designated public subdomain (e.g., app.yourdomain.com) to the named tunnel using the CLI:
cloudflared tunnel route dns web-production app.yourdomain.com
This command automatically injects a CNAME record into your Cloudflare DNS zone pointing app.yourdomain.com to a1b2c3d4-e5f6-7890-abcd-1234567890ab.cfargotunnel.com with Cloudflare proxying enabled.
Validate your configuration file syntax before launching the tunnel:
cloudflared tunnel ingress validate
Test the tunnel directly in foreground mode to verify end-to-end traffic flow:
cloudflared tunnel run web-production
Open a web browser and visit https://app.yourdomain.com. Your internal service should respond with a valid Cloudflare SSL certificate. Press Ctrl + C in your terminal to stop the foreground test.
Step 6: Running Cloudflared as a Systemd Service
To guarantee that your tunnel starts automatically upon system reboot and restarts in the event of transient failures, install cloudflared as a system-wide background service.
- Move the tunnel configuration and credentials to the global system directory
/etc/cloudflared/:sudo mkdir -p /etc/cloudflared sudo cp ~/.cloudflared/config.yml /etc/cloudflared/config.yml sudo cp ~/.cloudflared/*.json /etc/cloudflared/ - Update the
credentials-filepath inside/etc/cloudflared/config.ymlto reflect the new location:credentials-file: /etc/cloudflared/a1b2c3d4-e5f6-7890-abcd-1234567890ab.json - Register the system service using Cloudflared’s built-in installer:
sudo cloudflared service install - Enable and start the
cloudflaredsystemd service:sudo systemctl enable cloudflared sudo systemctl start cloudflared - Verify the runtime status of the daemon:
sudo systemctl status cloudflared
Essential Operational and Monitoring Commands
The following table outlines standard management commands for maintaining your Cloudflare Tunnels:
| Command | Operational Purpose |
|---|---|
cloudflared tunnel list |
Displays all active, inactive, and deleted tunnels in your account. |
cloudflared tunnel info <name> |
Shows tunnel connection state, active connectors, and IP metrics. |
sudo journalctl -u cloudflared -f |
Streams real-time connection and routing logs from systemd. |
cloudflared tunnel route ip show |
Lists private subnet IP routes configured through the tunnel. |
sudo systemctl restart cloudflared |
Reloads the configuration file after updating ingress rules. |
cloudflared tunnel delete <name> |
Deletes a tunnel and invalidates its remote credentials. |
Troubleshooting Common Cloudflared Issues
1. “Origin Certificate Missing or Expired”
If you encounter authentication errors when creating tunnels, ensure ~/.cloudflared/cert.pem exists and possesses valid read permissions. Run cloudflared tunnel login again to refresh credentials.
2. “502 Bad Gateway” on Public URL
A 502 error returned by Cloudflare indicates that cloudflared is connected to Cloudflare’s edge, but cannot establish a connection to your internal service. Verify that your target application is actively listening on the exact port specified in config.yml:
curl -I http://localhost:8080
sudo ss -tulpn | grep 8080
3. “TLS Verification Failed for Local HTTPS Backend”
If your local backend utilizes a self-signed SSL/TLS certificate (such as an internal Proxmox or router web GUI), add noTLSVerify: true under the originRequest block in /etc/cloudflared/config.yml:
ingress:
- hostname: pve.yourdomain.com
service: https://localhost:8006
originRequest:
noTLSVerify: true
- service: http_status:404
Save the file and run sudo systemctl restart cloudflared to apply the change.