Skip to content

Journald configuration - journald.conf

Introduction

The journald.conf file is the main configuration file for the system journal journald. It defines all aspects of system journal operation - from how logs are stored, through their rotation, to compression and size limits.

Configuration file location

Journald configuration is located in several possible locations, which are checked in the following order:

  1. /etc/systemd/journald.conf.d/*.conf - configuration fragments in directory
  2. /etc/systemd/journald.conf - main configuration file
  3. /usr/local/lib/systemd/journald.conf.d/*.conf - local configuration fragments
  4. /usr/lib/systemd/journald.conf.d/*.conf - system configuration fragments
  5. /etc/systemd/journald@NAMESPACE.conf - configuration for specific namespace
  6. /etc/systemd/journald@NAMESPACE.conf.d/*.conf - configuration fragments for namespace
  7. /usr/local/lib/systemd/journald@NAMESPACE.conf.d/*.conf - local fragments for namespace
  8. /usr/lib/systemd/journald@NAMESPACE.conf.d/*.conf - system fragments for namespace

Traditionally, I recommend creating your own configuration files in the /etc/systemd/journald.conf.d/ directory with .conf extension, instead of directly modifying the main configuration file.

Configuration file format

The journald.conf file uses the standard configuration file format used by systemd:

[Journal]
Storage=auto
Compress=yes

All configuration options are in the [Journal] section.


Available configuration options

Below I present most of the available configuration options in the latest version of journald:

Data storage options

Storage=

Specifies how journal messages are stored:

  • volatile - store only in memory (in /run/log/journal/)
  • persistent - store on disk (in /var/log/journal/)
  • auto - store on disk if /var/log/journal/ directory exists, otherwise in memory (default)
  • none - no storage, all messages are discarded
Storage=persistent

Compress=

Specifies whether stored data should be compressed to save space:

  • yes - enables compression (default)
  • no - disables compression
Compress=yes

CompressionLevel=

Compression level from 1 (lowest, fastest) to 9 (highest, slowest), or from -1 (default) to 0 (none):

CompressionLevel=6

Seal=

Specifies whether journal files should be cryptographically sealed:

  • yes - enables sealing (default if cryptographic tools are available)
  • no - disables sealing
Seal=yes
How does it work?

When Seal=yes, systemd uses public key cryptography (FSS - Forward Secure Sealing) to:

  • sign logs - each journal entry is authenticated
  • protect against changes - if someone modifies the log file, the system will detect tampering
  • ensure time integrity - logs are protected against backdating

SplitMode=

Specifies how to split journal files:

  • uid - creates separate files for each user
  • login - creates separate files for each login session
  • none - stores all logs in one file (default)
SplitMode=uid

Journal Ssze limiting options

SystemMaxUse=, SystemKeepFree=

Specify maximum disk space for system (global) journals and amount of free space that should remain available:

SystemMaxUse=10G
SystemKeepFree=15%

SystemMaxFileSize=

Maximum size of a single system journal file:

SystemMaxFileSize=100M

SystemMaxFiles=

Maximum number of system journal files:

SystemMaxFiles=100

RuntimeMaxUse=, RuntimeKeepFree=

Specify maximum memory space (/run) for journals and amount of free space that should remain available:

RuntimeMaxUse=10%
RuntimeKeepFree=30%

RuntimeMaxFileSize=

Maximum size of a single journal file in memory:

RuntimeMaxFileSize=100M

RuntimeMaxFiles=

Maximum number of journal files in memory:

RuntimeMaxFiles=100

MaxFileSec=

Maximum time messages are stored in a single journal file before rotation begins:

MaxFileSec=1month

MaxRetentionSec=

Maximum time to keep journal messages (regardless of other limits):

MaxRetentionSec=1year

Access control and forwarding policy options

ForwardToSyslog=, ForwardToKMsg=, ForwardToConsole=, ForwardToWall=

Options specifying whether the journal should forward messages to other logging systems:

ForwardToSyslog=yes   # Forward to traditional syslog
ForwardToKMsg=no      # Forward to kernel kmsg buffer
ForwardToConsole=no   # Forward to console
ForwardToWall=yes     # Forward to all logged in users (wall)

MaxLevelStore=, MaxLevelSyslog=, MaxLevelKMsg=, MaxLevelConsole=, MaxLevelWall=

Specify maximum priority level of messages stored or forwarded to respective systems:

MaxLevelStore=debug
MaxLevelSyslog=info
MaxLevelKMsg=notice
MaxLevelConsole=info
MaxLevelWall=emerg

Available levels (from lowest to highest): debug, info, notice, warning, err, crit, alert, emerg

Formatting and identification options

TTYPath=

Path to terminal where journal messages should be sent:

TTYPath=/dev/console

LineMax=

Maximum length of journal message line:

LineMax=48K

ReadKMsg=

Specifies whether messages from kernel kmsg buffer should be read and stored:

ReadKMsg=yes

Audit=

Specifies whether kernel audit system should be used:

Audit=yes

Network options

SyncIntervalSec=

Specifies how often journal is synchronized to disk:

SyncIntervalSec=5m

RateLimitIntervalSec=, RateLimitBurst=

Options limiting number of messages accepted in specified time:

RateLimitIntervalSec=30s    # Time period
RateLimitBurst=10000        # Maximum number of messages in period

SystemCallArchitectures=

List of allowed system call architectures:

SystemCallArchitectures=native
How does it work?

Parameter specifying which system call architectures are allowed for given process/container. native - means process can only execute system calls compatible with system architecture it runs on (e.g. x86_64, ARM64).

Every kernel-level operation (e.g. opening file, creating process) requires system call. Different processor architectures (x86, ARM, RISC-V) have different numbers and ways of calling syscalls.

Limiting to native

If you set SystemCallArchitectures=native, process can only use syscalls of its architecture. Attempt to execute syscall from different architecture (e.g. i386 emulation on x86_64) will be blocked.

For example:

  1. In systemd (e.g. for services/containers)

[Service] SystemCallArchitectures=native RestrictAddressFamilies=AF_UNIX AF_INET

  • blocks system calls from non-native architecture
  • prevents exploits using emulation

  • In Docker/Sandboxes

docker run --security-opt systemcalls=native ...

Container can only execute syscalls compatible with host (e.g. x86_64).


CapabilityBoundingSet=

Specifies set of capability restrictions for journald process:

CapabilityBoundingSet=CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_SYS_PTRACE CAP_SYSLOG CAP_AUDIT_CONTROL CAP_AUDIT_READ

MemoryDenyWriteExecute=

Prevents code execution from memory areas marked for writing:

MemoryDenyWriteExecute=yes

SystemCallFilter=

Filter for system calls that are allowed or forbidden:

SystemCallFilter=~@clock @cpu-emulation @debug @keyring @ipc @mount @obsolete @privileged @setuid

RestrictRealtime=

Prevents process from obtaining real-time priorities:

RestrictRealtime=yes
What does this mean?

Prevents process (e.g. system service) from setting real-time scheduling priority for its threads/tasks.

In Linux processes can use scheduling policies:

SCHED_OTHER (default, shared CPU time),

SCHED_FIFO/SCHED_RR (real-time - process has higher priority than even kernel processes).

Why is it important? Security: Process with SCHED_FIFO priority can block entire system if it enters infinite loop (because it has higher priority).

Attackers can use this for DoS (Denial of Service).

Stability: Prevents accidental RT assignment due to software bug.

Config in unit file

[Service] RestrictRealtime=yes

Effect: Service process cannot use sched_setscheduler() to set SCHED_FIFO/SCHED_RR.

How to check process priorities?

ps -eo pid,comm,cls,pri | grep -E 'FF|RR' # shows RT processes chrt -p # shows scheduling policy


RestrictNamespaces=

Restricts namespaces that can be created:

RestrictNamespaces=yes
What does this mean?

Blocks process from creating new namespaces, which are foundation of containerization (Docker, LXC, podman).

Includes these namespaces:

PID (process isolation), NET (network isolation), UTS (hostname isolation), USER (UID/GID isolation),

etc.

Why is it important?

Creating namespaces can be method of container breakout or privilege escalation. E.g. attacker might try to create new PID/USER namespace to bypass restrictions.

Prevents unauthorized containerization: If service doesn't need to create containers, you can block this capability.

Unit config

[Service] RestrictNamespaces=yes

Effect: Calls like unshare(2) or clone(2) with namespace flags (CLONE_NEWPID, CLONE_NEWNET etc.) will be blocked.

Detailed options You can also block only selected namespaces:

RestrictNamespaces=pid net user # blocks only these three

or allow all:

RestrictNamespaces=no

How to check process namespaces?

ls -l /proc//ns/ # list of process namespaces


LockPersonality=

Prevents changing execution personality:

LockPersonality=yes

SplitRoundRobin=

Enables rotation mode for journal splitting:

SplitRoundRobin=no

AutoFlush=

Specifies whether data should be automatically written to disk in case of critical errors:

AutoFlush=yes

Configuration verification

After making changes to configuration, you can apply and verify them:

Reload configuration

systemctl restart systemd-journald

Check service status

systemctl status systemd-journald

Check current settings

journalctl -o json-pretty _SYSTEMD_UNIT=systemd-journald.service | less

Best Practices

  1. Conscious limit setting - adjust journal size limits to system characteristics
  2. Using compression - enable compression even at cost of slight CPU load
  3. Security - enable Seal=yes on production servers
  4. Storage - use Storage=persistent for important systems
  5. Bandwidth limits - configure RateLimitIntervalSec and RateLimitBurst for DoS protection
  6. Rotation - set appropriate MaxRetentionSec and MaxFileSec values for automatic old journal management

Notes for Latest Versions

Recent versions of journal (2024-2025) added several security-related features such as system call filtering and capability restrictions. These options help reduce potential attack vector.

[Journal]
MemoryDenyWriteExecute=yes
CapabilityBoundingSet=CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_SYS_PTRACE CAP_SYSLOG
SystemCallArchitectures=native
SystemCallFilter=~@mount @privileged @setuid
RestrictRealtime=yes
RestrictNamespaces=yes
LockPersonality=yes

These settings strengthen journald process security by limiting its privileges to necessary minimum.

Summary

Journald configuration offers comprehensive capabilities to adapt system journal behavior to various needs - from small systems with limited resources to large production servers. Latest journald versions put special emphasis on security and performance, providing additional configuration options.

Proper configuration of journald allows for effective management of system journals and their monitoring.