1 { config, lib, pkgs, ... }:
3 cfg = config.services.logcheck;
5 defaultRules = pkgs.runCommand "logcheck-default-rules" { preferLocalBuild = true; } ''
6 cp -prd ${pkgs.logcheck}/etc/logcheck $out
11 rulesDir = pkgs.symlinkJoin
12 { name = "logcheck-rules-dir";
13 paths = ([ defaultRules ] ++ cfg.extraRulesDirs);
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]
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}
33 writeIgnoreRule = name: {level, regex, ...}:
36 destination = "/ignore.d.${level}/${name}";
38 ^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ ${regex}
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}" {
49 (/usr/bin/)?cron\[[0-9]+\]: \(${user}\) CMD \(${re}\)$
53 levelOption = lib.mkOption {
55 type = lib.types.enum [ "workstation" "server" "paranoid" ];
57 Set the logcheck level.
65 regex = lib.mkOption {
69 Regex specifying which log lines to ignore.
81 User that runs the cronjob.
85 cmdline = lib.mkOption {
89 Command line for the cron job. Will be turned into a regex for the logcheck ignore rule.
93 timeArgs = lib.mkOption {
95 type = lib.types.nullOr (lib.types.str);
96 example = "02 06 * * *";
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.
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;
115 Username for the logcheck user.
119 timeOfDay = lib.mkOption {
122 type = lib.types.str;
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.
130 mailTo = lib.mkOption {
132 example = "you@domain.com";
133 type = lib.types.str;
135 Email address to send reports to.
139 level = lib.mkOption {
141 type = lib.types.str;
143 Set the logcheck level. Either "workstation", "server", or "paranoid".
147 config = lib.mkOption {
149 type = lib.types.lines;
151 Config options that you would like in logcheck.conf.
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" ];
160 Which log files to check.
164 extraRulesDirs = lib.mkOption {
166 example = [ "/etc/logcheck" ];
167 type = lib.types.listOf lib.types.path;
169 Directories with extra rules.
173 ignore = lib.mkOption {
176 This option defines extra ignore rules.
178 type = with lib.types; attrsOf (submodule ignoreOptions);
181 ignoreCron = lib.mkOption {
184 This option defines extra ignore rules for cronjobs.
186 type = with lib.types; attrsOf (submodule ignoreCronOptions);
189 extraGroups = lib.mkOption {
191 type = lib.types.listOf lib.types.str;
192 example = [ "postdrop" "mongodb" ];
194 Extra groups for the logcheck user, for example to be able to use sendmail,
195 or to access certain log files.
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") {
212 description = "Logcheck user account";
213 extraGroups = cfg.extraGroups;
216 users.groups = lib.optionalAttrs (cfg.user == "logcheck") {
220 systemd.tmpfiles.settings.logcheck = {
221 "/var/lib/logcheck".d = {
225 "/var/lock/logcheck".d = {
231 services.cron.systemCronJobs =
232 let withTime = name: {timeArgs, ...}: timeArgs != null;
233 mkCron = name: {user, cmdline, timeArgs, ...}: ''
234 ${timeArgs} ${user} ${cmdline}
236 in lib.mapAttrsToList mkCron (lib.filterAttrs withTime cfg.ignoreCron)