//

Computers

FreeBSD Cloudflared rc.d script

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:

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.

Copyright © Celso Ferrarini Junior | [email protected]   |   English Português