]> Git — Sourcephile - sourcephile-nix.git/blob - nixos/modules/services/logging/logrotate.nix
logrotate: rotate /var/log/{b,w}tmp and nginx
[sourcephile-nix.git] / nixos / modules / services / logging / logrotate.nix
1 { config, lib, pkgs, ... }:
2
3 with lib;
4
5 let
6 cfg = config.services.logrotate;
7
8 pathOpts = {
9 options = {
10 enable = mkOption {
11 type = types.bool;
12 default = true;
13 description = ''
14 Whether to enable log rotation for this path. This can be used to explicitly disable
15 logging that has been configured by NixOS.
16 '';
17 };
18
19 path = mkOption {
20 type = with types; either str (listOf str);
21 description = ''
22 The path to log files to be rotated.
23 '';
24 };
25
26 user = mkOption {
27 type = with types; nullOr str;
28 default = null;
29 description = ''
30 The user account to use for rotation.
31 '';
32 };
33
34 group = mkOption {
35 type = with types; nullOr str;
36 default = null;
37 description = ''
38 The group to use for rotation.
39 '';
40 };
41
42 frequency = mkOption {
43 type = types.enum [ "hourly" "daily" "weekly" "monthly" "yearly" ];
44 default = "daily";
45 description = ''
46 How often to rotate the logs.
47 '';
48 };
49
50 keep = mkOption {
51 type = types.int;
52 default = 20;
53 description = ''
54 How many rotations to keep.
55 '';
56 };
57
58 extraConfig = mkOption {
59 type = types.lines;
60 default = "";
61 description = ''
62 Extra logrotate config options for this path. Refer to
63 <link xlink:href="https://linux.die.net/man/8/logrotate"/> for details.
64 '';
65 };
66
67 priority = mkOption {
68 type = types.int;
69 default = 1000;
70 description = ''
71 Order of this logrotate block in relation to the others. The semantics are
72 the same as with `lib.mkOrder`. Smaller values have a greater priority.
73 '';
74 };
75 };
76
77 config.extraConfig = ''
78 missingok
79 notifempty
80 '';
81 };
82
83 mkConf = pathOpts: ''
84 # generated by NixOS using the `services.logrotate.paths.${pathOpts.name}` attribute set
85 ${concatMapString " " (path: ''"${path}"'') (if isList pathOpts.path then pathOpts.path else [pathOpts.path]} {
86 ${optionalString (pathOpts.user != null || pathOpts.group != null) "su ${pathOpts.user} ${pathOpts.group}"}
87 ${pathOpts.frequency}
88 rotate ${toString pathOpts.keep}
89 ${pathOpts.extraConfig}
90 }
91 '';
92
93 paths = sortProperties (mapAttrsToList (name: pathOpts: pathOpts // { name = name; }) (filterAttrs (_: pathOpts: pathOpts.enable) cfg.paths));
94 configFile = pkgs.writeText "logrotate.conf" (concatStringsSep "\n" ((map mkConf paths) ++ [ cfg.extraConfig ]));
95
96 in
97 {
98 imports = [
99 (mkRenamedOptionModule [ "services" "logrotate" "config" ] [ "services" "logrotate" "extraConfig" ])
100 ];
101
102 options = {
103 services.logrotate = {
104 enable = mkEnableOption "the logrotate systemd service";
105
106 paths = mkOption {
107 type = with types; attrsOf (submodule pathOpts);
108 default = {};
109 description = ''
110 Attribute set of paths to rotate. The order each block appears in the generated configuration file
111 can be controlled by the <link linkend="opt-services.logrotate.paths._name_.priority">priority</link> option
112 using the same semantics as `lib.mkOrder`. Smaller values have a greater priority.
113 '';
114 example = literalExpression ''
115 {
116 httpd = {
117 path = "/var/log/httpd/*.log";
118 user = config.services.httpd.user;
119 group = config.services.httpd.group;
120 keep = 7;
121 };
122
123 myapp = {
124 path = "/var/log/myapp/*.log";
125 user = "myuser";
126 group = "mygroup";
127 frequency = "weekly";
128 keep = 5;
129 priority = 1;
130 };
131 }
132 '';
133 };
134
135 extraConfig = mkOption {
136 default = "";
137 type = types.lines;
138 description = ''
139 Extra contents to append to the logrotate configuration file. Refer to
140 <link xlink:href="https://linux.die.net/man/8/logrotate"/> for details.
141 '';
142 };
143 };
144 };
145
146 config = mkIf cfg.enable {
147 assertions = mapAttrsToList (name: pathOpts:
148 { assertion = (pathOpts.user != null) == (pathOpts.group != null);
149 message = ''
150 If either of `services.logrotate.paths.${name}.user` or `services.logrotate.paths.${name}.group` are specified then *both* must be specified.
151 '';
152 }
153 ) cfg.paths;
154
155 systemd.services.logrotate = {
156 description = "Logrotate Service";
157 wantedBy = [ "multi-user.target" ];
158 startAt = "hourly";
159 script = ''
160 exec ${pkgs.logrotate}/sbin/logrotate ${configFile}
161 '';
162
163 serviceConfig = {
164 Restart = "no";
165 User = "root";
166 };
167 };
168 };
169 }