16 min read

Getting Started with Cloudflare Tunnel

Table of Contents

In this guide, you’ll learn how to securely share an application running on your server onto the internet using Cloudflare Tunnel!

Why Use Cloudflare Tunnel?

  • Share local applications you’ve built with other people
  • Host applications from home servers without port forwarding

Alternatives to Cloudflare Tunnel

  • ngrok is another option, but it requires a paid plan for custom domains and persistent URLs. It’s easy to use but not as flexible as Cloudflare Tunnel.

Prerequisites

Before we begin, ensure you have:

  • An Ubuntu server
  • SSH access to your server with sudo privileges
  • Basic command line familiarity
  • A Cloudflare account (free tier works perfectly)
  • A domain name (optional)

Important note: The CLI tool is called cloudflared (with a ‘d’ at the end). Don’t let it trip you up!

Instant Tunnel: TryCloudflare

Before diving into full tunnel setup, let me show you the fastest way to start a tunnel. If you just want to test something quickly, you can use TryCloudflare, a free service that requires no configuration.

Instant Tunnel in One Command

On your Ubuntu server, run:

cloudflared tunnel --url http://localhost:8080

What this does: Cloudflare instantly generates a random URL like https://seasonal-deck-organisms-sf.trycloudflare.com that tunnels directly to your local service. No accounts, no setup, no DNS configuration and no firewall changes required.

TryCloudflare Limitations

Important limitations to understand:

  • Changing URLs: New random URL every time you restart the tunnel
  • Request limits: Maximum 200 concurrent requests
  • No uptime guarantee: Designed for testing only, not production workloads
  • No Server-Sent Events: SSE streaming not supported
  • No persistence: Tunnels disappear when you close the terminal or reboot

Testing your tunnel: Visit the generated URL in any browser and you’ll see your Ubuntu server’s application, complete with HTTPS and DDoS protection from Cloudflare’s global network.

Step 1: Custom Domains

To use Cloudflare Tunnel with your own domain, you have two options:

A. Full DNS Setup

For full DNS setup, you need to switch your domain’s DNS entirely to Cloudflare. Doing so provides:

  • Automatic DNS management: Cloudflare automatically creates and manages DNS records for new tunnels
  • Full feature access: Access to all Cloudflare security, performance, and analytics features
  • Simplified administration: One dashboard to manage DNS, tunnels, and security policies
  • Global load balancing: Distribute traffic across multiple servers automatically

B. Partial DNS Setup

You can still use Cloudflare Tunnel with other DNS providers by manually creating CNAME records:

  • DNS record type: CNAME (or ALIAS for root domains)
  • Record name: Your subdomain (e.g., api for api.yourdomain.com)
  • Record value: subdomain.domain.tld.cdn.cloudflare.net

Generally speaking, you’ll want to use the full DNS setup for the best experience, but if you prefer to keep your existing DNS provider, you can manually create CNAME records pointing to Cloudflare’s infrastructure.

Step 2: Installing cloudflared on Ubuntu

On your Ubuntu server:

# Add Cloudflare's package signing key
sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null

# Add Cloudflare's repository to APT sources
echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflared.list

# Update package lists and install cloudflared
sudo apt-get update && sudo apt-get install cloudflared

What this installation process does:

  • Package signing verification: The GPG key ensures you’re installing authentic Cloudflare software, not malicious packages
  • Repository integration: Adding Cloudflare’s repository allows automatic updates through your normal apt upgrade process
  • System-wide installation: Places cloudflared in /usr/local/bin/ making it accessible to all users and system services

Verify successful installation:

cloudflared --version

You should see version information like cloudflared version 2024.x.x confirming successful installation.

Step 3: Two Options to Creating Tunnels

Cloudflare offers two distinct methods for tunnel creation, each suited to different server administration needs:

Dashboard Method

This newer approach uses the intuitive Zero Trust dashboard and is perfect for learning:

Benefits:

  • Visual interface: Point-and-click tunnel management with guided workflows
  • Generated commands: Pre-configured installation commands with embedded credentials
  • Remote management: Configure and monitor tunnels from anywhere without server access
  • Built-in monitoring: Real-time connection status and traffic analytics

