SYSTEMD-SYSTEM.CONF(5)

๐Ÿ’– systemd-system.conf โ€” the manual, but make it make sense ๐Ÿ’–

ok so bestie, this is the systemd-system.conf manual page, aka section 5 of the systemd manuals (SYSTEMD-SYSTEM.CONF(5) if you're being formal at a party). It covers systemd-system.conf, system.conf.d, systemd-user.conf, and user.conf.d โ€” the system and session service manager configuration files. yes, all four. we contain multitudes. ๐Ÿฆ‹


โœจ NAME โœจ

systemd-system.conf, system.conf.d, systemd-user.conf, user.conf.d โ€” these are the system and session service manager configuration files. that's the whole vibe. ๐Ÿ’…


๐ŸŒธ SYNOPSIS ๐ŸŒธ

/etc/systemd/system.conf, /run/systemd/system.conf,
/usr/lib/systemd/system.conf, /etc/systemd/system.conf.d/*.conf,
/run/systemd/system.conf.d/*.conf, /usr/lib/systemd/system.conf.d/*.conf

~/.config/systemd/user.conf, /etc/systemd/user.conf,
/run/systemd/user.conf, /usr/lib/systemd/user.conf,
/etc/systemd/user.conf.d/*.conf, /run/systemd/user.conf.d/*.conf,
/usr/lib/systemd/user.conf.d/*.conf

like, look at all those paths. it's giving "i have a place for everything and everything in its place." ๐ŸŽ€


๐Ÿ‘‘ DESCRIPTION ๐Ÿ‘‘

so when systemd runs as a system instance, it reads the config file system.conf plus all the files hanging out in the system.conf.d directories. when it runs as a user instance, it reads user.conf instead โ€” and it goes looking in order of priority, in the user's home directory and under /etc/systemd/, /run/systemd/, and /usr/lib/systemd/ โ€” plus whatever's in the user.conf.d directories.

these config files hold a lil handful of settings that control basic manager operations. nothing wild, just the fundamentals.

also, peep systemd.syntax(7) for the general description of the syntax, because grammar rules matter bestie. ๐Ÿ“š


๐Ÿ—‚๏ธ CONFIGURATION DIRECTORIES AND PRECEDENCE ๐Ÿ—‚๏ธ

the default configuration gets baked in during compilation, so you only need config files when you wanna deviate from those defaults. iconique, honestly.

the main configuration file is loaded from one of the listed directories, in order of priority โ€” and only the first file found is used:

  1. /etc/systemd/
  2. /run/systemd/
  3. /usr/local/lib/systemd/ [1]
  4. /usr/lib/systemd/

the vendor version of the file has all the defaults commented out in there as a lil guide for the administrator. thoughtful of them fr fr. ๐Ÿซถ

local overrides can also be made by creating drop-ins, described below. you can also just edit the main configuration file directly for this (or drop a copy in /etc/ if it ships under /usr/), but using drop-ins for local config is the recommended move over modifying the main file. do it the right way, queen. ๐Ÿ‘‘

now, in addition to the main configuration file, drop-in configuration snippets get read from:

  • /usr/lib/systemd/*.conf.d/
  • /usr/local/lib/systemd/*.conf.d/
  • /etc/systemd/*.conf.d/

those drop-ins have higher precedence and override the main configuration file. periodt.

files in the *.conf.d/ subdirectories get sorted by filename in lexicographic order, no matter which of the subdirectories they live in. and when multiple files specify the same option:

  • for options that take just a single value, the entry in the file sorted last wins ๐Ÿ†
  • for options that take a list of values, entries get collected as they occur in the sorted files

when packages need to customize the config, they can install drop-ins under /usr/. files in /etc/ are reserved for the local administrator โ€” that's you, bestie โ€” who can use this logic to override config files installed by vendor packages.

drop-ins have to be used to override package drop-ins, since the main configuration file has lower precedence. no sneaking around the hierarchy. ๐Ÿšซ

it's recommended to prefix all filenames in those subdirectories with a two-digit number and a dash, to keep the ordering simple. this also defines a concept of drop-in priorities, letting OS vendors ship drop-ins within a specific range lower than the range users use. which lowers the risk of package drop-ins accidentally overriding user drop-ins. love that for us. ๐Ÿ’–

the recommended ranges:

  • use 10-40 for drop-ins in /usr/
  • use 60-90 for drop-ins in /etc/ and /run/

that way local and transient drop-ins take priority over the ones the OS vendor shipped. ๐Ÿงš

to disable a configuration file supplied by the vendor, the recommended way is to place a symlink to /dev/null in the configuration directory in /etc/, with the same filename as the vendor configuration file. sneaky? maybe. correct? absolutely. ๐Ÿ’€


โš™๏ธ OPTIONS โš™๏ธ

all these options live in the [Manager] section. yes, all of them. one section, many dreams. โœจ


  • LogColor=, LogLevel=, LogLocation=, LogTarget=, LogTime=, DumpCore=yes, CrashChangeVT=no, CrashShell=no, CrashAction=freeze, ShowStatus=yes, DefaultStandardOutput=journal, DefaultStandardError=inherit โ€” configures various parameters of basic manager operation. these options may be overridden by the respective process and kernel command line arguments. peep systemd(1) for the details.

Added in version 198.

  • CtrlAltDelBurstAction= โ€” defines what action gets performed if the user presses Ctrl+Alt+Delete more than 7 times in 2s. (yes, mashing. we see you.) it can be set to "reboot-force", "poweroff-force", "reboot-immediate", "poweroff-immediate", or disabled with "none". defaults to "reboot-force".

Added in version 232.

  • StatusUnitFormat= โ€” takes name, description, or combined as the value. if name, the system manager uses unit names in status messages (e.g. "systemd-journald.service") instead of the longer, more informative descriptions set with Description= (e.g. "Journal Logging Service"). if combined, the system manager uses both unit names and descriptions in status messages (e.g. "systemd-journald.service - Journal Logging Service"). best of both worlds, honestly.

see systemd.unit(5) for details about unit names and Description=.

Added in version 243.

  • DefaultTimerAccuracySec= โ€” sets the default accuracy of timer units. this controls the global default for the AccuracySec= setting of timer units, see systemd.timer(5) for details. an AccuracySec= set in an individual unit overrides the global default for that specific unit. defaults to 1min.
note that the accuracy of timer units is also affected by the configured timer slack for PID 1, see TimerSlackNSec= above. ๐Ÿ‘€

Added in version 212.

๐ŸŽ€ RESOURCE MANAGEMENT ๐ŸŽ€

  • TimerSlackNSec= โ€” sets the timer slack, in nanoseconds, for PID 1. And bestie, PID 1's slack gets inherited by every process it executes, unless somebody overrides it individually โ€” like with the TimerSlackNSec= setting in service units (deets in systemd.exec(5)). What even is timer slack? It's the thing that controls how accurate the wake-ups triggered by system timers are. prctl(2) has more if you wanna go deeper. โฐ
Heads up: unlike most other time span definitions, this one takes an integer in nanoseconds if you don't specify a unit. The usual time units work too, don't worry.

Added in version 198.

  • CPUAffinity= โ€” sets up the CPU affinity for the service manager and the default CPU affinity for all forked off processes. Takes a list of CPU indices or ranges, separated by either whitespace or commas. A CPU range is the lower and upper CPU indices with a dash in between. You can drop this option more than once and the CPU affinity masks all get merged together. If you assign the empty string, the mask is reset โ€” everything you assigned before that point has no effect, gone, bye. Individual services can still override the CPU affinity for their own processes with the CPUAffinity= setting in unit files, see systemd.exec(5). ๐Ÿง 

Added in version 198.

  • NUMAPolicy= โ€” configures the NUMA memory policy for the service manager and the default NUMA memory policy for all forked off processes. Individual services may override the default with the NUMAPolicy= setting in unit files, see systemd.exec(5). ๐Ÿ’œ

Added in version 243.

  • NUMAMask= โ€” configures the NUMA node mask that gets associated with the selected NUMA policy. Lowkey important: the default and local NUMA policies don't need an explicit NUMA node mask, so the value of this option can be empty. And just like NUMAPolicy=, individual services can override the value in unit files, see systemd.exec(5). โœจ

Added in version 243.

  • DefaultMemoryAccounting=, DefaultTasksAccounting=, DefaultIOAccounting=, DefaultIPAccounting= โ€” these set the default resource accounting settings, matching what's configured per-unit by MemoryAccounting=, TasksAccounting=, IOAccounting=, and IPAccounting=. All the per-unit details live in systemd.resource-control(5). ๐Ÿ“Š

The tea on defaults: DefaultMemoryAccounting= defaults to yes. DefaultTasksAccounting= defaults to yes. The other settings default to no.

Added in version 211.

  • DefaultTasksMax= โ€” sets the default value for the per-unit TasksMax= setting. See systemd.resource-control(5) for the details. This one applies to all unit types that support resource control settings, with the exception of slice units. It defaults to 15% of the minimum of kernel.pid_max=, kernel.threads-max= and root cgroup pids.max. The kernel has a default value for kernel.pid_max= and an algorithm for counting when there are more than 32 cores. For example, with the default kernel.pid_max=, DefaultTasksMax= defaults to 4915, but it might be greater on other systems or smaller in OS containers. ๐Ÿ™ˆ

Added in version 228.

  • DefaultLimitCPU=, DefaultLimitFSIZE=, DefaultLimitDATA=, DefaultLimitSTACK=, DefaultLimitCORE=, DefaultLimitRSS=, DefaultLimitNOFILE=, DefaultLimitAS=, DefaultLimitNPROC=, DefaultLimitMEMLOCK=, DefaultLimitLOCKS=, DefaultLimitSIGPENDING=, DefaultLimitMSGQUEUE=, DefaultLimitNICE=, DefaultLimitRTPRIO=, DefaultLimitRTTIME= โ€” this whole lil family controls the various default resource limits for processes executed by units. setrlimit(2) has the gory details. Any individual unit can override these using the matching LimitXXX= directives, and they accept the same parameter syntax โ€” see systemd.exec(5). One thing to know: these resource limits are only defaults for units, they are not applied to the service manager process itself (aka PID 1). ๐Ÿซถ

Most of these settings are unset, which means the resource limits get inherited from the kernel or, if invoked in a container, from the container manager. But these ones do have defaults:

  • DefaultLimitNOFILE= defaults to 1024:524288.
  • DefaultLimitMEMLOCK= defaults to 8M.
  • DefaultLimitCORE= does not have a default, but it's worth mentioning that RLIMIT_CORE is set to "infinity" by PID 1, and its children inherit that.

Also note: the service manager internally in PID 1 bumps RLIMIT_NOFILE and RLIMIT_MEMLOCK to higher values, however the limit gets reverted back to those defaults for all child processes it forks off.

Added in version 198.

  • DefaultOOMPolicy= โ€” configures the default policy for reacting to processes getting killed by the Linux Out-Of-Memory (OOM) killer or systemd-oomd. Use this to pick a global default for the per-unit OOMPolicy= setting. See systemd.service(5) for details. Lowkey a gotcha: this default is not used for services that have Delegate= turned on. ๐Ÿ’€

Added in version 243.

  • DefaultOOMScoreAdjust= โ€” configures the default OOM score adjustments of processes run by the service manager. Defaults to unset, which means the forked off processes inherit the service manager's OOM score adjustment value โ€” except if the service manager is run for an unprivileged user, in which case this defaults to the service manager's OOM adjustment value plus 100. That makes service processes slightly more likely to get killed under memory pressure than the manager itself. Use this to pick a global default for the per-unit OOMScoreAdjust= setting, see systemd.exec(5). And ngl, note that this setting has no effect on the OOM score adjustment value of the service manager process itself โ€” it keeps the original value set during its invocation. ๐Ÿ˜ญ

Added in version 250.

  • DefaultMemoryPressureWatch=, DefaultMemoryPressureThresholdSec= โ€” configure the default settings for the per-unit MemoryPressureWatch= and MemoryPressureThresholdSec= settings. See systemd.resource-control(5) for details. Defaults to "auto" and "200ms", respectively. This also sets the memory pressure monitoring threshold for the service manager itself. ๐Ÿ“

Added in version 254.

  • DefaultCPUPressureWatch=, DefaultCPUPressureThresholdSec= โ€” configure the default settings for the per-unit CPUPressureWatch= and CPUPressureThresholdSec= settings. See systemd.resource-control(5) for details. Defaults to "auto" and "200ms", respectively. This also sets the CPU pressure monitoring threshold for the service manager itself. ๐Ÿ”ฅ

Added in version 261.

  • DefaultIOPressureWatch=, DefaultIOPressureThresholdSec= โ€” configure the default settings for the per-unit IOPressureWatch= and IOPressureThresholdSec= settings. See systemd.resource-control(5) for details. Defaults to "auto" and "200ms", respectively. This also sets the IO pressure monitoring threshold for the service manager itself. ๐Ÿฆ‹

Added in version 261.

โœจ HARDWARE WATCHDOG โœจ

RuntimeWatchdogSec=, RebootWatchdogSec=, KExecWatchdogSec=

okay so these three are literally the watchdog girlies ๐Ÿ’… they configure the hardware watchdog both at runtime and at reboot. They take a timeout value in seconds โ€” or in other time units if you suffix it with "ms", "min", "h", "d", "w" โ€” or the special strings "off" or "default".

  • set it to "off" (or, same energy, "0") and the whole watchdog logic is disabled: no watchdog device gets opened, configured, or pinged. it's giving "we're not doing that today".
  • set it to the special string "default" and the watchdog gets opened and pinged in regular intervals, but the timeout is not changed from the default. respectful. lowkey keeping it as-is.
  • set it to any other time value and the watchdog timeout gets configured to that specified value โ€” or a value close to it, depending on what the hardware can actually do.

so if RuntimeWatchdogSec= is set to a non-zero value, the watchdog hardware (/dev/watchdog0, or the path you gave with WatchdogDevice=, or the kernel option systemd.watchdog_device=) gets programmed to automatically reboot the system if it's not contacted within the specified timeout interval ๐Ÿซถ. The system manager will make sure to contact it at least once in half the specified timeout interval. this needs an actual hardware watchdog device to be present, which is normally the case on embedded and server systems. and ngl, not all hardware watchdogs let you configure every possible reboot timeout value โ€” in that case the closest available timeout gets picked. close enough bestie.

RebootWatchdogSec= is what you reach for to configure the hardware watchdog when the system is asked to reboot. It's the safety net, fr fr โ€” it makes sure the reboot happens even if a clean reboot attempt times out. but heads up: the RebootWatchdogSec= timeout applies only to the second phase of the reboot, i.e. after all regular services are already terminated, and after the system and service manager process (PID 1) got replaced by the systemd-shutdown binary, see system bootup(7) for details. During the first phase of the shutdown operation the system and service manager is still running, so RuntimeWatchdogSec= is still honoured there. if you wanna define a timeout on that first phase of system shutdown, configure JobTimeoutSec= and JobTimeoutAction= in the [Unit] section of the shutdown.target unit. and by default? RuntimeWatchdogSec= defaults to 0 (off), and RebootWatchdogSec= defaults to 10min. โœจ

KExecWatchdogSec= can be used to additionally enable the watchdog when kexec is being executed rather than when rebooting. โš ๏ธ but listen: if the kernel does not reset the watchdog on kexec (depends on the specific hardware and/or driver), then in this case the watchdog might not get disabled after kexec succeeds and thus the system might get rebooted โ€” unless RuntimeWatchdogSec= is also enabled at the same time. so for this reason it is recommended to enable KExecWatchdogSec= only if RuntimeWatchdogSec= is also enabled. periodt.

also bestie, these settings have no effect if a hardware watchdog is not available. like, none. ๐Ÿ’€

Added in version 198.


RuntimeWatchdogPreSec=

this one configures the hardware watchdog device pre-timeout value ๐ŸŽ€. takes a timeout value in seconds (or in other time units, similar to RuntimeWatchdogSec=).

a watchdog pre-timeout is a notification generated by the watchdog before the watchdog reset might occur, in the event the watchdog has not been serviced. This notification is handled by the kernel and can be configured to take an action (i.e. generate a kernel panic) using RuntimeWatchdogPreGovernor=. Not all watchdog hardware or drivers support generating a pre-timeout, and depending on the state of the system, the kernel may be unable to take the configured action before the watchdog reboot. lowkey chaotic but okay.

The watchdog will be configured to generate the pre-timeout event at the amount of time specified by RuntimeWatchdogPreSec= before the runtime watchdog timeout (set by RuntimeWatchdogSec=). For example, if we have RuntimeWatchdogSec=30 and RuntimeWatchdogPreSec=10, then the pre-timeout event will occur if the watchdog has not pinged for 20s (that's 10s before the watchdog would fire). By default, RuntimeWatchdogPreSec= defaults to 0 (off). The value set for RuntimeWatchdogPreSec= must be smaller than the timeout value for RuntimeWatchdogSec=.

This setting has no effect if a hardware watchdog is not available or the hardware watchdog does not support a pre-timeout, and will be ignored by the kernel if the setting is greater than the actual watchdog timeout. ๐ŸŒธ

Added in version 251.


RuntimeWatchdogPreGovernor=

this configures the action taken by the hardware watchdog device when the pre-timeout expires ๐Ÿ‘‘. The default action for the pre-timeout event depends on the kernel configuration, but it is usually to log a kernel message.

For a list of valid actions available for a given watchdog device, check the content of the /sys/class/watchdog/watchdogX/pretimeout_available_governors file. Typically, available governor types are noop and panic. Availability, names and functionality might vary depending on the specific device driver in use. If the pretimeout_available_governors sysfs file is empty, the governor might be built as a kernel module and might need to be manually loaded (e.g. pretimeout_noop.ko), or the watchdog device might not support pre-timeouts. ๐Ÿ™ˆ

Added in version 251.


WatchdogDevice=

configure the hardware watchdog device that the runtime and shutdown watchdog timers will open and use ๐Ÿฆ‹. Defaults to /dev/watchdog0.

This setting has no effect if a hardware watchdog is not available. no cap.

Added in version 236.

๐Ÿ”’ SECURITY ๐Ÿ”’

okay bestie this section is the one that keeps your system from getting absolutely owned, so pay attention ๐Ÿ’…

  • CapabilityBoundingSet= โ€” controls which capabilities get included in the capability bounding set for PID 1 and its children. (capabilities(7) has the deets if you wanna go deeper.) It takes a whitespace-separated list of capability names, read the same way cap_from_name(3) reads them. Whatever you list gets included in the bounding set, and literally everything else gets removed. If you slap a ~ in front of the list, it flips: all but the listed capabilities get included, so the assignment's effect is inverted. Heads up though โ€” this option also affects the respective capabilities in the effective, permitted and inheritable capability sets.

You can also set the capability bounding set per-unit with the CapabilityBoundingSet= directive for units, but โ€” and this is the important part โ€” capabilities you drop for PID 1 cannot be regained in individual units. They are lost for good, no take-backs, periodt ๐Ÿ˜ญ

Added in version 198.

  • NoNewPrivileges= โ€” takes a boolean. If true, PID 1 and all its children can never gain new privileges through execve(2) โ€” so no setuid or setgid bits, no filesystem capabilities, none of it. Defaults to false.
General purpose distributions commonly rely on executables with setuid or setgid bits, so they will not function properly with this option enabled. Individual units cannot disable this option either. Also see No New Privileges Flag[2].

Added in version 239.

  • ProtectSystem= โ€” takes a boolean argument or the string "auto". Set it to true and it remounts /usr/ read-only โœจ. Set it to "auto" (which is the default) and running in an initrd it's equivalent to true, otherwise it's false. This implements a restricted subset of the per-unit setting with the same name โ€” see systemd.exec(5) for the full thing. Currently the "full" or "strict" values are just not supported here, sorry babe.

Added in version 256.

  • RestrictFileSystemAccess= โ€” takes a boolean argument or the special value "exec". Defaults to "no". When you enable it, PID 1 loads a BPF LSM program that enforces a deny-default execution policy: only binaries living on signed dm-verity block devices (plus the initramfs during early boot) are allowed to execute. Execution from tmpfs, procfs, sysfs, unsigned dm-verity devices, and anonymous executable memory mappings? Denied. All of it. ๐Ÿ’€

This setting is meant to be one component of an image-based, fully verified system, where the whole boot chain (firmware, kernel image, kernel command line, initramfs) is measured and attested. On a general-purpose system without those guarantees, it does not provide a meaningful security boundary on its own: an attacker with sufficient privilege to edit system.conf, modify the kernel command line, or kexec into an unsigned initrd can disable or bypass the policy. Like, lowkey it's a vibe, not a vault.

The enforcement hooks block execve() of untrusted binaries ("bprm_check_security"), PROT_EXEC memory mappings including shared libraries ("mmap_file"), and write-to-execute transitions such as JIT compilation ("file_mprotect").

The policy also enforces W^X system-wide: no mapping may be writable and executable at the same time, and a private file mapping that has been modified through copy-on-write may not be made executable afterwards.

Since v262, files on overlayfs mounts are resolved to the layer that hosts their data, so execution from an overlay whose data resides on a signed dm-verity device is permitted, while files in a writable upper layer are denied. This requires kernel v7.2 or newer; on older kernels execution from overlayfs mounts is denied entirely. Note that only the file data is checked, so an untrusted upper layer may still control a binary's ownership and setuid bits. Multi-device filesystems such as btrfs are unsupported.

Also note that, without further measures to secure the system, kexec can be used to circumvent this. ๐Ÿ‘€

This requires the kernel to be booted with "dm_verity.require_signatures=1" and "proc_mem.force_override=never" on the kernel command line, and with BPF LSM enabled ("lsm=...,bpf").

The value "yes" is equivalent to "exec". Additional modes may be added in the future.

This option may also be set via the systemd.restrict_filesystem_access= kernel command line option, see kernel-command-line(7).

Added in version 261.

  • SystemCallArchitectures= โ€” takes a space-separated list of architecture identifiers, and picks which architectures system calls may be invoked from on this system. This is a genuinely effective way to disable invocation of non-native binaries system-wide โ€” for example, to prohibit execution of 32-bit x86 binaries on 64-bit x86-64 systems. It operates system-wide and acts similar to the SystemCallArchitectures= setting of unit files, see systemd.exec(5) for details.

This setting defaults to the empty list, in which case no filtering of system calls based on architecture is applied. The known architecture identifiers are "x86", "x86-64", "x32", "arm", plus the special identifier "native". That last one implicitly maps to the native architecture of the system (or, more specifically, the architecture the system manager was compiled for). Set this setting to "native" to prohibit execution of any non-native binaries. And when a binary executes a system call of an architecture that isn't listed in this setting, it will be immediately terminated with the SIGSYS signal. Bye bestie ๐Ÿ‘‹

Added in version 209.

  • DefaultSmackProcessLabel= โ€” takes a SMACK64 security label as the argument. The process executed by a unit will be started under this label if SmackProcessLabel= is not set in the unit. See systemd.exec(5) for the details.

If the value is "/", only labels specified with SmackProcessLabel= are assigned and the compile-time default is ignored.

Added in version 252.

  • DefaultRestrictSUIDSGID= โ€” takes a boolean argument. This is used as a default for units which lack an explicit definition for RestrictSUIDSGID=. See systemd.exec(5) for the details.

Added in version 258.


โฐ TIMEOUTS AND RATE LIMITS โฐ

the section where we teach your system some patience ๐Ÿง˜โ€โ™€๏ธ

  • DefaultTimeoutStartSec=, DefaultTimeoutStopSec=, DefaultTimeoutAbortSec=, DefaultRestartSec= โ€” these configure the default timeouts for starting, stopping and aborting units, plus the default time to sleep between automatic restarts of units, exactly like the per-unit settings TimeoutStartSec=, TimeoutStopSec=, TimeoutAbortSec= and RestartSec= do (for services, see systemd.service(5) for all the per-unit details). For non-service units, DefaultTimeoutStartSec= sets the default TimeoutSec= value.

DefaultTimeoutStartSec= and DefaultTimeoutStopSec= default to 90 s in the system manager and 90 s in the user manager. DefaultTimeoutAbortSec= is not set by default, so that all units fall back to TimeoutStopSec=. And DefaultRestartSec= defaults to 100 ms.

Added in version 209.

  • DefaultDeviceTimeoutSec= โ€” configures the default timeout for waiting for devices. It can be changed per device via the x-systemd.device-timeout= option in /etc/fstab and /etc/crypttab (see systemd.mount(5), crypttab(5)). Defaults to 90 s in the system manager and 90 s in the user manager.

Added in version 252.

  • DefaultStartLimitIntervalSec=, DefaultStartLimitBurst= โ€” configure the default unit start rate limiting, as configured per-service by StartLimitIntervalSec= and StartLimitBurst=. See systemd.service(5) for details on the per-service settings. DefaultStartLimitIntervalSec= defaults to 10s. DefaultStartLimitBurst= defaults to 5.

Added in version 209.

  • ReloadLimitIntervalSec=, ReloadLimitBurst= โ€” rate limiting for daemon-reload and (since v256) daemon-reexec requests. The setting applies to both operations, but the rate limits are tracked separately. Defaults to unset, and any number of operations can be requested at any time. ReloadLimitIntervalSec= takes a value in seconds to configure the rate limit window, and ReloadLimitBurst= takes a positive integer to configure the maximum allowed number of operations within the configured time window.

Added in version 253.

  • EventLoopRateLimitIntervalSec=, EventLoopRateLimitBurst= โ€” configures the rate limiting applied to the manager's main event loop. If the event loop iterates more than EventLoopRateLimitBurst= times within EventLoopRateLimitIntervalSec=, event processing is briefly paused to prevent excessive CPU usage. EventLoopRateLimitIntervalSec= defaults to 1s. EventLoopRateLimitBurst= defaults to 50000. These settings can also be set on the kernel command line via systemd.event_loop_ratelimit_interval_sec= and systemd.event_loop_ratelimit_burst=.

Added in version 261.

  • MinimumUptimeSec= โ€” specifies the minimum uptime for the system which has to be reached before a shutdown is executed. Defaults to 15s. This mechanism was introduced to avoid high frequency reboot loops, like when technical failures trigger an automatic shutdown during the boot process. Each reboot cycle gets delayed to the specified minimum time, giving the user a chance to review screen contents or otherwise interact with the device before the shutdown proceeds ๐Ÿซถ

The delay takes place during the very last phase of system shutdown, immediately before the reboot() system call is executed. If the system is already running for longer than the specified time, this setting has no effect. This logic is also skipped in container environments. Set it to zero in order to disable this logic.

Added in version 261.

๐ŸŒธ ENVIRONMENT ๐ŸŒธ

okay bestie, this section is all about the vibes your processes inherit before they even get out of bed ๐Ÿ’…

  • DefaultEnvironment= โ€” sets the environment variables that get passed to every single process that gets executed. it takes a space-separated list of variable assignments, and if you wanna know all the deets about environment variables in general, go peek at environ(7). lowkey important: this environment block is internal, so your changes will not show up in the manager's /proc/PID/environ. no cap.

simple %-specifier expansion is supported here โ€” scroll down for the list of specifiers that work.

for example:

DefaultEnvironment="VAR1=word1 word2" VAR2=word3 "VAR3=word 5 6"

that sets three variables: "VAR1", "VAR2", "VAR3". iconic.

Added in version 205.

  • ManagerEnvironment= โ€” this one sets environment variables for the manager process itself, not just its kids. it takes a space-separated list of variable assignments in the same format as DefaultEnvironment=, see above. these variables get merged into the existing environment block of the manager process. specifically:
    • for the system manager, that block includes variables set by the kernel based on the kernel command line;
    • for the user manager, it's the variables passed by the system manager.

once those variables are merged, they persist until overridden โ€” even if the manager gets reloaded or reexecuted. periodt. and in the case of the user manager, these variables are also inherited by processes spawned by the manager. just like with DefaultEnvironment=, this environment block is internal and changes are not reflected in the manager's /proc/PID/environ.

setting environment variables for the manager process can genuinely be useful when you wanna modify its behaviour. check out Known Environment Variables[3] for a rundown of some variables systemd understands. iykyk.

simple %-specifier expansion is supported, see below for the list of supported specifiers.

Added in version 248.

  • DefaultMemoryZSwapWriteback= โ€” takes a boolean argument, and defaults to true if you don't specify anything. this acts as the default for units that don't have an explicit definition for MemoryZSwapWriteback=. see systemd.resource-control(5) for the details, bestie.

Added in version 261.


โœจ SPECIFIERS โœจ

specifiers can be used in the DefaultEnvironment= and ManagerEnvironment= settings ๐ŸŽ€ the following expansions are understood:

๐ŸŒˆ Table 1. Specifiers available ๐ŸŒˆ

Okay bestie, here's the full roster of specifiers you can drop into your config, and literally every single one of them matters. Header row said Specifier / Meaning / Details, so that's exactly how I'm giving it to you ๐Ÿ‘‘

  • "%a" โ€” Architecture โ€” A short string identifying the architecture of the local system. A string such as x86, x86-64 or arm64. See the architectures defined for ConditionArchitecture= in systemd.unit(5) for a full list. (iykyk, arch names are their own little language)
  • "%A" โ€” Operating system image version โ€” The operating system image version identifier of the running system, as read from the IMAGE_VERSION= field of /etc/os-release. If not set, resolves to an empty string. See os-release(5) for more information. โœจ
  • "%b" โ€” Boot ID โ€” The boot ID of the running system, formatted as string. See random(4) for more information. (new boot, new b, every single time)
  • "%B" โ€” Operating system build ID โ€” The operating system build identifier of the running system, as read from the BUILD_ID= field of /etc/os-release. If not set, resolves to an empty string. See os-release(5) for more information.
  • "%H" โ€” Host name โ€” The hostname of the running system. no notes, it's just the hostname ๐Ÿ’…
  • "%l" โ€” Short host name โ€” The hostname of the running system, truncated at the first dot to remove any domain component. the little one ๐ŸŽ€
  • "%m" โ€” Machine ID โ€” The machine ID of the running system, formatted as string. See machine-id(5) for more information.
  • "%M" โ€” Operating system image identifier โ€” The operating system image identifier of the running system, as read from the IMAGE_ID= field of /etc/os-release. If not set, resolves to an empty string. See os-release(5) for more information.
  • "%o" โ€” Operating system ID โ€” The operating system identifier of the running system, as read from the ID= field of /etc/os-release. See os-release(5) for more information. (this one's got no "empty string" fallback clause, so don't come for me, that's just what it says)
  • "%v" โ€” Kernel release โ€” Identical to uname -r output. fr fr, literally the same thing ๐ŸŒˆ
  • "%w" โ€” Operating system version ID โ€” The operating system version identifier of the running system, as read from the VERSION_ID= field of /etc/os-release. If not set, resolves to an empty string. See os-release(5) for more information.
  • "%W" โ€” Operating system variant ID โ€” The operating system variant identifier of the running system, as read from the VARIANT_ID= field of /etc/os-release. If not set, resolves to an empty string. See os-release(5) for more information.
  • "%T" โ€” Directory for temporary files โ€” This is either /tmp or the path "$TMPDIR", "$TEMP" or "$TMP" are set to. (Note that the directory may be specified without a trailing slash.) โš ๏ธ watch the no-trailing-slash thing, it's giving sneaky
  • "%V" โ€” Directory for larger and persistent temporary files โ€” This is either /var/tmp or the path "$TMPDIR", "$TEMP" or "$TMP" are set to. (Note that the directory may be specified without a trailing slash.) big temp energy ๐Ÿ“
  • "%h" โ€” User home directory โ€” This is the home directory of the user running the service manager instance. ๐Ÿ  home sweet home
  • "%u" โ€” Username โ€” This is the username of the user running the service manager instance. main character username โœจ

Bestie note: that's the whole specifier menu, and yes, every single one is fair game in your configs ๐Ÿ’–

  • %U โ€” User id โ€” bestie, this is the user id of the user running the service manager instance. ๐Ÿ’–
  • %G โ€” Primary group id โ€” the primary group id of the user running the service manager instance. โœจ
  • %g โ€” Primary group โ€” the primary group of the user running the service manager instance. ๐ŸŽ€
  • %s โ€” User shell โ€” this is the shell of the user running the service manager instance. ๐Ÿฆ‹
  • %% โ€” Single percent sign โ€” use "%%" in place of "%" to specify a single percent sign. no cap, that's the escape hatch. ๐Ÿ’…

๐Ÿ“œ HISTORY ๐Ÿ“œ

okay so the lore, let's get into it ๐Ÿซถ

systemd 252

DefaultBlockIOAccounting= was deprecated. Please switch to the unified cgroup hierarchy. it's giving "move on bestie", fr fr ๐Ÿ˜ญ

systemd 258

DefaultCPUAccounting= setting is deprecated, because CPU accounting is always available on the unified cgroup hierarchy and such setting has no effect. likeโ€ฆ it's a whole lot of nothing, lowkey ๐Ÿ’€


๐Ÿ‘€ SEE ALSO ๐Ÿ‘€

go read these next, i'm literally obsessed with a good cross-reference ๐ŸŒธ


๐Ÿ“ NOTES ๐Ÿ“

  1. ๐Ÿ’ฃ๐Ÿ’ฅ๐Ÿงจ๐Ÿ’ฅ๐Ÿ’ฅ๐Ÿ’ฃ Please note that those configuration files must be available at all times. If /usr/local/ is a separate partition, it may not be available during early boot, and must not be used for configuration. this one is NOT a vibe, take it seriously bestie ๐Ÿšจ
  2. No New Privileges Flag https://docs.kernel.org/userspace-api/no_new_privs.html
  3. Known Environment Variables https://systemd.io/ENVIRONMENT

and that's a wrap on the whole page, bestie ๐ŸŽ€โœจ you read all seven parts, you're literally the main character of manpage literacy ๐Ÿ‘‘ this was systemd 262.1's SYSTEMD-SYSTEM.CONF(5), and it ate. periodt ๐Ÿ’…๐Ÿฆ‹

๐Ÿ“ฆ where this page comes from
  • arch rolling: systemd 262.1-1 ยท LGPL-2.1-or-later AND CC0-1.0 AND GPL-2.0-or-later AND MIT-0
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms