Aug 10
Install Cloudflared on OPNsense

Overview
Cloudflare Tunnel (formerly Argo Tunnel) allows you to securely connect your internal services to the internet without opening inbound ports on your firewall. This guide shows how to install and configure cloudflared on OPNsense, which is based on FreeBSD.
Why Use Cloudflare Tunnel
- Security: No inbound ports need to be opened
- DDoS Protection: Built-in protection from Cloudflare
- SSL/TLS: Automatic SSL certificates
- Access Control: Integration with Cloudflare Access
- Performance: Global Cloudflare network acceleration
Prerequisites
- OPNsense firewall with shell access
- Cloudflare account with a domain
- Basic knowledge of OPNsense administration
Installation
Note: Cloudflare's official cloudflared releases don't support FreeBSD. We'll use a community-maintained fork at https://github.com/kjake/cloudflared that provides FreeBSD binaries compatible with OPNsense.
SSH to your OPNsense router and download the FreeBSD binary:
# Create directory for cloudflared
mkdir -p /usr/local/bin
# Download the latest FreeBSD binary (version 2025.8.0)
fetch -o /usr/local/bin/cloudflared https://github.com/kjake/cloudflared/releases/download/2025.8.0/cloudflared-freebsd14-amd64
# Make it executable
chmod +x /usr/local/bin/cloudflared
# Verify installation
cloudflared --version
Choose Your Setup Method
Method 1 (Recommended): Token-based setup - Simpler, uses Cloudflare Dashboard
Method 2: Configuration file setup - More control, requires CLI tunnel creation
Method 1: Token-based Setup (Recommended)
This method is simpler and more secure as it uses tokens generated from the Cloudflare Dashboard.
Getting Your Tunnel Token
- Go to Cloudflare Zero Trust Dashboard
- Navigate to Access > Tunnels
- Create a new tunnel or select an existing one
- Click Configure and copy the tunnel token from the installation command
Service Configuration
1. Create RC Script
Create /usr/local/etc/rc.d/cloudflared
:
#!/bin/sh
# PROVIDE: cloudflared
# REQUIRE: NETWORKING SERVERS
# KEYWORD: shutdown
. /etc/rc.subr
name="cloudflared"
rcvar="cloudflared_enable"
logfile="/var/log/cloudflared.log"
pidfile="/var/run/cloudflared.pid"
procname="/usr/local/bin/cloudflared"
load_rc_config $name
: ${cloudflared_enable:="NO"}
: ${cloudflared_mode:="tunnel"}
# Load token from secure file
if [ -f /usr/local/etc/cloudflared/token ]; then
token=$(cat /usr/local/etc/cloudflared/token)
command_args="${cloudflared_mode} --token ${token}"
else
command_args="${cloudflared_mode}"
fi
command="/usr/sbin/daemon"
command_args="-o ${logfile} -p ${pidfile} -f ${procname} ${command_args}"
run_rc_command "$1"
2. Set Permissions
Make the script executable:
chmod 755 /usr/local/etc/rc.d/cloudflared
3. Store Token Securely
Create a secure location for your Cloudflare tunnel token:
# Create directory
mkdir -p /usr/local/etc/cloudflared
# Store your tunnel token (replace with actual token)
echo "your-tunnel-token-here" > /usr/local/etc/cloudflared/token
# Secure the token file
chmod 600 /usr/local/etc/cloudflared/token
4. Configure RC
Add these lines to /etc/rc.conf
:
cloudflared_enable="YES"
cloudflared_mode="tunnel --no-autoupdate run --post-quantum"
5. Start the Service
# Start the service
service cloudflared start
# Check status
service cloudflared status
# View logs
tail -f /var/log/cloudflared.log
Method 2: Configuration File Setup
This method uses CLI commands to create tunnels and configuration files. More complex but offers more granular control.
Tunnel Creation
1. Authenticate with Cloudflare
# Login to Cloudflare (this will open a browser for authentication)
cloudflared tunnel login
This creates a certificate file at /root/.cloudflared/cert.pem
.
2. Create a Tunnel
# Create a new tunnel (replace 'opnsense-tunnel' with your preferred name)
cloudflared tunnel create opnsense-tunnel
# List your tunnels to verify
cloudflared tunnel list
This creates a tunnel credentials file at /root/.cloudflared/<tunnel-id>.json
.
Configuration
1. Create Configuration File
Create the cloudflared configuration file:
mkdir -p /usr/local/etc/cloudflared
Create /usr/local/etc/cloudflared/config.yml
:
tunnel: opnsense-tunnel
credentials-file: /root/.cloudflared/<tunnel-id>.json
ingress:
# Route web traffic to OPNsense web interface
- hostname: opnsense.yourdomain.com
service: https://127.0.0.1:443
originServerName: opnsense.yourdomain.com
# Route SSH traffic
- hostname: ssh.yourdomain.com
service: ssh://127.0.0.1:22
# Default rule (required)
- service: http_status:404
Replace <tunnel-id>
with your actual tunnel ID and yourdomain.com
with your domain.
2. Configure DNS
Add DNS records to point to your tunnel:
# Add DNS records
cloudflared tunnel route dns opnsense-tunnel opnsense.yourdomain.com
cloudflared tunnel route dns opnsense-tunnel ssh.yourdomain.com
Service Configuration
1. Create RC Script
Create /usr/local/etc/rc.d/cloudflared
:
#!/bin/sh
# PROVIDE: cloudflared
# REQUIRE: NETWORKING SERVERS
# KEYWORD: shutdown
. /etc/rc.subr
name="cloudflared"
rcvar="cloudflared_enable"
logfile="/var/log/cloudflared.log"
pidfile="/var/run/cloudflared.pid"
procname="/usr/local/bin/cloudflared"
load_rc_config $name
: ${cloudflared_enable:="NO"}
: ${cloudflared_mode:="--config /usr/local/etc/cloudflared/config.yml tunnel run"}
command="/usr/sbin/daemon"
command_args="-o ${logfile} -p ${pidfile} -f ${procname} ${cloudflared_mode}"
run_rc_command "$1"
2. Set Permissions
Make the script executable:
chmod 755 /usr/local/etc/rc.d/cloudflared
3. Configure RC
Add these lines to /etc/rc.conf
:
cloudflared_enable="YES"
4. Start the Service
# Start the service
service cloudflared start
# Check status
service cloudflared status
# View logs
tail -f /var/log/cloudflared.log
Testing
Both methods use the same testing approach since they both use the daemon and log to the same location:
# Check service status
service cloudflared status
# View logs (both methods log here)
tail -f /var/log/cloudflared.log
# Test web access (replace with your actual tunnel domain)
curl -I https://your-tunnel-domain.com
# For Method 1 - Test token connectivity
cloudflared tunnel info --token $(cat /usr/local/etc/cloudflared/token)
# For Method 2 - Test tunnel status
cloudflared tunnel info opnsense-tunnel
Troubleshooting
Common Issues
- Permission errors: Ensure cloudflared binary has execute permissions
- DNS resolution: Verify DNS records are properly configured
- Certificate issues: Check that
/root/.cloudflared/cert.pem
exists - Service won't start: Check configuration file syntax
Debugging Commands
For token-based setup:
# Run cloudflared in foreground for debugging
cloudflared tunnel --token $(cat /usr/local/etc/cloudflared/token) --no-autoupdate run --post-quantum
# Check service logs
tail -f /var/log/cloudflared.log
# Test token validity
cloudflared tunnel info --token $(cat /usr/local/etc/cloudflared/token)
For configuration file setup:
# Run cloudflared in foreground for debugging
cloudflared --config /usr/local/etc/cloudflared/config.yml tunnel run
# Check tunnel connectivity
cloudflared tunnel info opnsense-tunnel
# Validate configuration
cloudflared tunnel ingress validate
Common Token Issues
- Invalid token format: Ensure token is copied correctly without extra characters
- File permissions: Verify
/usr/local/etc/cloudflared/token
has 600 permissions - Service user: Ensure the daemon can read the token file
- Token expiration: Tokens don't expire but may be revoked - check Cloudflare dashboard
Security Considerations
- Token Security: Store your tunnel token securely with proper file permissions (600)
- Never share tokens: Keep your tokens private and rotate them regularly
- Monitor logs: Regularly check
/var/log/cloudflared.log
for suspicious activity - Update regularly: Keep cloudflared binary updated to the latest version
- Use Cloudflare Access: Implement additional authentication layers
- Firewall rules: Apply least-privilege access rules
- Backup tokens: Store backup tokens securely in case of emergencies
Updating cloudflared
To update cloudflared to the latest version from the fork repository:
# Stop the service
service cloudflared stop
# Check for latest version at https://github.com/kjake/cloudflared/releases
# Download latest version (replace version number as needed)
fetch -o /usr/local/bin/cloudflared https://github.com/kjake/cloudflared/releases/download/2025.8.0/cloudflared-freebsd14-amd64
# Make executable
chmod +x /usr/local/bin/cloudflared
# Start the service
service cloudflared start
References
- Cloudflare Tunnel Documentation
- FreeBSD cloudflared Fork - Community-maintained FreeBSD builds
- OPNsense Documentation
- FreeBSD Handbook