Process:

  1. Navigate to Zero Trust dashboard → Networks → Tunnels
  2. Click “Create a tunnel” → Choose “Cloudflared” connector
  3. Name your tunnel descriptively (e.g., “production-web-server”, “dev-api-server”)
  4. Copy the provided installation command containing your unique tunnel token
  5. Run the command on your Ubuntu server

Command Line Method

This traditional command-line approach provides deeper understanding and is better for production automation:

Benefits:

  • Infrastructure as code: Configuration files can be version-controlled with Git
  • Automation friendly: Easily integrated into deployment scripts and configuration management
  • Fine-grained control: Direct management of all tunnel parameters and routing rules
  • Learning value: Better understanding of how tunnels work under the hood

We’ll focus on the CLI method below.

Step 4: Creating a Tunnel (CLI Method)

Let’s create a tunnel using the command-line:

Authenticate with Cloudflare

On your Ubuntu server:

cloudflared login

What happens during authentication: This command opens a browser-based authentication flow. If you’re on a headless server, copy the URL to a local browser:

  1. The command displays a URL like https://dash.cloudflare.com/argotunnel?callback=...
  2. Open this URL in any browser where you can log into Cloudflare
  3. Authenticate and grant tunnel creation permissions
  4. The authentication creates a certificate file at ~/.cloudflared/cert.pem

Security consideration: This certificate authorizes tunnel creation for your Cloudflare account. Treat it like a password and keep it secure.

Create Your Named Tunnel

# Create a new tunnel with a descriptive name
cloudflared tunnel create your-tunnel-name

# List all tunnels to verify your new tunnel was created
cloudflared tunnel list

Understanding tunnel creation:

  • Persistent identity: Creates a permanent relationship between your chosen name and a UUID
  • Inactive by default: The tunnel exists but isn’t running—think of it as reserving a phone number
  • Credentials generation: Creates a JSON file containing tunnel-specific authentication tokens

Important details to record:

  • Tunnel UUID: Long identifier like ed5bfe16-cb5f-449c-b2e9-7c300b749c79
  • Credentials file location: Path to the JSON file (usually ~/.cloudflared/[uuid].json)

Verify Tunnel Creation

cloudflared tunnel list

Expected output shows your tunnel with “INACTIVE” status—this is normal since we haven’t configured routing or started the daemon yet.

Step 5: Server Configuration File

Configuration files are essential for production server management, providing repeatability and documentation:

Create Configuration Directory

On your Ubuntu server:

# Create user configuration directory
mkdir -p ~/.cloudflared
cd ~/.cloudflared

# Set secure permissions
chmod 700 ~/.cloudflared

Directory security: The 700 permission ensures only your user can read tunnel credentials, preventing other server users from accessing your tunnel configuration.

Configuration for a Single Service

For servers that run a single application:

vim ~/.cloudflared/config.yml

Basic web server configuration (replace values with your actual details):

tunnel: ed5bfe16-cb5f-449c-b2e9-7c300b749c79  # Change to your tunnel UUID
credentials-file: /home/yourusername/.cloudflared/ed5bfe16-cb5f-449c-b2e9-7c300b749c79.json # Change to your username and tunnel UUID

# Single service routing
url: http://localhost:8080

Configuration explanation:

  • tunnel: The UUID from your tunnel creation step—this identifies your specific tunnel
  • credentials-file: Absolute path to the JSON credentials file (replace username with your actual username)
  • url: Your local service endpoint—adjust port to match your application

Configuration for Multiple Services

For servers running multiple applications:

tunnel: ed5bfe16-cb5f-449c-b2e9-7c300b749c79  # Change to your tunnel UUID
credentials-file: /home/yourusername/.cloudflared/ed5bfe16-cb5f-449c-b2e9-7c300b749c79.json # Change to your username and tunnel UUID

# The below are examples. Change the hostnames and services as needed
ingress:
  - hostname: api.yourdomain.com
    service: http://localhost:8080      # REST API service
  - hostname: admin.yourdomain.com
    service: http://localhost:9000      # Admin dashboard
  - hostname: websocket.yourdomain.com
    service: ws://localhost:8081        # WebSocket service
  - hostname: static.yourdomain.com
    service: http://localhost:8082      # Static file server
  - service: http_status:404            # Required catch-all rule

