I´ve installed Freebsd 14.3 in this server and I use Cloudflare Argo Tunnel with it, but the default package does not work out of the box. Already updated to the last cloudflared version 2025.8.0 but no avail. Had quite a stuggle to make it work properly, and I´m trying to report this bug and the working script through Bugzilla. Here goes the complete process, including the correct working rc.d script.
After everything installed do a backup of /usr/local/etc/cloudflared/ and /usr/local/etc/rc.d/cloudflared. You can just copy this files to another installation to work without configuring everything again and creating the tunnel.
Depois de tudo instalado, faça um backup do diretorio /usr/local/etc/cloudflared/ e /usr/local/etc/rc.d/cloudflared. Você pode apenas copiar esses aruivos em outra instalação para funcionar sem ter que configurar tudo novamente.
Also the log daemon tries ti record the log in wrong format. On the end of this tutorial follows the procedure to fix this.
1. Install cloudflared via pkg
The first step is to install cloudflared on FreeBSD. Use the official package available in the repository:
pkg install cloudflared
After installation, confirm by running:
cloudflared --version
2. Authenticate and generate cert.pem
For cloudflared to create tunnels and access your Cloudflare account, you must authenticate:
cloudflared tunnel login
This opens a browser URL where you authorize your account.
Once authorized, FreeBSD automatically receives the file:
/usr/local/etc/cloudflared/cert.pem
3. Create a tunnel and generate the JSON credentials file
Now create the tunnel. Replace TUNNEL_NAME with any name you want:
cloudflared tunnel create TUNNEL_NAME
This command returns a Tunnel ID and saves the file:
/usr/local/etc/cloudflared/<tunnel-id>.json
Save this ID — you will use it in the config.yml file.
4. Create the config.yml file
With the Tunnel ID and the JSON file ready, create the main configuration file:
tunnel: (your_tunnel_id)
credentials-file: /usr/local/etc/cloudflared/(your_tunnel_id).json
protocol: quic # or http2, or auto
ingress:
- hostname: your_host.com
service: http://localhost:80
originRequest:
- service: http_status:404
Save it at:
/usr/local/etc/cloudflared/config.yml
5. Create and install the rc.d script
The FreeBSD version often ships with a broken rc.d script. Use the fixed version below:
#!/bin/sh
# PROVIDE: cloudflared
# REQUIRE: NETWORKING
# BEFORE: LOGIN
. /etc/rc.subr
name="cloudflared"
rcvar="cloudflared_enable"
pidfile="/var/run/${name}.pid"
logfile="/var/log/${name}.log"
cloudflared_bin="/usr/local/bin/cloudflared"
cloudflared_conf="/usr/local/etc/cloudflared/config.yml"
load_rc_config $name
: ${cloudflared_enable:="NO"}
start_cmd="cloudflared_start"
stop_cmd="cloudflared_stop"
status_cmd="cloudflared_status"
cloudflared_start()
{
echo "Starting cloudflared..."
/usr/sbin/daemon \
-r \
-f \
-p ${pidfile} \
-o ${logfile} \
${cloudflared_bin} --config ${cloudflared_conf} tunnel run
}
cloudflared_stop()
{
echo "Stopping cloudflared..."
[ -f "${pidfile}" ] && kill -15 $(cat ${pidfile}) 2>/dev/null
rm -f ${pidfile}
}
cloudflared_status()
{
if [ -f "${pidfile}" ]; then
echo "cloudflared is running (PID $(cat ${pidfile}))"
else
echo "cloudflared is not running"
return 1
fi
}
run_rc_command "$1"
Save it as:
/usr/local/etc/rc.d/cloudflared
Make it executable:
chmod +x /usr/local/etc/rc.d/cloudflared
6. Enable the service on boot
Add it to rc.conf:
sysrc cloudflared_enable=YES
Start the service:
service cloudflared start
7. Test the tunnel and check logs
Verify that the tunnel connected correctly:
cloudflared tunnel info (tunnel_id)
Check logs:
tail -f /var/log/cloudflared.log
8. Configure DNS in Cloudflare
Final step: point your hostname to the tunnel.
In Cloudflare Dashboard → DNS → Add record:
Type: CNAME
Name: your domain
Target: _your_tunnel_id.cfargotunnel.com
Your tunnel is now fully configured and persistent on FreeBSD.
SUMMARY OF IMPORTANT FILES
/usr/local/etc/cloudflared/cert.pem Cloudflare Account Certificate (created on login)
/usr/local/etc/cloudflared/TUNNEL_ID.json Tunnel Credentials
/usr/local/etc/cloudflared/config.yml Main Config
/usr/local/etc/rc.d/cloudflared FreeBSD Initialization Script
/var/log/cloudflared.log Daemon Logs
9. Fixing the cloudflared log and configuring newsyslog
By default, cloudflared uses the daemon command to write logs to /var/log/cloudflared.log.
After FreeBSD upgrades or cloudflared package updates, this file may disappear or lose its rotation configuration,
causing newsyslog errors such as invalid column count, incompatible format, or failure to rotate the log.
To ensure the log works correctly, follow the steps below:
9.1 Create the log file (if it does not exist)
touch /var/log/cloudflared.log chmod 640 /var/log/cloudflared.log chown root:wheel /var/log/cloudflared.log
These commands create the file with the correct permissions so the daemon process can write to it,
and so newsyslog can rotate it without issues.
9.2 Create the newsyslog configuration
Create the file:
/usr/local/etc/newsyslog.conf.d/cloudflared.conf
With the following content:
/var/log/cloudflared.log 640 7 1000 * JC
Explanation of each field:
- 640 — permissions of the newly rotated file
- 7 — keep up to 7 old log files
- 1000 — rotate when the file reaches 1000 KB
- * — do not rotate based on time
- J — compress rotated logs using bzip2
- C — create a new log file after rotation
This rule prevents common problems such as “invalid format,” “wrong number of columns,” and daemon startup failures caused by broken or missing log files.
9.3 Test the newsyslog configuration
To simulate without applying changes:
newsyslog -n
To execute rotation immediately:
newsyslog
9.4 Restart syslog and cloudflared
service syslogd restart service cloudflared restart
Your cloudflared logging system is now fully functional, properly rotating, and compatible with FreeBSD’s expected log format.