1 { config, lib, pkgs, ... }:
6 cfg = config.services.logcheck;
8 defaultRules = pkgs.runCommand "logcheck-default-rules" { preferLocalBuild = true; } ''
9 cp -prd ${pkgs.logcheck}/etc/logcheck $out
14 rulesDir = pkgs.symlinkJoin
15 { name = "logcheck-rules-dir";
16 paths = ([ defaultRules ] ++ cfg.extraRulesDirs);
19 configFile = pkgs.writeText "logcheck.conf" cfg.config;
21 logFiles = pkgs.writeText "logcheck.logfiles" cfg.files;
23 flags = "-r ${rulesDir} -c ${configFile} -L ${logFiles} -${levelFlag} -m ${cfg.mailTo}";
25 levelFlag = getAttrFromPath [cfg.level]
32 @reboot logcheck env PATH=/run/wrappers/bin:$PATH nice -n10 ${pkgs.logcheck}/sbin/logcheck -R ${flags}
33 2 ${cfg.timeOfDay} * * * logcheck env PATH=/run/wrappers/bin:$PATH nice -n10 ${pkgs.logcheck}/sbin/logcheck ${flags}
36 writeIgnoreRule = name: {level, regex, ...}:
39 destination = "/ignore.d.${level}/${name}";
41 ^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ ${regex}
45 writeIgnoreCronRule = name: {level, user, regex, cmdline, ...}:
46 let escapeRegex = escape (stringToCharacters "\\[]{}()^$?*+|.");
47 cmdline_ = builtins.unsafeDiscardStringContext cmdline;
48 re = if regex != "" then regex else if cmdline_ == "" then ".*" else escapeRegex cmdline_;
49 in writeIgnoreRule "cron-${name}" {
52 (/usr/bin/)?cron\[[0-9]+\]: \(${user}\) CMD \(${re}\)$
56 levelOption = mkOption {
58 type = types.enum [ "workstation" "server" "paranoid" ];
59 description = lib.mdDoc ''
60 Set the logcheck level.
71 description = lib.mdDoc ''
72 Regex specifying which log lines to ignore.
83 description = lib.mdDoc ''
84 User that runs the cronjob.
91 description = lib.mdDoc ''
92 Command line for the cron job. Will be turned into a regex for the logcheck ignore rule.
98 type = types.nullOr (types.str);
99 example = "02 06 * * *";
100 description = lib.mdDoc ''
101 "min hr dom mon dow" crontab time args, to auto-create a cronjob too.
102 Leave at null to not do this and just add a logcheck ignore rule.
111 services.logcheck = {
112 enable = mkEnableOption (lib.mdDoc "logcheck cron job");
115 default = "logcheck";
117 description = lib.mdDoc ''
118 Username for the logcheck user.
122 timeOfDay = mkOption {
126 description = lib.mdDoc ''
127 Time of day to run logcheck. A logcheck will be scheduled at xx:02 each day.
128 Leave default (*) to run every hour. Of course when nothing special was logged,
129 logcheck will be silent.
135 example = "you@domain.com";
137 description = lib.mdDoc ''
138 Email address to send reports to.
145 description = lib.mdDoc ''
146 Set the logcheck level. Either "workstation", "server", or "paranoid".
153 description = lib.mdDoc ''
154 Config options that you would like in logcheck.conf.
159 default = [ "/var/log/messages" ];
160 type = types.listOf types.path;
161 example = [ "/var/log/messages" "/var/log/mail" ];
162 description = lib.mdDoc ''
163 Which log files to check.
167 extraRulesDirs = mkOption {
169 example = [ "/etc/logcheck" ];
170 type = types.listOf types.path;
171 description = lib.mdDoc ''
172 Directories with extra rules.
178 description = lib.mdDoc ''
179 This option defines extra ignore rules.
181 type = with types; attrsOf (submodule ignoreOptions);
184 ignoreCron = mkOption {
186 description = lib.mdDoc ''
187 This option defines extra ignore rules for cronjobs.
189 type = with types; attrsOf (submodule ignoreCronOptions);
192 extraGroups = mkOption {
194 type = types.listOf types.str;
195 example = [ "postdrop" "mongodb" ];
196 description = lib.mdDoc ''
197 Extra groups for the logcheck user, for example to be able to use sendmail,
198 or to access certain log files.
205 config = mkIf cfg.enable {
206 services.logcheck.extraRulesDirs =
207 mapAttrsToList writeIgnoreRule cfg.ignore
208 ++ mapAttrsToList writeIgnoreCronRule cfg.ignoreCron;
210 users.users = optionalAttrs (cfg.user == "logcheck") {
215 description = "Logcheck user account";
216 extraGroups = cfg.extraGroups;
219 users.groups = optionalAttrs (cfg.user == "logcheck") {
223 system.activationScripts.logcheck = ''
224 mkdir -m 700 -p /var/{lib,lock}/logcheck
225 chown ${cfg.user} /var/{lib,lock}/logcheck
228 services.cron.systemCronJobs =
229 let withTime = name: {timeArgs, ...}: timeArgs != null;
230 mkCron = name: {user, cmdline, timeArgs, ...}: ''
231 ${timeArgs} ${user} ${cmdline}
233 in mapAttrsToList mkCron (filterAttrs withTime cfg.ignoreCron)