Ingress rules explained:

  • hostname matching: Each hostname routes to a different local service on your server
  • Service protocols: Support for HTTP, HTTPS, WebSocket, and TCP protocols
  • Catch-all rule: The final rule is mandatory and handles unmatched requests
  • Load balancing: Can distribute traffic across multiple backend servers

Secure Configuration File Permissions

# Secure configuration file permissions
chmod 600 ~/.cloudflared/config.yml

# Verify permissions
ls -la ~/.cloudflared/

Security importance: Configuration files contain sensitive routing information and should only be readable by the tunnel owner.

Step 6: DNS Configuration & Tunnel Activation

Create DNS Routes for Your Services

Connect your tunnel to specific hostnames that will route to your Ubuntu server:

# Create DNS routing for your primary service
cloudflared tunnel route dns your-tunnel-name app.yourdomain.com

# Add additional hostnames for multi-service configurations
cloudflared tunnel route dns your-tunnel-name api.yourdomain.com
cloudflared tunnel route dns your-tunnel-name admin.yourdomain.com

What DNS routing creates:

  • CNAME records: Points app.yourdomain.com to <tunnel-uuid>.cfargotunnel.com
  • Automatic SSL: Cloudflare automatically provisions and manages SSL certificates
  • Global anycast: Your Ubuntu server becomes accessible from Cloudflare’s 300+ data centers worldwide

Start Your Tunnel for Testing

Basic tunnel startup:

cloudflared tunnel --config ~/.cloudflared/config.yml run your-tunnel-name

With detailed logging for troubleshooting:

cloudflared tunnel --loglevel debug --config ~/.cloudflared/config.yml run your-tunnel-name

Success indicators to look for:

  • INF Connection to edge established - Tunnel connected to Cloudflare network
  • INF Registered tunnel connection - Your specific tunnel is active
  • INF Initial protocol http2 - Communication protocol established

Test your tunnel: Your Ubuntu server applications should now be accessible at https://app.yourdomain.com from anywhere in the world.

Monitor Tunnel Status

In a separate terminal session:

# Check tunnel status
cloudflared tunnel info your-tunnel-name

# Monitor live connection logs
tail -f ~/.cloudflared/cloudflared.log

Step 7: Advanced Server Configurations

Non-HTTP Service Tunneling

Your Ubuntu server can expose more than just web applications through Cloudflare Tunnel:

tunnel: ed5bfe16-cb5f-449c-b2e9-7c300b749c79  # Change to your tunnel UUID
credentials-file: /home/yourusername/.cloudflared/ed5bfe16-cb5f-449c-b2e9-7c300b749c79.json # Change to your username and tunnel UUID

# The below are examples. Change the hostnames and services as needed
ingress:
  - hostname: ssh.yourdomain.com
    service: ssh://localhost:2222         # Change to your SSH port if needed
  - hostname: database.yourdomain.com
    service: tcp://localhost:5432       # PostgreSQL database
  - hostname: redis.yourdomain.com
    service: tcp://localhost:6379       # Redis cache
  - hostname: monitoring.yourdomain.com
    service: http://localhost:3000      # Grafana dashboard
  - service: http_status:404

Server service examples:

  • SSH tunneling: Secure remote administration without opening port 22
  • Database access: Direct database connections through encrypted tunnels
  • Monitoring tools: Access to Grafana, Prometheus, or custom monitoring dashboards
  • Development tools: Code servers, documentation sites, or internal tools

Production Server Routing Strategies

Environment-based routing:

ingress:
  - hostname: prod.yourdomain.com
    service: http://localhost:8080
  - hostname: staging.yourdomain.com
    service: http://localhost:8081
  - hostname: dev.yourdomain.com
    service: http://localhost:8082
  - service: http_status:404

Service-based routing:

ingress:
  - hostname: www.yourdomain.com
    service: http://localhost:80        # Main website
  - hostname: api.yourdomain.com
    service: http://localhost:8080      # API server
  - hostname: admin.yourdomain.com
    service: http://localhost:9000      # Admin interface
  - hostname: docs.yourdomain.com
    service: http://localhost:4000      # Documentation site
  - service: http_status:404

Step 8: Run Cloudflare Tunnel on Boot

