A simple rc.d script to run your release as a daemon on FreeBSD

I don’t know if anyone is running Elixir releases as system services on FreeBSD but below is the simplest working solution I’ve found and been using so far.

The example service is called repp , and the following script should be placed in /usr/local/etc/rc.d/ .

# PROVIDE: repp
# REQUIRE: epmd
# AFTER: epmd
# KEYWORD: shutdown
#
# Add the following line to /etc/rc.conf to enable Repp
#
# repp_enable="YES"

. /etc/rc.subr

name="repp"
rcvar="repp_enable"

load_rc_config $name

: ${repp_enable:="NO"}
: ${repp_user:="www"}

repp_command="/usr/local/lib/repp/bin/repp"

cpidfile="/var/run/${name}/${name}.pid"
pidfile="/var/run/${name}/${name}d.pid"
command=/usr/sbin/daemon
command_args="-P ${pidfile} -p ${cpidfile} -r -f -S ${repp_command} start"

start_precmd="${name}_prestart"

repp_prestart()
{
    if [ ! -d /var/run/${name} ]; then
        install -d -o ${repp_user} /var/run/${name}
    fi
}

run_rc_command "$1"
  • The service is network-facing and that’s why I use the www user.
    • I never run services as root, even in jails.
  • FreeBSD’s daemon utility is used to detach the process from the terminal.
    • The -r flag makes daemon restart its child, the beam.smp process, when it crashes.
    • -f redirects stdout and stderr to /dev/null before -S redirects them to syslog .
  • The canonical place to create pid files is /var/run so the directory /var/run/repp is created if it doesn’t exist already.

From here, you can make it as complex as you want.

A similar setup is covered in Practical rc.d scripting in BSD | FreeBSD Documentation Portal. If anyone is interested in the topic, I’d advise them to look in the official docs first. I read many articles which claimed to show working solutions but they either didn’t use the daemon utility and didn’t redirect logs to syslog or used the daemon utility in conjunction with <release> daemon which creates an OS supervisor, which starts run_erl, which starts the release. Not optimal.

2 Likes