### What is Cloudflare Tunnel?

Cloudflare Tunnel (formerly Argo Tunnel) creates a secure, outbound-only connection between your RamNode VPS and the Cloudflare network. Instead of exposing your server's IP address or opening inbound firewall ports, the `cloudflared` daemon establishes encrypted tunnels that route traffic through Cloudflare's edge.

- **No Open Ports:** Outbound-only connections  
- **Free TLS:** Automatic SSL certificates  
- **Multi-Service:** Route multiple subdomains through one tunnel  
- **DDoS Protection:** Cloudflare edge shields your origin  
- **Zero Trust:** Identity-aware access policies  
- **Lightweight:** Under 50 MB RAM usage

### Prerequisites

#### What You Will Need

- A RamNode VPS running Ubuntu 22.04 or 24.04 (Debian also works)  
- A domain name with DNS managed by Cloudflare (free plan is sufficient)  
- A Cloudflare account with at least one active zone  
- Root or sudo access on your VPS  
- One or more local services to expose (web server, API, SSH, etc.)

#### Recommended VPS Specifications

| Use Case | Recommended Plan | Notes  |
| --- | --- | --- |
| Single web app or blog | 1 GB RAM VPS | More than sufficient for cloudflared plus a small app |
| Multiple tunneled services | 2 GB RAM VPS | Room for several containers or services |
| High-traffic API gateway | 4 GB+ RAM VPS | Extra headroom for concurrent connections |

### Install cloudflared

Install from the official APT repository for automatic updates.

Add Cloudflare GPG Key & Repository

```bash
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

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
```

Install the Package

```bash
sudo apt update
sudo apt install -y cloudflared
```

Verify Installation

```bash
cloudflared --version
```

**📝 Note:** If you prefer a manual installation, download the latest `.deb` package from the Cloudflare GitHub releases page and install with `dpkg -i`.

### Authenticate with Cloudflare

Link your VPS to your Cloudflare account. This generates a certificate that authorizes tunnel and DNS management.

Login to Cloudflare

```bash
cloudflared tunnel login
```

This outputs a URL. Copy and paste it into your browser, select the domain you want to use, and authorize. After authorization, a certificate is saved to:

Certificate Location

```bash
~/.cloudflared/cert.pem
```

**🔒 Security:** Keep `cert.pem` secure. It grants full tunnel management permissions for the selected zone.

**💡 Tip:** On a headless VPS without a browser, copy the URL and open it on any device where you are logged into your Cloudflare dashboard.

### Create a Tunnel

Create the Tunnel

```bash
cloudflared tunnel create my-ramnode-tunnel
```

Expected Output

```bash
Created tunnel my-ramnode-tunnel with id a1b2c3d4-e5f6-7890-abcd-ef1234567890
```

The tunnel credentials JSON file is stored at `~/.cloudflared/<UUID>.json`. Make a note of the tunnel UUID — you'll reference it in the configuration file.

### Configure the Tunnel

Create Config Directory

```bash
sudo mkdir -p /etc/cloudflared
sudo nano /etc/cloudflared/config.yml
```

#### Basic Configuration (Single Service)

config.yml — Single Service

```yaml

tunnel: a1b2c3d4-e5f6-7890-abcd-ef1234567890
credentials-file: /root/.cloudflared/a1b2c3d4-e5f6-7890-abcd-ef1234567890.json

ingress:
  - hostname: app.example.com
    service: http://localhost:8080
  - service: http_status:404
```

**⚠️ Important:** The final catch-all rule (`- service: http_status:404`) is required. Cloudflare Tunnel will not start without it.

#### Multi-Service Configuration

Route multiple subdomains through a single tunnel:

config.yml — Multi-Service

```yaml

tunnel: a1b2c3d4-e5f6-7890-abcd-ef1234567890
credentials-file: /root/.cloudflared/a1b2c3d4-e5f6-7890-abcd-ef1234567890.json

ingress:
  - hostname: app.example.com
    service: http://localhost:8080

- hostname: api.example.com
    service: http://localhost:3000

- hostname: grafana.example.com
    service: http://localhost:3001

- hostname: ssh.example.com
    service: ssh://localhost:22

- service: http_status:404
```

#### Configuration Options Reference

| Option | Description | Example  |
| --- | --- | --- |
| `tunnel` | Your tunnel UUID | a1b2c3d4-... |
| `credentials-file` | Path to tunnel credentials JSON | /root/.cloudflared/<UUID>.json |
| `protocol` | Connection protocol | auto, quic, http2 |
| `logfile` | Path for log output | /var/log/cloudflared.log |
| `metrics` | Prometheus metrics endpoint | localhost:2000 |
| `no-tls-verify` | Skip TLS verification (dev only) | true |

### Route DNS

Create DNS records that point your hostnames to the tunnel:

Create DNS Routes

```bash
cloudflared tunnel route dns my-ramnode-tunnel app.example.com
cloudflared tunnel route dns my-ramnode-tunnel api.example.com
cloudflared tunnel route dns my-ramnode-tunnel grafana.example.com
```

