systemd configuration
=====================

Even if systemd works well with the default configuration, it needs to be
configured on some system so that logs don't fill the disk, ...

Logging: syslog and journald
----------------------------

On most of my systems I'm using syslog-ng to manage my log files. This
interfaces quite well with journald as the only thing you need to do to make it
work is to use these sources in ``/etc/syslog-ng/syslog-ng.conf``::

    source src {
      unix-dgram("/run/systemd/journal/syslog");
      internal();
      file("/proc/kmsg");
    };

Once this is done, you no longer need persistent storage to /var/log/journal.
Instead of deleting this directory or making it a tmpfs, the right way to
disable persistent storage is to set this into ``/etc/systemd/journald.conf``::

    Storage=volatile
    ForwardToSyslog=yes
    ForwardToKMsg=no
    ForwardToConsole=no

More information can be found in the man page:
http://www.freedesktop.org/software/systemd/man/journald.conf.html

If you use persistent storage, you may want to rotate logs every 3 months for
example. This option in ``/etc/systemd/journald.conf`` tells journald to do
this::

    MaxRetentionSec=3month

Logging: audit logs and journald
--------------------------------

journald can listen to the audit socket for events. Even if that could be
useful without ``auditd`` service, it can spam the logs when using software
such as Chrome (https://bugs.chromium.org/p/chromium/issues/detail?id=456535
has been opened for more than a year) and it does not honour auditctl
configuration such as::

    auditctl -a never,exit -F arch=b64 -S set_robust_list -F path=/usr/lib/chromium/chromium -F key=bug456535

(This line without ``auditctl`` can be put in
``/etc/audit/rules.d/chromium.rules`` so that ``augenrules --load`` loads this
at every boot).

