Adding Daemons to OpenBSD 6

Aug 19, 2018  

The irony of having a BSD centric post as my first post on the linuxlab blog is not lost on me…

As a Linux admin by trade for the last two decades, I’ve only dabbled in BSD here and there. My last prior real experience with a BSD was when FreeBSD 5 was considered unstable. So it’s been quite a while.

Why am I doing this?

I had a thought that I might want to try to “spin up” an OpenBSD webhead for cheap on a VPS provider, just to get my bearings again with the progress of the razor-sharp security focused BSD Distribution. Caddy is my preferred http daemon these days since its dead simple to configure and get started with. But it doesn’t exist in the package tree. So we’ll manually install it and set it up to auto-start on boot.

Install Caddy on OpenBSD 6

Installation of caddy was quite painless. We’ll need to add the curl package in order to get started

pkg_add curl
pkg_add bash

Once we’ve installed curl from the ports package tree, lets go ahead and grab caddy from its official upstream.

Note: the following is not considered best practice, but included for expediency, and contains my default set of plugins.

curl https://getcaddy.com | bash -s http.cache,http.ipfilter,http.ratelimit

Now that caddy is installed, we can verify this with a which command.

$ which caddy
/usr/local/bin/caddy

Great, we have the daemon binary installed, we’ll skip the Caddy configuration for now, and examine the rc scripts.

RC Scripting

This is where I was really tripped up. I didn’t think I’d ever find myself saying this but I really kind of missed systemd in this particular instance. And that’s only because I’m intimately familiar with how to create and manage services in systemd (or upstart, or sysvinit for that matter).

OpenBSD uses a very simplistic RC init system that is deceptively complex. And I’m only 80% clear on why I did some of the things I did along this process.

EDIT - Located a Template

After writing this article, I ran across a template for writing your rc files distributed via the upstream CVS server.

Inspect the templat here This will ease creation of new RC files significantly.

Create the rc.d/caddy file

Daemons are executed with an rc script, and they can load a special set of shell helpers to make generating rc files quick - given that you know the framework in use.

The following is the contents of /etc/rc.d/caddy

#!/bin/ksh
#
# $OpenBSD: caddy 2018/08/19 

daemon="/usr/local/bin/caddy"
daemon_flags="-conf /etc/Caddyfile"

. /etc/rc.d/rc.subr

rc_bg=YES
rc_reload=NO

rc_start() {
  ${rcexec} "${daemon} ${daemon_flags} ${_bg}"
}

rc_check() {
  pgrep -T "${daemon_rtable}" -q -xf "${pexp}"
}

rc_stop() {
  pkill -T "${daemon_rtable}" -xf "${pexp}"
}

rc_cmd $1

You’ll notice that we source /etc/rc.d/rc.subr - this is the magic sauce that gives you the flexibility to free-form your rc file.

Each function defined: rc_start, rc_check, rc_stop refer to a state/event happening during the daemons lifecycle. We invoke rcexec to control the process kind of like we would with start-stop-daemon in older linux installations.

Note: I’m not entirely positive in rcexec works at all like start-stop daemon but this is my own anecdotal findings.

We’ve scripted a few commands to feed back information in to the rc.subr framework in the rc_check invocation, which lets the rc system know when caddy is running. And as you might have guessed. rc_stop simply kills the parent thread of the executing daemon.

We’re not quite done yet, we’ll need to inform the RC system about caddy’s existance in /etc/rc.conf.local:

pkg_scripts="caddy"

Now, we can use rcctl to enable and start caddy.

sudo rcctl enable caddy
sudo rcctl start caddy

If you’ve placed the config file in /etc/Caddyfile you should be able to navigate to your server’s IP and get a response. There’s still more to do here, like privilege de-escalation (its currently running as root). But this is a good start, that we have a functional Caddy rc file.

Man pages for further reading

The BSD Man pages are an excellent guide, and will serve to help you along the way. I found the following man pages of great use in my journey to this minimally functioning rc script:

man 8 rc
man 8 rc.conf
man 8 rc.subr

Happy hacking out there! Until next time.