April 16, 2025

System logs are an important source of information about events that happened during the runtime of the system. FreeBSD’s default logging system, called syslog, writes them to /var/log/ as different files based on the subject matter. The most common events, as well as those that don’t fit anywhere else, are written to /var/log/messages.

Log rotation

Over time, logs grow and get rotated by the newsyslog daemon. During the rotation, newsyslog creates a new log and renames the old log file, while compressing it to save space. The default naming scheme is to add a number (or increase it) based on the age. For example, the current log file gets the extension .1 added and newsyslog renames the old .1 file to .2. Log files that would rotate past .7 get deleted as the oldest logs. Two configuration files control the size, total number of logs, and other rotation rules and how to log in general: /etc/newsyslog.conf and syslog.conf.

ZFS data Compression

OpenZFS has some powerful and efficient compression algorithms available to compress data on the fly in a dataset. Whenever the system writes a log file, ZFS compresses it in main memory before it reaches the underlying storage. When reading the file again, ZFS transparently uncompresses the requested data and presents it uncompressed to the application. This yields tremendous benefits both in compression ratio and convenience, since the filesystem does all the compression steps automatically. The syslog compression is still done in the traditional way by zipping and unzipping files. When accessing the contents of an old log file, the user needs to uncompress or view it using a program like bzcat first. ZFS also yields higher compression ratios, which is why it makes sense to let ZFS take control of the syslog compression, too.

Configuring newsyslog

When running a root-on-ZFS system /var/log resides on a separate dataset. Display the current compression algorithm used by running the following command:

zfs get compression zroot/var/log

We use the default pool name (zroot) used in the FreeBSD installer. Change it in these examples when zpool list -Ho name returns a different name. If this returns off, then set it to one of the available compression algorithms listed in zfsprops. Good starting values are lz4 or even zstd.

zfs set compression=zstd zroot/var/log

Remember that ZFS compresses new data, not the existing files that are in the dataset already. We’ll make some changes to disable newsyslog’s compression next. FreeBSD documents the fields of /etc/newsyslog.conf in newsyslog.conf(5). The last column (flags) in the configuration file contains the compression algorithm to apply when rotating a log file. Since we want ZFS to do the compression, remove the J from this column for each such log file listed there. Once finished with the changes, save and exit newsyslog.conf.

Changing syslog’s rotation naming scheme

This step is not necessary, but provides a simple way of identifying the timeframe from a rotated log file. We wrote above that older log files get an extension from .1 up to .7. When looking for an older log, it may be tedious to open all those old log files to find a specific one from a certain date. Wouldn’t it be easier to have the file’s rotation date used instead? For example, messages.20240914T210000 indicates when the messages file was last rotated: September 14, 2024, at 21:00:00. Of course, the format is configurable and described in the -t parameter to newsyslog.

We can apply this naming scheme to each log file created by editing /etc/crontab. A line with a comment above like this is what we need to find:

# Rotate log files every hour, if necessary.
0       *       *       *       *       root    newsyslog

Change it to the following:

# Rotate log files every hour, if necessary.
0       *       *       *       *       root    newsyslog -t DEFAULT

Save and exit.

Activating the changes

To let these changes take effect, restart both the newsyslog and syslog daemons:

service newslog restart
service syslogd restart

ZFS will now see uncompressed log files in /var/log. Log rotation still happens, but the old logs are not compressed by newsyslog anymore. To check the space savings achieved by the compression, run this command:

zfs get refcompressratio zroot/var/log

Here is the output from a system where this change happened weeks ago:

NAME           PROPERTY          VALUE     SOURCE
zroot/var/log  refcompressratio  40.60x    -

This means the log is 1/40 the original, uncompressed size. ZFS also provides details about the original size without compression as a property:

zfs get used,logicalreferenced zroot/var/log
NAME           PROPERTY           VALUE   SOURCE
zroot/var/log  used               2.28M   -
zroot/var/log  logicalreferenced  91.0M   -

The result is a good amount of space saved for a small change. The new log files also receive the new naming scheme when rotating from now on. Find out more about logging in FreeBSD by reading the Configuring System Logging handbook chapter.

Although the changes here are small and few, we have also put together an Ansible play to automate it for you 😊 You can find it here.