To disable this journald feature, the easier way consists in masking the audit
socket (cf. https://github.com/systemd/systemd/issues/959#issuecomment-174541674):

.. code-block:: sh

    systemctl mask systemd-journald-audit.socket

Write journal on tty
--------------------

On a workstation, it can be quite convenient to read the journal directly from
ttys above 7 (tty1-6 being consoles and tty7 the X Window session, for example).

With syslog-ng, the configuration is quite straightforward::

    source src { system(); };
    destination d_tty9 { file("/dev/tty9" owner(-1) group(-1) perm(-1)); };
    destination d_tty10 { file("/dev/tty10" owner(-1) group(-1) perm(-1)); };
    destination d_tty11 { file("/dev/tty11" owner(-1) group(-1) perm(-1)); };
    destination console_all { file("/dev/tty12" owner(-1) group(-1) perm(-1)); };
    filter f_authpriv { facility(auth, authpriv); };
    filter f_daemon { facility(daemon); };
    filter f_kernel { facility(kern); };
    log { source(src); filter(f_authpriv); destination(d_tty9); };
    log { source(src); filter(f_daemon); destination(d_tty10); };
    log { source(src); filter(f_kernel); destination(d_tty11); };
    log { source(src); destination(console_all); };

It is also possible to send emergency messages to everyone logged in::

    source s_src {
        system();
        internal();
    };
    destination du_all { usertty("*"); };
    filter f_emerg { level(emerg); };
    log { source(s_src); filter(f_emerg); destination(du_all); };

With journald, the only "natively" available feature is logging to a tty, with
something like this in ``/etc/systemd/journald.conf``::

    ForwardToConsole=yes
    TTYPath=/dev/tty12
    MaxLevelConsole=info

The other filters can be implemented with services.  Here are some files.

``/etc/systemd/system/journal@.service``::

    [Unit]
    Description=Show journal on %I
    After=systemd-journald.service
    ConditionPathExists=/dev/%I

    [Service]
    Type=idle
    StandardOutput=tty
    TTYPath=/dev/%I
    TTYReset=yes
    TTYVHangup=yes

    [Install]
    WantedBy=multi-user.target

``/etc/systemd/system/journal@tty9.service``::

    .include /etc/systemd/system/journal@.service

    [Unit]
    Description=Show journal on %I (auth)

    [Service]
    # Facilities: 4 = LOG_AUTH, 10 = LOG_AUTHPRIV
    ExecStart=/usr/bin/journalctl -b -n50 SYSLOG_FACILITY=4 SYSLOG_FACILITY=10

``/etc/systemd/system/journal@tty10.service``::

    .include /etc/systemd/system/journal@.service

    [Unit]
    Description=Show journal on %I (daemon)

    [Service]
    # Facility codes:
    #   2 = LOG_MAIL
    #   3 = LOG_DAEMON
    #   5 = LOG_SYSLOG
    #   6 = LOG_LPR
    #   7 = LOG_NEWS
    #   8 = LOG_UUCP
    #   9 = LOG_CRON
    #  11 = LOG_FTP
    #
    # Not selected:
    #   0 = LOG_KERN
    #   1 = LOG_USER
    #   4 = LOG_AUTH
    #  10 = LOG_AUTHPRIV
    #  16..23 = LOG_LOCAL0..7
    #
    # Source: /usr/include/sys/syslog.h
    #   in glibc: https://sourceware.org/git/?p=glibc.git;a=blob;f=misc/sys/syslog.h;hb=HEAD
    ExecStart=/usr/bin/journalctl -b -n50 \
        SYSLOG_FACILITY=2 SYSLOG_FACILITY=3 SYSLOG_FACILITY=5 SYSLOG_FACILITY=6 \
        SYSLOG_FACILITY=7 SYSLOG_FACILITY=8 SYSLOG_FACILITY=9 SYSLOG_FACILITY=11

``/etc/systemd/system/journal@tty11.service``::

    .include /etc/systemd/system/journal@.service

    [Unit]
    Description=Show journal on %I (kernel)

    [Service]
    # --dmesg implies -b and _TRANSPORT=kernel
    ExecStart=/usr/bin/journalctl -b -f -n 50 --dmesg

    ``/etc/systemd/system/journal@tty12.service``::

    .include /etc/systemd/system/journal@.service

    [Unit]
    Description=Show journal on %I (everything)

    [Service]
    ExecStart=/usr/bin/journalctl -b -f -n 50

With such commands, it is also possible to pipe ``journalctl`` output to
``ccze`` (if installed) to colorize the logs.


Configure timers (and remove cron)
----------------------------------

systemd doesn't rely on a cron daemon to run periodic tasks but uses its own
system with calendar time events. ArchLinux provides on its wiki some config
files to replace common cron scripts:
https://wiki.archlinux.org/index.php/Systemd/cron_functionality

Since April 2014 the timers are included and enabled by default, with timer
files in ``/usr/lib/systemd/system`` and symlinks in
``/usr/lib/systemd/system/multi-user.target.wants/``. To disable some timers
which do many disk writes, an overriding unit needs to be created.

``/etc/systemd/system/disabled-timer.service``::

    [Unit]
    Description=Unit to be able to disable timers

    [Service]
    Type=oneshot
    ExecStart=/usr/bin/true


``/etc/systemd/system/updatedb.timer``::

    [Unit]
    Description=Disabled locate database update

    [Timer]
    #OnCalendar=daily
    #Persistent=true
    #OnBootSec=10min
    #OnUnitActiveSec=1d
    OnCalendar=monthly
    Unit=disabled-timer.service

Another way may consist in masking the service units, but it did not work well
back in spring 2014::

    $ systemctl mask updatedb
    Created symlink from /etc/systemd/system/updatedb.service to /dev/null.

Automatically create a bridge interface
---------------------------------------

To automatically create a bridge interface which can be used for example to
bridge together several virtual machines, here is a systemd-networkd
configuration.

``/etc/systemd/network/VMBridge.netdev``::

    [NetDev]
    Name=br0
    Kind=bridge

``/etc/systemd/network/br0.network``::

    [Match]
    Name=br0

    [Network]
    IPForward=yes

    [Address]
    Address=198.51.100.0/24