diff options
-rw-r--r-- | nixos/doc/manual/from_md/release-notes/rl-2205.section.xml | 17 | ||||
-rw-r--r-- | nixos/doc/manual/release-notes/rl-2205.section.md | 5 | ||||
-rw-r--r-- | nixos/modules/services/logging/logrotate.nix | 192 | ||||
-rw-r--r-- | nixos/modules/services/misc/gitlab.nix | 16 | ||||
-rw-r--r-- | nixos/modules/services/networking/lxd-image-server.nix | 18 | ||||
-rw-r--r-- | nixos/modules/services/web-servers/apache-httpd/default.nix | 21 | ||||
-rw-r--r-- | nixos/modules/services/web-servers/nginx/default.nix | 16 | ||||
-rw-r--r-- | nixos/modules/system/boot/systemd.nix | 18 | ||||
-rw-r--r-- | nixos/modules/virtualisation/azure-agent.nix | 14 | ||||
-rw-r--r-- | nixos/tests/logrotate.nix | 80 |
10 files changed, 297 insertions, 100 deletions
diff --git a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml index 99af050d7ba..9535d441740 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml @@ -1655,9 +1655,20 @@ </listitem> <listitem> <para> - <literal>services.logrotate.enable</literal> now defaults to - true if any rotate path has been defined, and some paths have - been added by default. + <link linkend="opt-services.logrotate.enable">services.logrotate.enable</link> + now defaults to true if any rotate path has been defined, and + some paths have been added by default. + </para> + </listitem> + <listitem> + <para> + The logrotate module also has been updated to freeform syntax: + <link linkend="opt-services.logrotate.paths">services.logrotate.paths</link> + and + <link linkend="opt-services.logrotate.extraConfig">services.logrotate.extraConfig</link> + will work, but issue deprecation warnings and + <link linkend="opt-services.logrotate.settings">services.logrotate.settings</link> + should now be used instead. </para> </listitem> <listitem> diff --git a/nixos/doc/manual/release-notes/rl-2205.section.md b/nixos/doc/manual/release-notes/rl-2205.section.md index 3e883625664..377dd1b5cae 100644 --- a/nixos/doc/manual/release-notes/rl-2205.section.md +++ b/nixos/doc/manual/release-notes/rl-2205.section.md @@ -578,8 +578,11 @@ In addition to numerous new and upgraded packages, this release has the followin - `services.mattermost.plugins` has been added to allow the declarative installation of Mattermost plugins. Plugins are automatically repackaged using autoPatchelf. -- `services.logrotate.enable` now defaults to true if any rotate path has +- [services.logrotate.enable](#opt-services.logrotate.enable) now defaults to true if any rotate path has been defined, and some paths have been added by default. +- The logrotate module also has been updated to freeform syntax: [services.logrotate.paths](#opt-services.logrotate.paths) + and [services.logrotate.extraConfig](#opt-services.logrotate.extraConfig) will work, but issue deprecation + warnings and [services.logrotate.settings](#opt-services.logrotate.settings) should now be used instead. - The `zrepl` package has been updated from 0.4.0 to 0.5: diff --git a/nixos/modules/services/logging/logrotate.nix b/nixos/modules/services/logging/logrotate.nix index d16a5a571ba..6a9ed469fd3 100644 --- a/nixos/modules/services/logging/logrotate.nix +++ b/nixos/modules/services/logging/logrotate.nix @@ -5,6 +5,9 @@ with lib; let cfg = config.services.logrotate; + # deprecated legacy compat settings + # these options will be removed before 22.11 in the following PR: + # https://github.com/NixOS/nixpkgs/pull/164169 pathOpts = { name, ... }: { options = { enable = mkOption { @@ -86,27 +89,77 @@ let config.name = name; }; - mkConf = pathOpts: '' - # generated by NixOS using the `services.logrotate.paths.${pathOpts.name}` attribute set - ${concatMapStringsSep " " (path: ''"${path}"'') (toList pathOpts.path)} { - ${optionalString (pathOpts.user != null || pathOpts.group != null) "su ${pathOpts.user} ${pathOpts.group}"} - ${pathOpts.frequency} - rotate ${toString pathOpts.keep} - ${pathOpts.extraConfig} - } - ''; - - paths = sortProperties (attrValues (filterAttrs (_: pathOpts: pathOpts.enable) cfg.paths)); - configText = concatStringsSep "\n" ( - [ "missingok" "notifempty" cfg.extraConfig ] ++ (map mkConf paths) + generateLine = n: v: + if builtins.elem n [ "files" "priority" "enable" "global" ] || v == null then null + else if builtins.elem n [ "extraConfig" "frequency" ] then "${v}\n" + else if builtins.elem n [ "firstaction" "lastaction" "prerotate" "postrotate" "preremove" ] + then "${n}\n ${v}\n endscript\n" + else if isInt v then "${n} ${toString v}\n" + else if v == true then "${n}\n" + else if v == false then "no${n}\n" + else "${n} ${v}\n"; + generateSection = indent: settings: concatStringsSep (fixedWidthString indent " " "") ( + filter (x: x != null) (mapAttrsToList generateLine settings) + ); + + # generateSection includes a final newline hence weird closing brace + mkConf = settings: + if settings.global or false then generateSection 0 settings + else '' + ${concatMapStringsSep "\n" (files: ''"${files}"'') (toList settings.files)} { + ${generateSection 2 settings}} + ''; + + # below two mapPaths are compat functions + mapPathOptToSetting = n: v: + if n == "keep" then nameValuePair "rotate" v + else if n == "path" then nameValuePair "files" v + else nameValuePair n v; + + mapPathsToSettings = path: pathOpts: + nameValuePair path ( + filterAttrs (n: v: ! builtins.elem n [ "user" "group" "name" ] && v != "") ( + (mapAttrs' mapPathOptToSetting pathOpts) // + { + su = + if pathOpts.user != null + then "${pathOpts.user} ${pathOpts.group}" + else null; + } + ) + ); + + settings = sortProperties (attrValues (filterAttrs (_: settings: settings.enable) ( + foldAttrs recursiveUpdate { } [ + { + header = { + enable = true; + missingok = true; + notifempty = true; + frequency = "weekly"; + rotate = 4; + }; + # compat section + extraConfig = { + enable = (cfg.extraConfig != ""); + global = true; + extraConfig = cfg.extraConfig; + priority = 101; + }; + } + (mapAttrs' mapPathsToSettings cfg.paths) + cfg.settings + { header = { global = true; priority = 100; }; } + ] + ))); + configFile = pkgs.writeText "logrotate.conf" ( + concatStringsSep "\n" ( + map mkConf settings + ) ); - configFile = pkgs.writeText "logrotate.conf" configText; mailOption = - # add mail option to service if a mail is requested in config - # this ugly match will be replaced by cleaner attribute check in - # the near future - if builtins.match "(.*[[:space:]])?mail[[:space:]].*" configText != null + if foldr (n: a: a || n ? mail) false (attrValues cfg.settings) then "--mail=${pkgs.mailutils}/bin/mail" else ""; in @@ -118,8 +171,68 @@ in options = { services.logrotate = { enable = mkEnableOption "the logrotate systemd service" // { - default = foldr (n: a: a || n.enable) false (attrValues cfg.paths); - defaultText = literalExpression "cfg.paths != {}"; + default = foldr (n: a: a || n.enable) false (attrValues cfg.settings); + defaultText = literalExpression "cfg.settings != {}"; + }; + + settings = mkOption { + default = { }; + description = '' + logrotate freeform settings: each attribute here will define its own section, + ordered by priority, which can either define files to rotate with their settings + or settings common to all further files settings. + Refer to <link xlink:href="https://linux.die.net/man/8/logrotate"/> for details. + ''; + type = types.attrsOf (types.submodule ({ name, ... }: { + freeformType = with types; attrsOf (nullOr (oneOf [ int bool str ])); + + options = { + enable = mkEnableOption "setting individual kill switch" // { + default = true; + }; + + global = mkOption { + type = types.bool; + default = false; + description = '' + Whether this setting is a global option or not: set to have these + settings apply to all files settings with a higher priority. + ''; + }; + files = mkOption { + type = with types; either str (listOf str); + default = name; + defaultText = '' + The attrset name if not specified + ''; + description = '' + Single or list of files for which rules are defined. + The files are quoted with double-quotes in logrotate configuration, + so globs and spaces are supported. + Note this setting is ignored if globals is true. + ''; + }; + + frequency = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + How often to rotate the logs. Defaults to previously set global setting, + which itself defauts to weekly. + ''; + }; + + priority = mkOption { + type = types.int; + default = 1000; + description = '' + Order of this logrotate block in relation to the others. The semantics are + the same as with `lib.mkOrder`. Smaller values are inserted first. + ''; + }; + }; + + })); }; configFile = mkOption { @@ -130,7 +243,7 @@ in ''; description = '' Override the configuration file used by MySQL. By default, - NixOS generates one automatically from <option>services.logrotate.settings</option>. + NixOS generates one automatically from <xref linkend="opt-services.logrotate.settings"/>. ''; example = literalExpression '' pkgs.writeText "logrotate.conf" ''' @@ -143,6 +256,7 @@ in ''; }; + # deprecated legacy compat settings paths = mkOption { type = with types; attrsOf (submodule pathOpts); default = { }; @@ -150,6 +264,7 @@ in Attribute set of paths to rotate. The order each block appears in the generated configuration file can be controlled by the <link linkend="opt-services.logrotate.paths._name_.priority">priority</link> option using the same semantics as `lib.mkOrder`. Smaller values have a greater priority. + This setting has been deprecated in favor of <link linkend="opt-services.logrotate.settings">logrotate settings</link>. ''; example = literalExpression '' { @@ -178,22 +293,37 @@ in description = '' Extra contents to append to the logrotate configuration file. Refer to <link xlink:href="https://linux.die.net/man/8/logrotate"/> for details. + This setting has been deprecated in favor of + <link linkend="opt-services.logrotate.settings">logrotate settings</link>. ''; }; }; }; config = mkIf cfg.enable { - assertions = mapAttrsToList - (name: pathOpts: - { - assertion = (pathOpts.user != null) == (pathOpts.group != null); - message = '' - If either of `services.logrotate.paths.${name}.user` or `services.logrotate.paths.${name}.group` are specified then *both* must be specified. - ''; - } - ) - cfg.paths; + assertions = + mapAttrsToList + (name: pathOpts: + { + assertion = (pathOpts.user != null) == (pathOpts.group != null); + message = '' + If either of `services.logrotate.paths.${name}.user` or `services.logrotate.paths.${name}.group` are specified then *both* must be specified. + ''; + }) + cfg.paths; + + warnings = + (mapAttrsToList + (name: pathOpts: '' + Using config.services.logrotate.paths.${name} is deprecated and will become unsupported in a future release. + Please use services.logrotate.settings instead. + '') + cfg.paths + ) ++ + (optional (cfg.extraConfig != "") '' + Using config.services.logrotate.extraConfig is deprecated and will become unsupported in a future release. + Please use services.logrotate.settings with globals=true instead. + ''); systemd.services.logrotate = { description = "Logrotate Service"; diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix index e48444f7161..488c3be7b65 100644 --- a/nixos/modules/services/misc/gitlab.nix +++ b/nixos/modules/services/misc/gitlab.nix @@ -848,10 +848,7 @@ in { extraConfig = mkOption { type = types.lines; - default = '' - copytruncate - compress - ''; + default = ""; description = '' Extra logrotate config options for this path. Refer to <link xlink:href="https://linux.die.net/man/8/logrotate"/> for details. @@ -977,13 +974,14 @@ in { # Enable rotation of log files services.logrotate = { enable = cfg.logrotate.enable; - paths = { + settings = { gitlab = { - path = "${cfg.statePath}/log/*.log"; - user = cfg.user; - group = cfg.group; + files = "${cfg.statePath}/log/*.log"; + su = "${cfg.user} ${cfg.group}"; frequency = cfg.logrotate.frequency; - keep = cfg.logrotate.keep; + rotate = cfg.logrotate.keep; + copytruncate = true; + compress = true; extraConfig = cfg.logrotate.extraConfig; }; }; diff --git a/nixos/modules/services/networking/lxd-image-server.nix b/nixos/modules/services/networking/lxd-image-server.nix index b119ba8acf6..d326626eed4 100644 --- a/nixos/modules/services/networking/lxd-image-server.nix +++ b/nixos/modules/services/networking/lxd-image-server.nix @@ -51,18 +51,14 @@ in environment.etc."lxd-image-server/config.toml".source = format.generate "config.toml" cfg.settings; - services.logrotate.paths.lxd-image-server = { - path = "/var/log/lxd-image-server/lxd-image-server.log"; + services.logrotate.settings.lxd-image-server = { + files = "/var/log/lxd-image-server/lxd-image-server.log"; frequency = "daily"; - keep = 21; - extraConfig = '' - create 755 lxd-image-server ${cfg.group} - missingok - compress - delaycompress - copytruncate - notifempty - ''; + rotate = 21; + create = "755 lxd-image-server ${cfg.group}"; + compress = true; + delaycompress = true; + copytruncate = true; }; systemd.tmpfiles.rules = [ diff --git a/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixos/modules/services/web-servers/apache-httpd/default.nix index d817ff6019a..3099705acbe 100644 --- a/nixos/modules/services/web-servers/apache-httpd/default.nix +++ b/nixos/modules/services/web-servers/apache-httpd/default.nix @@ -710,20 +710,15 @@ in services.logrotate = optionalAttrs (cfg.logFormat != "none") { enable = mkDefault true; - paths.httpd = { - path = "${cfg.logDir}/*.log"; - user = cfg.user; - group = cfg.group; + settings.httpd = { + files = "${cfg.logDir}/*.log"; + su = "${cfg.user} ${cfg.group}"; frequency = "daily"; - keep = 28; - extraConfig = '' - sharedscripts - compress - delaycompress - postrotate - systemctl reload httpd.service > /dev/null 2>/dev/null || true - endscript - ''; + rotate = 28; + sharedscripts = true; + compress = true; + delaycompress = true; + postrotate = "systemctl reload httpd.service > /dev/null 2>/dev/null || true"; }; }; diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix index e046c28dd6b..1e18956c2dc 100644 --- a/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixos/modules/services/web-servers/nginx/default.nix @@ -989,17 +989,13 @@ in nginx.gid = config.ids.gids.nginx; }; - services.logrotate.paths.nginx = mapAttrs (_: mkDefault) { - path = "/var/log/nginx/*.log"; + services.logrotate.settings.nginx = mapAttrs (_: mkDefault) { + files = "/var/log/nginx/*.log"; frequency = "weekly"; - keep = 26; - extraConfig = '' - compress - delaycompress - postrotate - [ ! -f /var/run/nginx/nginx.pid ] || kill -USR1 `cat /var/run/nginx/nginx.pid` - endscript - ''; + rotate = 26; + compress = true; + delaycompress = true; + postrotate = "[ ! -f /var/run/nginx/nginx.pid ] || kill -USR1 `cat /var/run/nginx/nginx.pid`"; }; }; } diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index 297a80d4681..f69c5d3d5a6 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -612,22 +612,18 @@ in boot.kernelParams = optional (!cfg.enableUnifiedCgroupHierarchy) "systemd.unified_cgroup_hierarchy=0"; - services.logrotate.paths = { + services.logrotate.settings = { "/var/log/btmp" = mapAttrs (_: mkDefault) { frequency = "monthly"; - keep = 1; - extraConfig = '' - create 0660 root ${config.users.groups.utmp.name} - minsize 1M - ''; + rotate = 1; + 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 - ''; + rotate = 1; + create = "0664 root ${config.users.groups.utmp.name}"; + minsize = "1M"; }; }; }; diff --git a/nixos/modules/virtualisation/azure-agent.nix b/nixos/modules/virtualisation/azure-agent.nix index bd8c7f8c1ee..e2425b44eac 100644 --- a/nixos/modules/virtualisation/azure-agent.nix +++ b/nixos/modules/virtualisation/azure-agent.nix @@ -146,15 +146,11 @@ in services.logrotate = { enable = true; - extraConfig = '' - /var/log/waagent.log { - compress - monthly - rotate 6 - notifempty - missingok - } - ''; + settings."/var/log/waagent.log" = { + compress = true; + frequency = "monthly"; + rotate = 6; + }; }; systemd.targets.provisioned = { diff --git a/nixos/tests/logrotate.nix b/nixos/tests/logrotate.nix index 85923465593..3087119c339 100644 --- a/nixos/tests/logrotate.nix +++ b/nixos/tests/logrotate.nix @@ -1,5 +1,14 @@ # Test logrotate service works and is enabled by default +let + importTest = { ... }: { + services.logrotate.settings.import = { + olddir = false; + }; + }; + +in + import ./make-test-python.nix ({ pkgs, ... }: rec { name = "logrotate"; meta = with pkgs.lib.maintainers; { @@ -9,10 +18,59 @@ import ./make-test-python.nix ({ pkgs, ... }: rec { nodes = { defaultMachine = { ... }: { }; machine = { config, ... }: { - services.logrotate.paths = { + imports = [ importTest ]; + + services.logrotate.settings = { + # remove default frequency header and add another + header = { + frequency = null; + delaycompress = true; + }; + # extra global setting... affecting nothing + last_line = { + global = true; + priority = 2000; + shred = true; + }; # using mail somewhere should add --mail to logrotate invokation sendmail = { - extraConfig = "mail user@domain.tld"; + mail = "user@domain.tld"; + }; + # postrotate should be suffixed by 'endscript' + postrotate = { + postrotate = "touch /dev/null"; + }; + # multiple paths should be aggregated + multipath = { + files = [ "file1" "file2" ]; + }; + # overriding imported path should keep existing attributes + # (e.g. olddir is still set) + import = { + notifempty = true; + }; + }; + # extraConfig compatibility - should be added to top level, early. + services.logrotate.extraConfig = '' + nomail + ''; + # paths compatibility + services.logrotate.paths = { + compat_path = { + path = "compat_test_path"; + }; + # user/group should be grouped as 'su user group' + compat_user = { + user = config.users.users.root.name; + group = "root"; + }; + # extraConfig in path should be added to block + compat_extraConfig = { + extraConfig = "dateext"; + }; + # keep -> rotate + compat_keep = { + keep = 1; }; }; }; @@ -44,5 +102,23 @@ import ./make-test-python.nix ({ pkgs, ... }: rec { defaultMachine.fail("systemctl cat logrotate.service | grep -- --mail") with subtest("using mails adds mail option"): machine.succeed("systemctl cat logrotate.service | grep -- --mail") + with subtest("check generated config matches expectation"): + machine.succeed( + # copy conf to /tmp/logrotate.conf for easy grep + "conf=$(systemctl cat logrotate | grep -oE '/nix/store[^ ]*logrotate.conf'); cp $conf /tmp/logrotate.conf", + "! grep weekly /tmp/logrotate.conf", + "grep -E '^delaycompress' /tmp/logrotate.conf", + "tail -n 1 /tmp/logrotate.conf | grep shred", + "sed -ne '/\"sendmail\" {/,/}/p' /tmp/logrotate.conf | grep 'mail user@domain.tld'", + "sed -ne '/\"postrotate\" {/,/}/p' /tmp/logrotate.conf | grep endscript", + "grep '\"file1\"\n\"file2\" {' /tmp/logrotate.conf", + "sed -ne '/\"import\" {/,/}/p' /tmp/logrotate.conf | grep noolddir", + "sed -ne '1,/^\"/p' /tmp/logrotate.conf | grep nomail", + "grep '\"compat_test_path\" {' /tmp/logrotate.conf", + "sed -ne '/\"compat_user\" {/,/}/p' /tmp/logrotate.conf | grep 'su root root'", + "sed -ne '/\"compat_extraConfig\" {/,/}/p' /tmp/logrotate.conf | grep dateext", + "[[ $(sed -ne '/\"compat_keep\" {/,/}/p' /tmp/logrotate.conf | grep -w rotate) = \" rotate 1\" ]]", + "! sed -ne '/\"compat_keep\" {/,/}/p' /tmp/logrotate.conf | grep -w keep", + ) ''; }) |