Writing syslog Daemons Which Cooperate Nicely With systemd

Here are a few notes on things to keep in mind when you work on a classic BSD syslog daemon for Linux, to ensure that your syslog daemon works nicely together with systemd. If your syslog implementation does not follow these rules, then it will not be compatible with systemd v38 and newer.

A few notes in advance: systemd centralizes all log streams in the Journal daemon. Messages coming in via /dev/log, via the native protocol, via STDOUT/STDERR of all services and via the kernel are received in the journal daemon.

The journal daemon then stores them to disk or in RAM (depending on the configuration of the Storage= option in journald.conf), and optionally forwards them to the console, the kernel log buffer, or to a classic BSD syslog daemon – and that’s where you come in.

Note that it is now the journal that listens on /dev/log, no longer the BSD syslog daemon directly. If your logging daemon wants to get access to all logging data then it should listen on /run/systemd/journal/syslog instead via the syslog.socket unit file that is shipped along with systemd. On a systemd system it is no longer OK to listen on /dev/log directly, and your daemon may not bind to the /run/systemd/journal/syslog socket on its own. If you do that then you will lose logging from STDOUT/STDERR of services (as well as other stuff).

Your BSD compatible logging service should alias syslog.service to itself (i.e. symlink) when it is enabled. That way syslog.socket will activate your service when things are logged. Of course, only one implementation of BSD syslog can own that symlink, and hence only one implementation can be enabled at a time, but that’s intended as there can only be one process listening on that socket. (see below for details how to manage this symlink.)

Note that this means that syslog.socket as shipped with systemd is shared among all implementations, and the implementation that is in control is configured with where syslog.service points to.

Note that journald tries hard to forward to your BSD syslog daemon as much as it can. That means you will get more than you traditionally got on /dev/log, such as stuff all daemons log on STDOUT/STDERR and the messages that are logged natively to systemd. Also, we will send stuff like the original SCM_CREDENTIALS along if possible.

(BTW, journald is smart enough not to forward the kernel messages it gets to you, you should read that on your own, directly from /proc/kmsg, as you always did. It’s also smart enough never to forward kernel messages back to the kernel, but that probably shouldn’t concern you too much…)

And here are the recommendations:

Here are a few other recommendations, that are not directly related to systemd:

The unit file you install for your service should look something like this:

[Unit]
Description=System Logging Service
Requires=syslog.socket

[Service]
ExecStart=/usr/sbin/syslog-ng -n
StandardOutput=null

[Install]
Alias=syslog.service
WantedBy=multi-user.target

And remember: don’t ship any socket unit for /dev/log or /run/systemd/journal/syslog (or even make your daemon bind directly to these sockets)! That’s already shipped along with systemd for you.