at 17.09-beta 6.4 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.logcheck; 7 8 defaultRules = pkgs.runCommand "logcheck-default-rules" {} '' 9 cp -prd ${pkgs.logcheck}/etc/logcheck $out 10 chmod u+w $out 11 rm $out/logcheck.* 12 ''; 13 14 rulesDir = pkgs.symlinkJoin 15 { name = "logcheck-rules-dir"; 16 paths = ([ defaultRules ] ++ cfg.extraRulesDirs); 17 }; 18 19 configFile = pkgs.writeText "logcheck.conf" cfg.config; 20 21 logFiles = pkgs.writeText "logcheck.logfiles" cfg.files; 22 23 flags = "-r ${rulesDir} -c ${configFile} -L ${logFiles} -${levelFlag} -m ${cfg.mailTo}"; 24 25 levelFlag = getAttrFromPath [cfg.level] 26 { "paranoid" = "p"; 27 "server" = "s"; 28 "workstation" = "w"; 29 }; 30 31 cronJob = '' 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} 34 ''; 35 36 writeIgnoreRule = name: {level, regex, ...}: 37 pkgs.writeTextFile 38 { inherit name; 39 destination = "/ignore.d.${level}/${name}"; 40 text = '' 41 ^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ ${regex} 42 ''; 43 }; 44 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}" { 50 inherit level; 51 regex = '' 52 (/usr/bin/)?cron\[[0-9]+\]: \(${user}\) CMD \(${re}\)$ 53 ''; 54 }; 55 56 levelOption = mkOption { 57 default = "server"; 58 type = types.enum [ "workstation" "server" "paranoid" ]; 59 description = '' 60 Set the logcheck level. 61 ''; 62 }; 63 64 ignoreOptions = { 65 options = { 66 level = levelOption; 67 68 regex = mkOption { 69 default = ""; 70 type = types.str; 71 description = '' 72 Regex specifying which log lines to ignore. 73 ''; 74 }; 75 }; 76 }; 77 78 ignoreCronOptions = { 79 options = { 80 user = mkOption { 81 default = "root"; 82 type = types.str; 83 description = '' 84 User that runs the cronjob. 85 ''; 86 }; 87 88 cmdline = mkOption { 89 default = ""; 90 type = types.str; 91 description = '' 92 Command line for the cron job. Will be turned into a regex for the logcheck ignore rule. 93 ''; 94 }; 95 96 timeArgs = mkOption { 97 default = null; 98 type = types.nullOr (types.str); 99 example = "02 06 * * *"; 100 description = '' 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. 103 ''; 104 }; 105 }; 106 }; 107 108in 109{ 110 options = { 111 services.logcheck = { 112 enable = mkOption { 113 default = false; 114 type = types.bool; 115 description = '' 116 Enable the logcheck cron job. 117 ''; 118 }; 119 120 user = mkOption { 121 default = "logcheck"; 122 type = types.str; 123 description = '' 124 Username for the logcheck user. 125 ''; 126 }; 127 128 timeOfDay = mkOption { 129 default = "*"; 130 example = "6"; 131 type = types.str; 132 description = '' 133 Time of day to run logcheck. A logcheck will be scheduled at xx:02 each day. 134 Leave default (*) to run every hour. Of course when nothing special was logged, 135 logcheck will be silent. 136 ''; 137 }; 138 139 mailTo = mkOption { 140 default = "root"; 141 example = "you@domain.com"; 142 type = types.str; 143 description = '' 144 Email address to send reports to. 145 ''; 146 }; 147 148 level = mkOption { 149 default = "server"; 150 type = types.str; 151 description = '' 152 Set the logcheck level. Either "workstation", "server", or "paranoid". 153 ''; 154 }; 155 156 config = mkOption { 157 default = "FQDN=1"; 158 type = types.string; 159 description = '' 160 Config options that you would like in logcheck.conf. 161 ''; 162 }; 163 164 files = mkOption { 165 default = [ "/var/log/messages" ]; 166 type = types.listOf types.path; 167 example = [ "/var/log/messages" "/var/log/mail" ]; 168 description = '' 169 Which log files to check. 170 ''; 171 }; 172 173 extraRulesDirs = mkOption { 174 default = []; 175 example = "/etc/logcheck"; 176 type = types.listOf types.path; 177 description = '' 178 Directories with extra rules. 179 ''; 180 }; 181 182 ignore = mkOption { 183 default = {}; 184 description = '' 185 This option defines extra ignore rules. 186 ''; 187 type = with types; attrsOf (submodule ignoreOptions); 188 }; 189 190 ignoreCron = mkOption { 191 default = {}; 192 description = '' 193 This option defines extra ignore rules for cronjobs. 194 ''; 195 type = with types; attrsOf (submodule ignoreCronOptions); 196 }; 197 198 extraGroups = mkOption { 199 default = []; 200 type = types.listOf types.str; 201 example = [ "postdrop" "mongodb" ]; 202 description = '' 203 Extra groups for the logcheck user, for example to be able to use sendmail, 204 or to access certain log files. 205 ''; 206 }; 207 208 }; 209 }; 210 211 config = mkIf cfg.enable { 212 services.logcheck.extraRulesDirs = 213 mapAttrsToList writeIgnoreRule cfg.ignore 214 ++ mapAttrsToList writeIgnoreCronRule cfg.ignoreCron; 215 216 users.extraUsers = optionalAttrs (cfg.user == "logcheck") (singleton 217 { name = "logcheck"; 218 uid = config.ids.uids.logcheck; 219 shell = "/bin/sh"; 220 description = "Logcheck user account"; 221 extraGroups = cfg.extraGroups; 222 }); 223 224 system.activationScripts.logcheck = '' 225 mkdir -m 700 -p /var/{lib,lock}/logcheck 226 chown ${cfg.user} /var/{lib,lock}/logcheck 227 ''; 228 229 services.cron.systemCronJobs = 230 let withTime = name: {timeArgs, ...}: ! (builtins.isNull timeArgs); 231 mkCron = name: {user, cmdline, timeArgs, ...}: '' 232 ${timeArgs} ${user} ${cmdline} 233 ''; 234 in mapAttrsToList mkCron (filterAttrs withTime cfg.ignoreCron) 235 ++ [ cronJob ]; 236 }; 237}