If you want your Cloudflare Tunnel to run automatically when the server starts, you can set it up as a system service. This allows the tunnel to run in the background and remain active and start automatically whenever you boot up your server.

Service Installation and Configuration

Install cloudflared as a system service:

sudo cloudflared service install

What service installation creates:

  • Systemd service file: /etc/systemd/system/cloudflared.service
  • Automatic startup: Service configured to start on boot
  • Process monitoring: Systemd automatically restarts the service if it crashes
  • Logging integration: Logs accessible through journalctl

System-Wide Configuration Setup

Configuration file location: System services require configuration in /etc/cloudflared/, not user directories.

Copy your configuration to the system location:

# Create system configuration directory
sudo mkdir -p /etc/cloudflared

# Copy your working configuration
sudo cp ~/.cloudflared/config.yml /etc/cloudflared/

# Set appropriate permissions
sudo chmod 600 /etc/cloudflared/config.yml
sudo chown root:root /etc/cloudflared/config.yml

Update configuration for system service context:

sudo vim /etc/cloudflared/config.yml

Critical system service configuration:

tunnel: ed5bfe16-cb5f-449c-b2e9-7c300b749c79
credentials-file: /home/username/.cloudflared/ed5bfe16-cb5f-449c-b2e9-7c300b749c79.json

# Production service settings
logfile: /var/log/cloudflared/cloudflared.log
loglevel: info

# Your service configuration
url: http://localhost:8080

Why absolute paths are critical: System services run in a different context than user sessions. The service must be able to locate credential files regardless of which user starts the service.

Service Management and Monitoring

Essential systemd service commands:

# Start the cloudflared service
sudo systemctl start cloudflared

# Enable automatic startup on boot
sudo systemctl enable cloudflared

# Check current service status
sudo systemctl status cloudflared

# Stop the service
sudo systemctl stop cloudflared

# Restart service after configuration changes
sudo systemctl restart cloudflared

# Disable automatic startup
sudo systemctl disable cloudflared

Service monitoring and logging:

# View live service logs
sudo journalctl -u cloudflared -f

# View recent logs with timestamps
sudo journalctl -u cloudflared --since "1 hour ago"

# View logs from last boot
sudo journalctl -u cloudflared -b

# Check if service is enabled for boot
sudo systemctl is-enabled cloudflared

Log file management:

# Create log directory
sudo mkdir -p /var/log/cloudflared

# Set appropriate log permissions
sudo chown syslog:adm /var/log/cloudflared
sudo chmod 755 /var/log/cloudflared

Production Service Validation

Verify service is running correctly:

# Check process status
ps aux | grep cloudflared

# Verify network connections
sudo netstat -tlpn | grep cloudflared

# Test tunnel connectivity
curl -I https://yourdomain.com

# Monitor resource usage
sudo systemctl show cloudflared --property=MainPID,CPUUsageNSec,MemoryCurrent

Step 9: Troubleshooting

Connection and Network Issues

“Failed to create new quic connection” error:

This may be because of firewall restrictions or ISP limitations:

# Check if UFW is blocking outbound connections
sudo ufw status verbose

# Allow Cloudflare Tunnel's required outbound ports
sudo ufw allow out 80/tcp
sudo ufw allow out 443/tcp
sudo ufw allow out 7844/udp

# Force HTTP/2 protocol instead of QUIC (more firewall-friendly)
cloudflared tunnel --protocol http2 --config ~/.cloudflared/config.yml run your-tunnel-name

Protocol explanation: QUIC (UDP-based) provides better performance but some firewalls or ISPs block it. HTTP/2 over TCP is more universally supported.

Configuration and Service Issues

“Cannot determine default configuration path” error:

Always specify configuration file location explicitly:

# Correct command with explicit config path
cloudflared tunnel --config ~/.cloudflared/config.yml run your-tunnel-name

# For system service, ensure config exists
sudo ls -la /etc/cloudflared/config.yml

Service fails to start but manual tunnel works:

