nixpkgs/nixos/modules/system/boot/systemd.nix
2022-03-17 23:15:49 +01:00

812 lines
27 KiB
Nix
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{ config, lib, pkgs, utils, ... }:
with utils;
with systemdUtils.unitOptions;
with lib;
let
cfg = config.systemd;
systemd = cfg.package;
inherit (systemdUtils.lib)
makeUnit
generateUnits
makeJobScript
unitConfig
serviceConfig
mountConfig
automountConfig
commonUnitText
targetToUnit
serviceToUnit
socketToUnit
timerToUnit
pathToUnit
mountToUnit
automountToUnit
sliceToUnit;
upstreamSystemUnits =
[ # Targets.
"basic.target"
"sysinit.target"
"sockets.target"
"exit.target"
"graphical.target"
"multi-user.target"
"network.target"
"network-pre.target"
"network-online.target"
"nss-lookup.target"
"nss-user-lookup.target"
"time-sync.target"
] ++ (optionals cfg.package.withCryptsetup [
"cryptsetup.target"
"cryptsetup-pre.target"
"remote-cryptsetup.target"
]) ++ [
"sigpwr.target"
"timers.target"
"paths.target"
"rpcbind.target"
# Rescue mode.
"rescue.target"
"rescue.service"
# Udev.
"systemd-udevd-control.socket"
"systemd-udevd-kernel.socket"
"systemd-udevd.service"
"systemd-udev-settle.service"
] ++ (optional (!config.boot.isContainer) "systemd-udev-trigger.service") ++ [
# hwdb.bin is managed by NixOS
# "systemd-hwdb-update.service"
# Consoles.
"getty.target"
"getty-pre.target"
"getty@.service"
"serial-getty@.service"
"console-getty.service"
"container-getty@.service"
"systemd-vconsole-setup.service"
# Hardware (started by udev when a relevant device is plugged in).
"sound.target"
"bluetooth.target"
"printer.target"
"smartcard.target"
# Kernel module loading.
"systemd-modules-load.service"
"kmod-static-nodes.service"
"modprobe@.service"
# Filesystems.
"systemd-fsck@.service"
"systemd-fsck-root.service"
"systemd-remount-fs.service"
"systemd-pstore.service"
"local-fs.target"
"local-fs-pre.target"
"remote-fs.target"
"remote-fs-pre.target"
"swap.target"
"dev-hugepages.mount"
"dev-mqueue.mount"
"sys-fs-fuse-connections.mount"
] ++ (optional (!config.boot.isContainer) "sys-kernel-config.mount") ++ [
"sys-kernel-debug.mount"
# Maintaining state across reboots.
"systemd-random-seed.service"
"systemd-backlight@.service"
"systemd-rfkill.service"
"systemd-rfkill.socket"
# Hibernate / suspend.
"hibernate.target"
"suspend.target"
"suspend-then-hibernate.target"
"sleep.target"
"hybrid-sleep.target"
"systemd-hibernate.service"
"systemd-hybrid-sleep.service"
"systemd-suspend.service"
"systemd-suspend-then-hibernate.service"
# Reboot stuff.
"reboot.target"
"systemd-reboot.service"
"poweroff.target"
"systemd-poweroff.service"
"halt.target"
"systemd-halt.service"
"shutdown.target"
"umount.target"
"final.target"
"kexec.target"
"systemd-kexec.service"
"systemd-update-utmp.service"
# Password entry.
"systemd-ask-password-console.path"
"systemd-ask-password-console.service"
"systemd-ask-password-wall.path"
"systemd-ask-password-wall.service"
# Slices / containers.
"slices.target"
"user.slice"
"machine.slice"
"machines.target"
"systemd-importd.service"
"systemd-machined.service"
"systemd-nspawn@.service"
# Temporary file creation / cleanup.
"systemd-tmpfiles-clean.service"
"systemd-tmpfiles-clean.timer"
"systemd-tmpfiles-setup.service"
"systemd-tmpfiles-setup-dev.service"
# Misc.
"systemd-sysctl.service"
"dbus-org.freedesktop.timedate1.service"
"dbus-org.freedesktop.locale1.service"
"dbus-org.freedesktop.hostname1.service"
"systemd-timedated.service"
"systemd-localed.service"
"systemd-hostnamed.service"
"systemd-exit.service"
"systemd-update-done.service"
] ++ cfg.additionalUpstreamSystemUnits;
upstreamSystemWants =
[ "sysinit.target.wants"
"sockets.target.wants"
"local-fs.target.wants"
"multi-user.target.wants"
"timers.target.wants"
];
upstreamUserUnits = [
"app.slice"
"background.slice"
"basic.target"
"bluetooth.target"
"default.target"
"exit.target"
"graphical-session-pre.target"
"graphical-session.target"
"paths.target"
"printer.target"
"session.slice"
"shutdown.target"
"smartcard.target"
"sockets.target"
"sound.target"
"systemd-exit.service"
"systemd-tmpfiles-clean.service"
"systemd-tmpfiles-clean.timer"
"systemd-tmpfiles-setup.service"
"timers.target"
"xdg-desktop-autostart.target"
];
proxy_env = config.networking.proxy.envVars;
in
{
###### interface
options = {
systemd.package = mkOption {
default = pkgs.systemd;
defaultText = literalExpression "pkgs.systemd";
type = types.package;
description = "The systemd package.";
};
systemd.units = mkOption {
description = "Definition of systemd units.";
default = {};
type = with types; attrsOf (submodule (
{ name, config, ... }:
{ options = concreteUnitOptions;
config = {
unit = mkDefault (makeUnit name config);
};
}));
};
systemd.packages = mkOption {
default = [];
type = types.listOf types.package;
example = literalExpression "[ pkgs.systemd-cryptsetup-generator ]";
description = "Packages providing systemd units and hooks.";
};
systemd.targets = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = targetOptions; } unitConfig] );
description = "Definition of systemd target units.";
};
systemd.services = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = serviceOptions; } unitConfig serviceConfig ]);
description = "Definition of systemd service units.";
};
systemd.sockets = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = socketOptions; } unitConfig ]);
description = "Definition of systemd socket units.";
};
systemd.timers = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = timerOptions; } unitConfig ]);
description = "Definition of systemd timer units.";
};
systemd.paths = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = pathOptions; } unitConfig ]);
description = "Definition of systemd path units.";
};
systemd.mounts = mkOption {
default = [];
type = with types; listOf (submodule [ { options = mountOptions; } unitConfig mountConfig ]);
description = ''
Definition of systemd mount units.
This is a list instead of an attrSet, because systemd mandates the names to be derived from
the 'where' attribute.
'';
};
systemd.automounts = mkOption {
default = [];
type = with types; listOf (submodule [ { options = automountOptions; } unitConfig automountConfig ]);
description = ''
Definition of systemd automount units.
This is a list instead of an attrSet, because systemd mandates the names to be derived from
the 'where' attribute.
'';
};
systemd.slices = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = sliceOptions; } unitConfig] );
description = "Definition of slice configurations.";
};
systemd.generators = mkOption {
type = types.attrsOf types.path;
default = {};
example = { systemd-gpt-auto-generator = "/dev/null"; };
description = ''
Definition of systemd generators.
For each <literal>NAME = VALUE</literal> pair of the attrSet, a link is generated from
<literal>/etc/systemd/system-generators/NAME</literal> to <literal>VALUE</literal>.
'';
};
systemd.shutdown = mkOption {
type = types.attrsOf types.path;
default = {};
description = ''
Definition of systemd shutdown executables.
For each <literal>NAME = VALUE</literal> pair of the attrSet, a link is generated from
<literal>/etc/systemd/system-shutdown/NAME</literal> to <literal>VALUE</literal>.
'';
};
systemd.defaultUnit = mkOption {
default = "multi-user.target";
type = types.str;
description = "Default unit started when the system boots.";
};
systemd.ctrlAltDelUnit = mkOption {
default = "reboot.target";
type = types.str;
example = "poweroff.target";
description = ''
Target that should be started when Ctrl-Alt-Delete is pressed.
'';
};
systemd.globalEnvironment = mkOption {
type = with types; attrsOf (nullOr (oneOf [ str path package ]));
default = {};
example = { TZ = "CET"; };
description = ''
Environment variables passed to <emphasis>all</emphasis> systemd units.
'';
};
systemd.enableCgroupAccounting = mkOption {
default = true;
type = types.bool;
description = ''
Whether to enable cgroup accounting.
'';
};
systemd.enableUnifiedCgroupHierarchy = mkOption {
default = true;
type = types.bool;
description = ''
Whether to enable the unified cgroup hierarchy (cgroupsv2).
'';
};
systemd.extraConfig = mkOption {
default = "";
type = types.lines;
example = "DefaultLimitCORE=infinity";
description = ''
Extra config options for systemd. See man systemd-system.conf for
available options.
'';
};
systemd.sleep.extraConfig = mkOption {
default = "";
type = types.lines;
example = "HibernateDelaySec=1h";
description = ''
Extra config options for systemd sleep state logic.
See sleep.conf.d(5) man page for available options.
'';
};
systemd.user.extraConfig = mkOption {
default = "";
type = types.lines;
example = "DefaultCPUAccounting=yes";
description = ''
Extra config options for systemd user instances. See man systemd-user.conf for
available options.
'';
};
systemd.tmpfiles.rules = mkOption {
type = types.listOf types.str;
default = [];
example = [ "d /tmp 1777 root root 10d" ];
description = ''
Rules for creation, deletion and cleaning of volatile and temporary files
automatically. See
<citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for the exact format.
'';
};
systemd.tmpfiles.packages = mkOption {
type = types.listOf types.package;
default = [];
example = literalExpression "[ pkgs.lvm2 ]";
apply = map getLib;
description = ''
List of packages containing <command>systemd-tmpfiles</command> rules.
All files ending in .conf found in
<filename><replaceable>pkg</replaceable>/lib/tmpfiles.d</filename>
will be included.
If this folder does not exist or does not contain any files an error will be returned instead.
If a <filename>lib</filename> output is available, rules are searched there and only there.
If there is no <filename>lib</filename> output it will fall back to <filename>out</filename>
and if that does not exist either, the default output will be used.
'';
};
systemd.user.units = mkOption {
description = "Definition of systemd per-user units.";
default = {};
type = with types; attrsOf (submodule (
{ name, config, ... }:
{ options = concreteUnitOptions;
config = {
unit = mkDefault (makeUnit name config);
};
}));
};
systemd.user.paths = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = pathOptions; } unitConfig ]);
description = "Definition of systemd per-user path units.";
};
systemd.user.services = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = serviceOptions; } unitConfig serviceConfig ] );
description = "Definition of systemd per-user service units.";
};
systemd.user.slices = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = sliceOptions; } unitConfig ] );
description = "Definition of systemd per-user slice units.";
};
systemd.user.sockets = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = socketOptions; } unitConfig ] );
description = "Definition of systemd per-user socket units.";
};
systemd.user.targets = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = targetOptions; } unitConfig] );
description = "Definition of systemd per-user target units.";
};
systemd.user.timers = mkOption {
default = {};
type = with types; attrsOf (submodule [ { options = timerOptions; } unitConfig ] );
description = "Definition of systemd per-user timer units.";
};
systemd.additionalUpstreamSystemUnits = mkOption {
default = [ ];
type = types.listOf types.str;
example = [ "debug-shell.service" "systemd-quotacheck.service" ];
description = ''
Additional units shipped with systemd that shall be enabled.
'';
};
systemd.suppressedSystemUnits = mkOption {
default = [ ];
type = types.listOf types.str;
example = [ "systemd-backlight@.service" ];
description = ''
A list of units to suppress when generating system systemd configuration directory. This has
priority over upstream units, <option>systemd.units</option>, and
<option>systemd.additionalUpstreamSystemUnits</option>. The main purpose of this is to
suppress a upstream systemd unit with any modifications made to it by other NixOS modules.
'';
};
systemd.watchdog.device = mkOption {
type = types.nullOr types.path;
default = null;
example = "/dev/watchdog";
description = ''
The path to a hardware watchdog device which will be managed by systemd.
If not specified, systemd will default to /dev/watchdog.
'';
};
systemd.watchdog.runtimeTime = mkOption {
type = types.nullOr types.str;
default = null;
example = "30s";
description = ''
The amount of time which can elapse before a watchdog hardware device
will automatically reboot the system. Valid time units include "ms",
"s", "min", "h", "d", and "w".
'';
};
systemd.watchdog.rebootTime = mkOption {
type = types.nullOr types.str;
default = null;
example = "10m";
description = ''
The amount of time which can elapse after a reboot has been triggered
before a watchdog hardware device will automatically reboot the system.
Valid time units include "ms", "s", "min", "h", "d", and "w".
'';
};
systemd.watchdog.kexecTime = mkOption {
type = types.nullOr types.str;
default = null;
example = "10m";
description = ''
The amount of time which can elapse when kexec is being executed before
a watchdog hardware device will automatically reboot the system. This
option should only be enabled if reloadTime is also enabled. Valid
time units include "ms", "s", "min", "h", "d", and "w".
'';
};
};
###### implementation
config = {
warnings = concatLists (
mapAttrsToList
(name: service:
let
type = service.serviceConfig.Type or "";
restart = service.serviceConfig.Restart or "no";
hasDeprecated = builtins.hasAttr "StartLimitInterval" service.serviceConfig;
in
concatLists [
(optional (type == "oneshot" && (restart == "always" || restart == "on-success"))
"Service '${name}.service' with 'Type=oneshot' cannot have 'Restart=always' or 'Restart=on-success'"
)
(optional hasDeprecated
"Service '${name}.service' uses the attribute 'StartLimitInterval' in the Service section, which is deprecated. See https://github.com/NixOS/nixpkgs/issues/45786."
)
(optional (service.reloadIfChanged && service.reloadTriggers != [])
"Service '${name}.service' has both 'reloadIfChanged' and 'reloadTriggers' set. This is probably not what you want, because 'reloadTriggers' behave the same whay as 'restartTriggers' if 'reloadIfChanged' is set."
)
]
)
cfg.services
);
system.build.units = cfg.units;
system.nssModules = [ systemd.out ];
system.nssDatabases = {
hosts = (mkMerge [
(mkOrder 400 ["mymachines"]) # 400 to ensure it comes before resolve (which is mkBefore'd)
(mkOrder 999 ["myhostname"]) # after files (which is 998), but before regular nss modules
]);
passwd = (mkMerge [
(mkAfter [ "systemd" ])
]);
group = (mkMerge [
(mkAfter [ "systemd" ])
]);
};
environment.systemPackages = [ systemd ];
environment.etc = let
# generate contents for /etc/systemd/system-${type} from attrset of links and packages
hooks = type: links: pkgs.runCommand "system-${type}" {
preferLocalBuild = true;
packages = cfg.packages;
} ''
set -e
mkdir -p $out
for package in $packages
do
for hook in $package/lib/systemd/system-${type}/*
do
ln -s $hook $out/
done
done
${concatStrings (mapAttrsToList (exec: target: "ln -s ${target} $out/${exec};\n") links)}
'';
enabledUpstreamSystemUnits = filter (n: ! elem n cfg.suppressedSystemUnits) upstreamSystemUnits;
enabledUnits = filterAttrs (n: v: ! elem n cfg.suppressedSystemUnits) cfg.units;
in ({
"systemd/system".source = generateUnits "system" enabledUnits enabledUpstreamSystemUnits upstreamSystemWants;
"systemd/user".source = generateUnits "user" cfg.user.units upstreamUserUnits [];
"systemd/system.conf".text = ''
[Manager]
${optionalString config.systemd.enableCgroupAccounting ''
DefaultCPUAccounting=yes
DefaultIOAccounting=yes
DefaultBlockIOAccounting=yes
DefaultIPAccounting=yes
''}
DefaultLimitCORE=infinity
${optionalString (config.systemd.watchdog.device != null) ''
WatchdogDevice=${config.systemd.watchdog.device}
''}
${optionalString (config.systemd.watchdog.runtimeTime != null) ''
RuntimeWatchdogSec=${config.systemd.watchdog.runtimeTime}
''}
${optionalString (config.systemd.watchdog.rebootTime != null) ''
RebootWatchdogSec=${config.systemd.watchdog.rebootTime}
''}
${optionalString (config.systemd.watchdog.kexecTime != null) ''
KExecWatchdogSec=${config.systemd.watchdog.kexecTime}
''}
${config.systemd.extraConfig}
'';
"systemd/user.conf".text = ''
[Manager]
${config.systemd.user.extraConfig}
'';
"systemd/sleep.conf".text = ''
[Sleep]
${config.systemd.sleep.extraConfig}
'';
"tmpfiles.d".source = (pkgs.symlinkJoin {
name = "tmpfiles.d";
paths = map (p: p + "/lib/tmpfiles.d") cfg.tmpfiles.packages;
postBuild = ''
for i in $(cat $pathsPath); do
(test -d "$i" && test $(ls "$i"/*.conf | wc -l) -ge 1) || (
echo "ERROR: The path '$i' from systemd.tmpfiles.packages contains no *.conf files."
exit 1
)
done
'' + concatMapStrings (name: optionalString (hasPrefix "tmpfiles.d/" name) ''
rm -f $out/${removePrefix "tmpfiles.d/" name}
'') config.system.build.etc.passthru.targets;
}) + "/*";
"systemd/system-generators" = { source = hooks "generators" cfg.generators; };
"systemd/system-shutdown" = { source = hooks "shutdown" cfg.shutdown; };
});
services.dbus.enable = true;
users.users.systemd-network = {
uid = config.ids.uids.systemd-network;
group = "systemd-network";
};
users.groups.systemd-network.gid = config.ids.gids.systemd-network;
users.users.systemd-resolve = {
uid = config.ids.uids.systemd-resolve;
group = "systemd-resolve";
};
users.groups.systemd-resolve.gid = config.ids.gids.systemd-resolve;
# Target for charon send-keys to hook into.
users.groups.keys.gid = config.ids.gids.keys;
systemd.targets.keys =
{ description = "Security Keys";
unitConfig.X-StopOnReconfiguration = true;
};
systemd.tmpfiles.packages = [
# Default tmpfiles rules provided by systemd
(pkgs.runCommand "systemd-default-tmpfiles" {} ''
mkdir -p $out/lib/tmpfiles.d
cd $out/lib/tmpfiles.d
ln -s "${systemd}/example/tmpfiles.d/home.conf"
ln -s "${systemd}/example/tmpfiles.d/journal-nocow.conf"
ln -s "${systemd}/example/tmpfiles.d/static-nodes-permissions.conf"
ln -s "${systemd}/example/tmpfiles.d/systemd.conf"
ln -s "${systemd}/example/tmpfiles.d/systemd-nologin.conf"
ln -s "${systemd}/example/tmpfiles.d/systemd-nspawn.conf"
ln -s "${systemd}/example/tmpfiles.d/systemd-tmp.conf"
ln -s "${systemd}/example/tmpfiles.d/tmp.conf"
ln -s "${systemd}/example/tmpfiles.d/var.conf"
ln -s "${systemd}/example/tmpfiles.d/x11.conf"
'')
# User-specified tmpfiles rules
(pkgs.writeTextFile {
name = "nixos-tmpfiles.d";
destination = "/lib/tmpfiles.d/00-nixos.conf";
text = ''
# This file is created automatically and should not be modified.
# Please change the option systemd.tmpfiles.rules instead.
${concatStringsSep "\n" cfg.tmpfiles.rules}
'';
})
];
systemd.units =
mapAttrs' (n: v: nameValuePair "${n}.path" (pathToUnit n v)) cfg.paths
// mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit n v)) cfg.services
// mapAttrs' (n: v: nameValuePair "${n}.slice" (sliceToUnit n v)) cfg.slices
// mapAttrs' (n: v: nameValuePair "${n}.socket" (socketToUnit n v)) cfg.sockets
// mapAttrs' (n: v: nameValuePair "${n}.target" (targetToUnit n v)) cfg.targets
// mapAttrs' (n: v: nameValuePair "${n}.timer" (timerToUnit n v)) cfg.timers
// listToAttrs (map
(v: let n = escapeSystemdPath v.where;
in nameValuePair "${n}.mount" (mountToUnit n v)) cfg.mounts)
// listToAttrs (map
(v: let n = escapeSystemdPath v.where;
in nameValuePair "${n}.automount" (automountToUnit n v)) cfg.automounts);
systemd.user.units =
mapAttrs' (n: v: nameValuePair "${n}.path" (pathToUnit n v)) cfg.user.paths
// mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit n v)) cfg.user.services
// mapAttrs' (n: v: nameValuePair "${n}.slice" (sliceToUnit n v)) cfg.user.slices
// mapAttrs' (n: v: nameValuePair "${n}.socket" (socketToUnit n v)) cfg.user.sockets
// mapAttrs' (n: v: nameValuePair "${n}.target" (targetToUnit n v)) cfg.user.targets
// mapAttrs' (n: v: nameValuePair "${n}.timer" (timerToUnit n v)) cfg.user.timers;
system.requiredKernelConfig = map config.lib.kernelConfig.isEnabled
[ "DEVTMPFS" "CGROUPS" "INOTIFY_USER" "SIGNALFD" "TIMERFD" "EPOLL" "NET"
"SYSFS" "PROC_FS" "FHANDLE" "CRYPTO_USER_API_HASH" "CRYPTO_HMAC"
"CRYPTO_SHA256" "DMIID" "AUTOFS4_FS" "TMPFS_POSIX_ACL"
"TMPFS_XATTR" "SECCOMP"
];
# Generate timer units for all services that have a startAt value.
systemd.timers =
mapAttrs (name: service:
{ wantedBy = [ "timers.target" ];
timerConfig.OnCalendar = service.startAt;
})
(filterAttrs (name: service: service.enable && service.startAt != []) cfg.services);
# Generate timer units for all services that have a startAt value.
systemd.user.timers =
mapAttrs (name: service:
{ wantedBy = [ "timers.target" ];
timerConfig.OnCalendar = service.startAt;
})
(filterAttrs (name: service: service.startAt != []) cfg.user.services);
# Provide the systemd-user PAM service, required to run systemd
# user instances.
security.pam.services.systemd-user =
{ # Ensure that pam_systemd gets included. This is special-cased
# in systemd to provide XDG_RUNTIME_DIR.
startSession = true;
};
# Some overrides to upstream units.
systemd.services."systemd-backlight@".restartIfChanged = false;
systemd.services."systemd-fsck@".restartIfChanged = false;
systemd.services."systemd-fsck@".path = [ config.system.path ];
systemd.services."user@".restartIfChanged = false;
systemd.services.systemd-random-seed.restartIfChanged = false;
systemd.services.systemd-remount-fs.restartIfChanged = false;
systemd.services.systemd-update-utmp.restartIfChanged = false;
systemd.services.systemd-user-sessions.restartIfChanged = false; # Restart kills all active sessions.
systemd.services.systemd-udev-settle.restartIfChanged = false; # Causes long delays in nixos-rebuild
systemd.targets.local-fs.unitConfig.X-StopOnReconfiguration = true;
systemd.targets.remote-fs.unitConfig.X-StopOnReconfiguration = true;
systemd.targets.network-online.wantedBy = [ "multi-user.target" ];
systemd.services.systemd-importd.environment = proxy_env;
systemd.services.systemd-pstore.wantedBy = [ "sysinit.target" ]; # see #81138
# Don't bother with certain units in containers.
systemd.services.systemd-remount-fs.unitConfig.ConditionVirtualization = "!container";
systemd.services.systemd-random-seed.unitConfig.ConditionVirtualization = "!container";
# Increase numeric PID range (set directly instead of copying a one-line file from systemd)
# https://github.com/systemd/systemd/pull/12226
boot.kernel.sysctl."kernel.pid_max" = mkIf pkgs.stdenv.is64bit (lib.mkDefault 4194304);
boot.kernelParams = optional (!cfg.enableUnifiedCgroupHierarchy) "systemd.unified_cgroup_hierarchy=0";
services.logrotate.paths = {
"/var/log/btmp" = mapAttrs (_: mkDefault) {
frequency = "monthly";
keep = 1;
extraConfig = ''
create 0660 root ${config.users.groups.utmp.name}
minsize 1M
'';
};
"/var/log/wtmp" = mapAttrs (_: mkDefault) {
frequency = "monthly";
keep = 1;
extraConfig = ''
create 0664 root ${config.users.groups.utmp.name}
minsize 1M
'';
};
};
};
# FIXME: Remove these eventually.
imports =
[ (mkRenamedOptionModule [ "boot" "systemd" "sockets" ] [ "systemd" "sockets" ])
(mkRenamedOptionModule [ "boot" "systemd" "targets" ] [ "systemd" "targets" ])
(mkRenamedOptionModule [ "boot" "systemd" "services" ] [ "systemd" "services" ])
(mkRenamedOptionModule [ "jobs" ] [ "systemd" "services" ])
(mkRemovedOptionModule [ "systemd" "generator-packages" ] "Use systemd.packages instead.")
];
}