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:
/etc/systemd//run/systemd//usr/local/lib/systemd/[1]/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. peepsystemd(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=โ takesname,description, orcombinedas the value. ifname, the system manager uses unit names in status messages (e.g."systemd-journald.service") instead of the longer, more informative descriptions set withDescription=(e.g."Journal Logging Service"). ifcombined, 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 theAccuracySec=setting of timer units, seesystemd.timer(5)for details. anAccuracySec=set in an individual unit overrides the global default for that specific unit. defaults to1min.
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 theTimerSlackNSec=setting in service units (deets insystemd.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 theCPUAffinity=setting in unit files, seesystemd.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 theNUMAPolicy=setting in unit files, seesystemd.exec(5). ๐
Added in version 243.
NUMAMask=โ configures the NUMA node mask that gets associated with the selected NUMA policy. Lowkey important: thedefaultandlocalNUMA policies don't need an explicit NUMA node mask, so the value of this option can be empty. And just likeNUMAPolicy=, individual services can override the value in unit files, seesystemd.exec(5). โจ
Added in version 243.
DefaultMemoryAccounting=,DefaultTasksAccounting=,DefaultIOAccounting=,DefaultIPAccounting=โ these set the default resource accounting settings, matching what's configured per-unit byMemoryAccounting=,TasksAccounting=,IOAccounting=, andIPAccounting=. All the per-unit details live insystemd.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-unitTasksMax=setting. Seesystemd.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 ofkernel.pid_max=,kernel.threads-max=and root cgrouppids.max. The kernel has a default value forkernel.pid_max=and an algorithm for counting when there are more than 32 cores. For example, with the defaultkernel.pid_max=,DefaultTasksMax=defaults to4915, 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 matchingLimitXXX=directives, and they accept the same parameter syntax โ seesystemd.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 to1024:524288.DefaultLimitMEMLOCK=defaults to8M.DefaultLimitCORE=does not have a default, but it's worth mentioning thatRLIMIT_COREis 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 orsystemd-oomd. Use this to pick a global default for the per-unitOOMPolicy=setting. Seesystemd.service(5)for details. Lowkey a gotcha: this default is not used for services that haveDelegate=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-unitOOMScoreAdjust=setting, seesystemd.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-unitMemoryPressureWatch=andMemoryPressureThresholdSec=settings. Seesystemd.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-unitCPUPressureWatch=andCPUPressureThresholdSec=settings. Seesystemd.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-unitIOPressureWatch=andIOPressureThresholdSec=settings. Seesystemd.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 waycap_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 throughexecve(2)โ so no setuid or setgid bits, no filesystem capabilities, none of it. Defaults tofalse.
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 theSystemCallArchitectures=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 ifSmackProcessLabel=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 forRestrictSUIDSGID=. 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 settingsTimeoutStartSec=,TimeoutStopSec=,TimeoutAbortSec=andRestartSec=do (for services, see systemd.service(5) for all the per-unit details). For non-service units,DefaultTimeoutStartSec=sets the defaultTimeoutSec=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 thex-systemd.device-timeout=option in/etc/fstaband/etc/crypttab(see systemd.mount(5), crypttab(5)). Defaults to90 sin the system manager and90 sin the user manager.
Added in version 252.
DefaultStartLimitIntervalSec=,DefaultStartLimitBurst=โ configure the default unit start rate limiting, as configured per-service byStartLimitIntervalSec=andStartLimitBurst=. See systemd.service(5) for details on the per-service settings.DefaultStartLimitIntervalSec=defaults to10s.DefaultStartLimitBurst=defaults to5.
Added in version 209.
ReloadLimitIntervalSec=,ReloadLimitBurst=โ rate limiting fordaemon-reloadand (since v256)daemon-reexecrequests. 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, andReloadLimitBurst=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 thanEventLoopRateLimitBurst=times withinEventLoopRateLimitIntervalSec=, event processing is briefly paused to prevent excessive CPU usage.EventLoopRateLimitIntervalSec=defaults to1s.EventLoopRateLimitBurst=defaults to50000. These settings can also be set on the kernel command line viasystemd.event_loop_ratelimit_interval_sec=andsystemd.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 to15s. 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 atenviron(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 asDefaultEnvironment=, 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 totrueif you don't specify anything. this acts as the default for units that don't have an explicit definition forMemoryZSwapWriteback=. seesystemd.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 asx86,x86-64orarm64. See the architectures defined forConditionArchitecture=insystemd.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 theIMAGE_VERSION=field of/etc/os-release. If not set, resolves to an empty string. Seeos-release(5)for more information. โจ"%b"โ Boot ID โ The boot ID of the running system, formatted as string. Seerandom(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 theBUILD_ID=field of/etc/os-release. If not set, resolves to an empty string. Seeos-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. Seemachine-id(5)for more information."%M"โ Operating system image identifier โ The operating system image identifier of the running system, as read from theIMAGE_ID=field of/etc/os-release. If not set, resolves to an empty string. Seeos-release(5)for more information."%o"โ Operating system ID โ The operating system identifier of the running system, as read from theID=field of/etc/os-release. Seeos-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 touname -routput. fr fr, literally the same thing ๐"%w"โ Operating system version ID โ The operating system version identifier of the running system, as read from theVERSION_ID=field of/etc/os-release. If not set, resolves to an empty string. Seeos-release(5)for more information."%W"โ Operating system variant ID โ The operating system variant identifier of the running system, as read from theVARIANT_ID=field of/etc/os-release. If not set, resolves to an empty string. Seeos-release(5)for more information."%T"โ Directory for temporary files โ This is either/tmpor 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/tmpor 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 ๐
- ๐ฃ๐ฅ๐งจ๐ฅ๐ฅ๐ฃ 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 ๐จ - No New Privileges Flag
https://docs.kernel.org/userspace-api/no_new_privs.html - 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