Each command creates a CNAME record pointing to your tunnel's unique hostname. Verify the records in your Cloudflare dashboard under DNS settings — each should show the orange proxy icon enabled.

### Test the Tunnel

Run the tunnel manually before setting it up as a service:

Run Tunnel in Foreground

```bash
cloudflared tunnel --config /etc/cloudflared/config.yml run
```

You should see log output indicating connections to multiple Cloudflare edge locations. Open your configured hostname in a browser to confirm your service is accessible.

#### Troubleshooting Common Issues

**502 Bad Gateway:** Local service is not running. Start your application and verify it responds on the configured port.

**Tunnel won't start:** Missing catch-all ingress rule. Add `- service: http_status:404` as the last entry.

**DNS not resolving:** CNAME record not created. Run `cloudflared tunnel route dns` for the hostname.

**Connection refused:** Wrong port in config. Verify your service listens on the port specified in `config.yml`.

**Certificate error:** Expired or missing cert.pem. Re-run `cloudflared tunnel login`.

### Run as a systemd Service

For production, run cloudflared as a background service that starts on boot and restarts on failure.

Install the Service

```bash
sudo cloudflared service install
```

This creates a systemd unit file and copies your configuration to system directories.

Manage the Service

```bash
# Start the tunnel
sudo systemctl start cloudflared

# Enable on boot
sudo systemctl enable cloudflared

# Check status
sudo systemctl status cloudflared

# View logs
sudo journalctl -u cloudflared -f
```

**💡 Tip:** After installing the service, config changes should be made to `/etc/cloudflared/config.yml` followed by `sudo systemctl restart cloudflared`.

### Security Hardening

#### Restrict Inbound Firewall Rules

Since all traffic flows through the tunnel, you can block inbound HTTP/HTTPS entirely:

Lock Down UFW

```bash
# Allow SSH (keep unless tunneling SSH too)
sudo ufw allow 22/tcp

# Deny all other inbound traffic
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Enable the firewall
sudo ufw enable
sudo ufw status verbose
```

**📝 Note:** If you also tunnel SSH, you can remove the SSH allow rule for a fully locked-down server. Keep a backup access method (RamNode console) in case the tunnel goes down.

#### Enable Cloudflare Access (Zero Trust)

Put authentication in front of any tunneled service — especially admin panels and dashboards:

1. Navigate to the Cloudflare Zero Trust dashboard at `one.dash.cloudflare.com`  
2. Go to **Access → Applications** and create a new self-hosted application  
3. Set the application domain to match your tunneled hostname  
4. Configure an Access policy (e.g., allow specific email addresses or IdP groups)  
5. Save and test in an incognito window

#### Keep cloudflared Updated

Update cloudflared

```bash
sudo apt update && sudo apt upgrade -y
sudo systemctl restart cloudflared
```

#### Monitor Tunnel Health

Enable Prometheus-compatible metrics by adding to your config:

Add to config.yml (top level)

```yaml
metrics: localhost:2000
```

This exposes metrics at `http://localhost:2000/metrics` for integration with Grafana and Prometheus.

### Advanced Configuration

#### Docker Integration

Point the tunnel at Docker container ports or use Docker's internal network:

Docker Ingress Example

```yaml
ingress:
  - hostname: app.example.com
    service: http://172.17.0.2:8080        # Docker container IP

- hostname: db-admin.example.com
    service: http://host.docker.internal:8081  # Host-mapped port

- service: http_status:404
```

**💡 Tip:** For Docker Compose setups, run cloudflared as a container in the same network to reference services by name.

#### Load Balancing & Replicas

Run multiple instances of the same tunnel across different servers for high availability. Each replica uses the same UUID and credentials. Cloudflare distributes traffic automatically.

Run Replica on Each VPS

```bash
cloudflared tunnel --config /etc/cloudflared/config.yml run
```

#### Private Networking with WARP

For internal services that shouldn't be publicly accessible, use Cloudflare Tunnel with the WARP client. Team members connect through WARP and access internal IPs or hostnames directly, without public DNS exposure.

### Quick Reference

#### Essential Commands

| Command | Description |
| --- | --- |
| `cloudflared tunnel login` | Authenticate with Cloudflare |
| `cloudflared tunnel create <name>` | Create a new tunnel |
| `cloudflared tunnel list` | List all tunnels |
| `cloudflared tunnel info <name>` | Show tunnel details |
| `cloudflared tunnel route dns <tunnel> <hostname>` | Create DNS route |
| `cloudflared tunnel run` | Start tunnel (foreground) |
| `cloudflared tunnel delete <name>` | Delete a tunnel |
| `sudo systemctl restart cloudflared` | Restart the tunnel service |
| `sudo journalctl -u cloudflared -f` | Tail tunnel logs |

#### Key File Locations

| Path | Description |
| --- | --- |
| `~/.cloudflared/cert.pem` | Account authentication certificate |
| `~/.cloudflared/<UUID>.json` | Tunnel credentials file |
| `/etc/cloudflared/config.yml` | System-level tunnel configuration |
| `/var/log/cloudflared.log` | Log file (if configured) |
