grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / logging / logcheck.nix
blobd937a523c8661aca09994ac792586adcaff77fc2
1 { config, lib, pkgs, ... }:
2 let
3   cfg = config.services.logcheck;
5   defaultRules = pkgs.runCommand "logcheck-default-rules" { preferLocalBuild = true; } ''
6                    cp -prd ${pkgs.logcheck}/etc/logcheck $out
7                    chmod u+w $out
8                    rm -r $out/logcheck.*
9                  '';
11   rulesDir = pkgs.symlinkJoin
12     { name = "logcheck-rules-dir";
13       paths = ([ defaultRules ] ++ cfg.extraRulesDirs);
14     };
16   configFile = pkgs.writeText "logcheck.conf" cfg.config;
18   logFiles = pkgs.writeText "logcheck.logfiles" cfg.files;
20   flags = "-r ${rulesDir} -c ${configFile} -L ${logFiles} -${levelFlag} -m ${cfg.mailTo}";
22   levelFlag = lib.getAttrFromPath [cfg.level]
23     { paranoid    = "p";
24       server      = "s";
25       workstation = "w";
26     };
28   cronJob = ''
29     @reboot   logcheck env PATH=/run/wrappers/bin:$PATH nice -n10 ${pkgs.logcheck}/sbin/logcheck -R ${flags}
30     2 ${cfg.timeOfDay} * * * logcheck env PATH=/run/wrappers/bin:$PATH nice -n10 ${pkgs.logcheck}/sbin/logcheck ${flags}
31   '';
33   writeIgnoreRule = name: {level, regex, ...}:
34     pkgs.writeTextFile
35       { inherit name;
36         destination = "/ignore.d.${level}/${name}";
37         text = ''
38           ^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ ${regex}
39         '';
40       };
42   writeIgnoreCronRule = name: {level, user, regex, cmdline, ...}:
43     let escapeRegex = lib.escape (lib.stringToCharacters "\\[]{}()^$?*+|.");
44         cmdline_ = builtins.unsafeDiscardStringContext cmdline;
45         re = if regex != "" then regex else if cmdline_ == "" then ".*" else escapeRegex cmdline_;
46     in writeIgnoreRule "cron-${name}" {
47       inherit level;
48       regex = ''
49         (/usr/bin/)?cron\[[0-9]+\]: \(${user}\) CMD \(${re}\)$
50       '';
51     };
53   levelOption = lib.mkOption {
54     default = "server";
55     type = lib.types.enum [ "workstation" "server" "paranoid" ];
56     description = ''
57       Set the logcheck level.
58     '';
59   };
61   ignoreOptions = {
62     options = {
63       level = levelOption;
65       regex = lib.mkOption {
66         default = "";
67         type = lib.types.str;
68         description = ''
69           Regex specifying which log lines to ignore.
70         '';
71       };
72     };
73   };
75   ignoreCronOptions = {
76     options = {
77       user = lib.mkOption {
78         default = "root";
79         type = lib.types.str;
80         description = ''
81           User that runs the cronjob.
82         '';
83       };
85       cmdline = lib.mkOption {
86         default = "";
87         type = lib.types.str;
88         description = ''
89           Command line for the cron job. Will be turned into a regex for the logcheck ignore rule.
90         '';
91       };
93       timeArgs = lib.mkOption {
94         default = null;
95         type = lib.types.nullOr (lib.types.str);
96         example = "02 06 * * *";
97         description = ''
98           "min hr dom mon dow" crontab time args, to auto-create a cronjob too.
99           Leave at null to not do this and just add a logcheck ignore rule.
100         '';
101       };
102     };
103   };
107   options = {
108     services.logcheck = {
109       enable = lib.mkEnableOption "logcheck cron job, to mail anomalies in the system logfiles to the administrator";
111       user = lib.mkOption {
112         default = "logcheck";
113         type = lib.types.str;
114         description = ''
115           Username for the logcheck user.
116         '';
117       };
119       timeOfDay = lib.mkOption {
120         default = "*";
121         example = "6";
122         type = lib.types.str;
123         description = ''
124           Time of day to run logcheck. A logcheck will be scheduled at xx:02 each day.
125           Leave default (*) to run every hour. Of course when nothing special was logged,
126           logcheck will be silent.
127         '';
128       };
130       mailTo = lib.mkOption {
131         default = "root";
132         example = "you@domain.com";
133         type = lib.types.str;
134         description = ''
135           Email address to send reports to.
136         '';
137       };
139       level = lib.mkOption {
140         default = "server";
141         type = lib.types.str;
142         description = ''
143           Set the logcheck level. Either "workstation", "server", or "paranoid".
144         '';
145       };
147       config = lib.mkOption {
148         default = "FQDN=1";
149         type = lib.types.lines;
150         description = ''
151           Config options that you would like in logcheck.conf.
152         '';
153       };
155       files = lib.mkOption {
156         default = [ "/var/log/messages" ];
157         type = lib.types.listOf lib.types.path;
158         example = [ "/var/log/messages" "/var/log/mail" ];
159         description = ''
160           Which log files to check.
161         '';
162       };
164       extraRulesDirs = lib.mkOption {
165         default = [];
166         example = [ "/etc/logcheck" ];
167         type = lib.types.listOf lib.types.path;
168         description = ''
169           Directories with extra rules.
170         '';
171       };
173       ignore = lib.mkOption {
174         default = {};
175         description = ''
176           This option defines extra ignore rules.
177         '';
178         type = with lib.types; attrsOf (submodule ignoreOptions);
179       };
181       ignoreCron = lib.mkOption {
182         default = {};
183         description = ''
184           This option defines extra ignore rules for cronjobs.
185         '';
186         type = with lib.types; attrsOf (submodule ignoreCronOptions);
187       };
189       extraGroups = lib.mkOption {
190         default = [];
191         type = lib.types.listOf lib.types.str;
192         example = [ "postdrop" "mongodb" ];
193         description = ''
194           Extra groups for the logcheck user, for example to be able to use sendmail,
195           or to access certain log files.
196         '';
197       };
199     };
200   };
202   config = lib.mkIf cfg.enable {
203     services.logcheck.extraRulesDirs =
204         lib.mapAttrsToList writeIgnoreRule cfg.ignore
205         ++ lib.mapAttrsToList writeIgnoreCronRule cfg.ignoreCron;
207     users.users = lib.optionalAttrs (cfg.user == "logcheck") {
208       logcheck = {
209         group = "logcheck";
210         isSystemUser = true;
211         shell = "/bin/sh";
212         description = "Logcheck user account";
213         extraGroups = cfg.extraGroups;
214       };
215     };
216     users.groups = lib.optionalAttrs (cfg.user == "logcheck") {
217       logcheck = {};
218     };
220     systemd.tmpfiles.settings.logcheck = {
221       "/var/lib/logcheck".d = {
222         mode = "700";
223         inherit (cfg) user;
224       };
225       "/var/lock/logcheck".d = {
226         mode = "700";
227         inherit (cfg) user;
228       };
229     };
231     services.cron.systemCronJobs =
232         let withTime = name: {timeArgs, ...}: timeArgs != null;
233             mkCron = name: {user, cmdline, timeArgs, ...}: ''
234               ${timeArgs} ${user} ${cmdline}
235             '';
236         in lib.mapAttrsToList mkCron (lib.filterAttrs withTime cfg.ignoreCron)
237            ++ [ cronJob ];
238   };