Daniel Ziltener

Write And Auto-Deploy Daemons on FreeBSD

Daniel Ziltener, 2022-09-08

Our goal is to write an rc.d file that allows us to start anything as a daemon, and an accompanying settings file, and to get to know the commands to use for automated deploy.

Settings File

We will start with the settings file. Technically you can do in there whatever you want; if you have any sanity left, you will simply use it to set environment variables. This makes it easy to follow the third rule of the Twelve-Factor App. And it really is that simple, you just add export statements, and make "dummy values" you will replace in your CI/CD script using sed:

export HTTP_PORT=3000
export POSTGRES_IP=SED_PGSQL_IP
export POSTGRES_USERNAME=SED_PGSQL_USER
export POSTGRES_PASSWORD=SED_PGSQL_PASS

This file has to be stored with the same name as your actual service file, but under /usr/local/etc/rc.conf.d/. The RC system will auto-detect it.

Daemon File

This one is going to be a little bit longer. Let’s first take a look at the whole script:

#!/bin/sh

# PROVIDE: location_service
# REQUIRE: LOGIN DAEMON NETWORKING
# BEFORE: some_other_service
# KEYWORD: shutdown

. /etc/rc.subr

name=location_service
rcvar=${name}_enable
pidfile="/var/run/${name}.pid"
pidfile_child="/var/run/${name}_jvm.pid"
logfile="/var/log/${name}.log"
location_service_chdir="/usr/local/share/location-service"

command="/usr/sbin/daemon"
start_cmd="location_service_start"
procname="daemon"

load_rc_config ${name}
: ${location_service_enable:=no}

location_service_start() {
    /usr/sbin/daemon -r -f -P ${pidfile} -p ${pidfile_child} -t ${name} -o ${logfile} /usr/local/bin/java -jar location-service.jar
}

run_rc_command "$1"

Main Variables

There is some magic going on with the variable names, but that aside, it is a pretty standard shell script file. In this case, we are working with a location service that is to be run by the JVM, but it really doesn’t matter - you can run literally anything as a service this way.

The Daemon Command

FreeBSD ships with a program aptly called daemon, and we are using it to run our normal program as one. We thus tell the rc system to use /usr/sbin/daemon as the main command, and tell it that the process started by it - procname - will be called "daemon". We also tell it to run a custom starting function, start_cmd, which in this case is called "location_service_start".

Configure The Daemon

We configure the daemon by setting the flags when starting it. We have the following flags:

The service has to be stored under /usr/local/etc/rc.d and be made executable.

Automatic Deployment

We are almost done - the only thing missing are the commands for your CI/CD. It is really simple once you have both files at their respective locations.

You can set the config variables using sed -i.bak "s/SED_PGSQL_IP/${your_ci_var}/g" /usr/local/etc/rc.conf.d/location_service. Remember, if your variable contains the "/" character, you can use something else for sed, whatever character follows the "s" will be the separator.

Enable the service using sysrc -f /etc/rc.conf "location_service_enable=YES".

And finally, don’t forget to actually (re-)start it using service location_service restart.

Have fun!