239 lines
6.6 KiB
Nix
239 lines
6.6 KiB
Nix
{ config, lib, pkgs, ... }:
|
|
let
|
|
cfg = config.services.logcheck;
|
|
|
|
defaultRules = pkgs.runCommand "logcheck-default-rules" { preferLocalBuild = true; } ''
|
|
cp -prd ${pkgs.logcheck}/etc/logcheck $out
|
|
chmod u+w $out
|
|
rm -r $out/logcheck.*
|
|
'';
|
|
|
|
rulesDir = pkgs.symlinkJoin
|
|
{ name = "logcheck-rules-dir";
|
|
paths = ([ defaultRules ] ++ cfg.extraRulesDirs);
|
|
};
|
|
|
|
configFile = pkgs.writeText "logcheck.conf" cfg.config;
|
|
|
|
logFiles = pkgs.writeText "logcheck.logfiles" cfg.files;
|
|
|
|
flags = "-r ${rulesDir} -c ${configFile} -L ${logFiles} -${levelFlag} -m ${cfg.mailTo}";
|
|
|
|
levelFlag = lib.getAttrFromPath [cfg.level]
|
|
{ paranoid = "p";
|
|
server = "s";
|
|
workstation = "w";
|
|
};
|
|
|
|
cronJob = ''
|
|
@reboot logcheck env PATH=/run/wrappers/bin:$PATH nice -n10 ${pkgs.logcheck}/sbin/logcheck -R ${flags}
|
|
2 ${cfg.timeOfDay} * * * logcheck env PATH=/run/wrappers/bin:$PATH nice -n10 ${pkgs.logcheck}/sbin/logcheck ${flags}
|
|
'';
|
|
|
|
writeIgnoreRule = name: {level, regex, ...}:
|
|
pkgs.writeTextFile
|
|
{ inherit name;
|
|
destination = "/ignore.d.${level}/${name}";
|
|
text = ''
|
|
^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ ${regex}
|
|
'';
|
|
};
|
|
|
|
writeIgnoreCronRule = name: {level, user, regex, cmdline, ...}:
|
|
let escapeRegex = lib.escape (lib.stringToCharacters "\\[]{}()^$?*+|.");
|
|
cmdline_ = builtins.unsafeDiscardStringContext cmdline;
|
|
re = if regex != "" then regex else if cmdline_ == "" then ".*" else escapeRegex cmdline_;
|
|
in writeIgnoreRule "cron-${name}" {
|
|
inherit level;
|
|
regex = ''
|
|
(/usr/bin/)?cron\[[0-9]+\]: \(${user}\) CMD \(${re}\)$
|
|
'';
|
|
};
|
|
|
|
levelOption = lib.mkOption {
|
|
default = "server";
|
|
type = lib.types.enum [ "workstation" "server" "paranoid" ];
|
|
description = ''
|
|
Set the logcheck level.
|
|
'';
|
|
};
|
|
|
|
ignoreOptions = {
|
|
options = {
|
|
level = levelOption;
|
|
|
|
regex = lib.mkOption {
|
|
default = "";
|
|
type = lib.types.str;
|
|
description = ''
|
|
Regex specifying which log lines to ignore.
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
|
|
ignoreCronOptions = {
|
|
options = {
|
|
user = lib.mkOption {
|
|
default = "root";
|
|
type = lib.types.str;
|
|
description = ''
|
|
User that runs the cronjob.
|
|
'';
|
|
};
|
|
|
|
cmdline = lib.mkOption {
|
|
default = "";
|
|
type = lib.types.str;
|
|
description = ''
|
|
Command line for the cron job. Will be turned into a regex for the logcheck ignore rule.
|
|
'';
|
|
};
|
|
|
|
timeArgs = lib.mkOption {
|
|
default = null;
|
|
type = lib.types.nullOr (lib.types.str);
|
|
example = "02 06 * * *";
|
|
description = ''
|
|
"min hr dom mon dow" crontab time args, to auto-create a cronjob too.
|
|
Leave at null to not do this and just add a logcheck ignore rule.
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
|
|
in
|
|
{
|
|
options = {
|
|
services.logcheck = {
|
|
enable = lib.mkEnableOption "logcheck cron job, to mail anomalies in the system logfiles to the administrator";
|
|
|
|
user = lib.mkOption {
|
|
default = "logcheck";
|
|
type = lib.types.str;
|
|
description = ''
|
|
Username for the logcheck user.
|
|
'';
|
|
};
|
|
|
|
timeOfDay = lib.mkOption {
|
|
default = "*";
|
|
example = "6";
|
|
type = lib.types.str;
|
|
description = ''
|
|
Time of day to run logcheck. A logcheck will be scheduled at xx:02 each day.
|
|
Leave default (*) to run every hour. Of course when nothing special was logged,
|
|
logcheck will be silent.
|
|
'';
|
|
};
|
|
|
|
mailTo = lib.mkOption {
|
|
default = "root";
|
|
example = "you@domain.com";
|
|
type = lib.types.str;
|
|
description = ''
|
|
Email address to send reports to.
|
|
'';
|
|
};
|
|
|
|
level = lib.mkOption {
|
|
default = "server";
|
|
type = lib.types.str;
|
|
description = ''
|
|
Set the logcheck level. Either "workstation", "server", or "paranoid".
|
|
'';
|
|
};
|
|
|
|
config = lib.mkOption {
|
|
default = "FQDN=1";
|
|
type = lib.types.lines;
|
|
description = ''
|
|
Config options that you would like in logcheck.conf.
|
|
'';
|
|
};
|
|
|
|
files = lib.mkOption {
|
|
default = [ "/var/log/messages" ];
|
|
type = lib.types.listOf lib.types.path;
|
|
example = [ "/var/log/messages" "/var/log/mail" ];
|
|
description = ''
|
|
Which log files to check.
|
|
'';
|
|
};
|
|
|
|
extraRulesDirs = lib.mkOption {
|
|
default = [];
|
|
example = [ "/etc/logcheck" ];
|
|
type = lib.types.listOf lib.types.path;
|
|
description = ''
|
|
Directories with extra rules.
|
|
'';
|
|
};
|
|
|
|
ignore = lib.mkOption {
|
|
default = {};
|
|
description = ''
|
|
This option defines extra ignore rules.
|
|
'';
|
|
type = with lib.types; attrsOf (submodule ignoreOptions);
|
|
};
|
|
|
|
ignoreCron = lib.mkOption {
|
|
default = {};
|
|
description = ''
|
|
This option defines extra ignore rules for cronjobs.
|
|
'';
|
|
type = with lib.types; attrsOf (submodule ignoreCronOptions);
|
|
};
|
|
|
|
extraGroups = lib.mkOption {
|
|
default = [];
|
|
type = lib.types.listOf lib.types.str;
|
|
example = [ "postdrop" "mongodb" ];
|
|
description = ''
|
|
Extra groups for the logcheck user, for example to be able to use sendmail,
|
|
or to access certain log files.
|
|
'';
|
|
};
|
|
|
|
};
|
|
};
|
|
|
|
config = lib.mkIf cfg.enable {
|
|
services.logcheck.extraRulesDirs =
|
|
lib.mapAttrsToList writeIgnoreRule cfg.ignore
|
|
++ lib.mapAttrsToList writeIgnoreCronRule cfg.ignoreCron;
|
|
|
|
users.users = lib.optionalAttrs (cfg.user == "logcheck") {
|
|
logcheck = {
|
|
group = "logcheck";
|
|
isSystemUser = true;
|
|
shell = "/bin/sh";
|
|
description = "Logcheck user account";
|
|
extraGroups = cfg.extraGroups;
|
|
};
|
|
};
|
|
users.groups = lib.optionalAttrs (cfg.user == "logcheck") {
|
|
logcheck = {};
|
|
};
|
|
|
|
systemd.tmpfiles.settings.logcheck = {
|
|
"/var/lib/logcheck".d = {
|
|
mode = "700";
|
|
inherit (cfg) user;
|
|
};
|
|
"/var/lock/logcheck".d = {
|
|
mode = "700";
|
|
inherit (cfg) user;
|
|
};
|
|
};
|
|
|
|
services.cron.systemCronJobs =
|
|
let withTime = name: {timeArgs, ...}: timeArgs != null;
|
|
mkCron = name: {user, cmdline, timeArgs, ...}: ''
|
|
${timeArgs} ${user} ${cmdline}
|
|
'';
|
|
in lib.mapAttrsToList mkCron (lib.filterAttrs withTime cfg.ignoreCron)
|
|
++ [ cronJob ];
|
|
};
|
|
}
|