Common system service issues and solutions:

  1. Configuration file location mismatch:

    # Verify system config exists
    sudo cat /etc/cloudflared/config.yml
    
    # Check service logs for path errors
    sudo journalctl -u cloudflared --lines=20
  2. Incorrect credentials file permissions:

    # Service needs access to credentials file
    sudo chmod 644 /home/username/.cloudflared/uuid.json
    
    # Or copy credentials to system location
    sudo cp /home/username/.cloudflared/uuid.json /etc/cloudflared/
    sudo chmod 600 /etc/cloudflared/uuid.json
    sudo chown root:root /etc/cloudflared/uuid.json
  3. Service user access issues:

    # Check which user runs the service
    sudo systemctl show cloudflared --property=User
    
    # Ensure service user can access files
    sudo -u cloudflared test -r /etc/cloudflared/config.yml

Step 10: Useful Command Line Commands

Tunnel Operations You’ll Use Regularly

# List all tunnels on your account
cloudflared tunnel list

# Get detailed information about your server's tunnel
cloudflared tunnel info your-tunnel-name

# Validate configuration file syntax
cloudflared tunnel --config ~/.cloudflared/config.yml validate

# Add new hostname to existing tunnel
cloudflared tunnel route dns your-tunnel-name new-service.yourdomain.com

# Test tunnel connectivity
curl -I https://yourdomain.com

System Service Management

# Check service health
sudo systemctl status cloudflared

# Restart service after configuration changes
sudo systemctl restart cloudflared

# Monitor service logs in real-time
sudo journalctl -u cloudflared -f

# Check service startup time and performance
sudo systemctl show cloudflared --property=ExecMainStartTimestamp,CPUUsageNSec

# Verify service starts automatically
sudo systemctl is-enabled cloudflared

DNS and Routing Management

Adding new services: Use the cloudflared tunnel route dns command for each new hostname.

Removing DNS records: Navigate to Cloudflare dashboard → DNS → Records, locate the CNAME record for your hostname, and delete it.

Bulk hostname management: For multiple hostnames, the Cloudflare dashboard provides more efficient management than individual CLI commands.

Server Security and Monitoring

# Monitor tunnel connection attempts
sudo journalctl -u cloudflared | grep -E "(connection|auth|error)"

# Check for unauthorized access attempts
sudo tail -f /var/log/auth.log | grep -E "(ssh|tunnel)"

# Verify only expected ports are listening
sudo netstat -tlpn | grep -E "(cloudflared|80|443)"

# Monitor server resource usage with tunnels
htop -p $(pgrep cloudflared)

Step 11: Security and Access Control

IP-Based Access Restrictions

Restrict tunnel access to specific IP ranges or geographic locations:

In your Cloudflare dashboard:

  1. Navigate to “Access” → “Applications”

  2. Click “Add an application” → “Self-hosted”

  3. Configure application security:

    • Application name: “Ubuntu Server Access”
    • Application domain: “app.yourdomain.com”
    • Session duration: Set appropriate timeout
  4. Create access policies:

    • Policy name: “Office IP Allowlist”
    • Action: “Allow”
    • Rule type: “IP Ranges”
    • Value: Your office/home IP addresses (e.g., 203.0.113.0/24)

Authentication Integration

Email-based one-time passwords:

  1. In application policy setup:
    • Rule type: “Email”
    • Value: Authorized email addresses
  2. Users receive OTP codes via email for access
  3. No additional authentication infrastructure required on your Ubuntu server

Corporate authentication integration:

  • SAML/OIDC: Connect to existing corporate identity providers
  • Multi-factor authentication: Require additional verification steps
  • Session management: Control session duration and concurrent connections

Step 12: Server Maintenance

Regular Maintenance Tasks

Weekly server maintenance checklist:

# Update cloudflared and system packages
sudo apt update && sudo apt upgrade

# Check tunnel service logs for errors
sudo journalctl -u cloudflared --since "1 week ago" | grep -i error

# Verify tunnel connectivity
curl -I https://yourdomain.com

# Review Cloudflare analytics for unusual traffic patterns
# (Check in the dashboard on Cloudflare's website under Analytics → Traffic)

Conclusion

You now have general knowledge of Cloudflare Tunnel deployment and management for your Ubuntu server:

  • ✅ Instant tunnels using TryCloudflare
  • ✅ Flexible tunnel creation using both dashboard and CLI methods
  • ✅ Advanced server configurations supporting multiple services and protocols
  • ✅ System service integration with systemd for reliability and automatic startup
  • ✅ Troubleshooting
  • ✅ Server maintenance with regular updates and monitoring