Move all of NixOS to nixos/ in preparation of the repository merge
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
with pkgs.lib;
|
||||
|
||||
{
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
|
||||
services.klogd.enable = mkOption {
|
||||
type = types.bool;
|
||||
default = versionOlder (getVersion config.boot.kernelPackages.kernel) "3.5";
|
||||
description = ''
|
||||
Whether to enable klogd, the kernel log message processing
|
||||
daemon. Since systemd handles logging of kernel messages on
|
||||
Linux 3.5 and later, this is only useful if you're running an
|
||||
older kernel.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf config.services.klogd.enable {
|
||||
|
||||
jobs.klogd =
|
||||
{ description = "Kernel Log Daemon";
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
path = [ pkgs.sysklogd ];
|
||||
|
||||
exec =
|
||||
"klogd -c 1 -2 -n " +
|
||||
"-k $(dirname $(readlink -f /run/booted-system/kernel))/System.map";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
{config, pkgs, ...}:
|
||||
|
||||
with pkgs.lib;
|
||||
|
||||
let
|
||||
cfg = config.services.logcheck;
|
||||
|
||||
defaultRules = pkgs.runCommand "logcheck-default-rules" {} ''
|
||||
cp -prd ${pkgs.logcheck}/etc/logcheck $out
|
||||
chmod u+w $out
|
||||
rm $out/logcheck.*
|
||||
'';
|
||||
|
||||
rulesDir = pkgs.symlinkJoin "logcheck-rules-dir" ([ 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 = getAttrFromPath [cfg.level]
|
||||
{ "paranoid" = "p";
|
||||
"server" = "s";
|
||||
"workstation" = "w";
|
||||
};
|
||||
|
||||
cronJob = ''
|
||||
@reboot logcheck env PATH=/var/setuid-wrappers:$PATH nice -n10 ${pkgs.logcheck}/sbin/logcheck -R ${flags}
|
||||
2 ${cfg.timeOfDay} * * * logcheck env PATH=/var/setuid-wrappers:$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 = escape (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 = mkOption {
|
||||
default = "server";
|
||||
type = types.uniq types.string;
|
||||
description = ''
|
||||
Set the logcheck level. Either "workstation", "server", or "paranoid".
|
||||
'';
|
||||
};
|
||||
|
||||
ignoreOptions = {
|
||||
level = levelOption;
|
||||
|
||||
regex = mkOption {
|
||||
default = "";
|
||||
type = types.uniq types.string;
|
||||
description = ''
|
||||
Regex specifying which log lines to ignore.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
ignoreCronOptions = {
|
||||
user = mkOption {
|
||||
default = "root";
|
||||
type = types.uniq types.string;
|
||||
description = ''
|
||||
User that runs the cronjob.
|
||||
'';
|
||||
};
|
||||
|
||||
cmdline = mkOption {
|
||||
default = "";
|
||||
type = types.uniq types.string;
|
||||
description = ''
|
||||
Command line for the cron job. Will be turned into a regex for the logcheck ignore rule.
|
||||
'';
|
||||
};
|
||||
|
||||
timeArgs = mkOption {
|
||||
default = null;
|
||||
type = types.nullOr (types.uniq types.string);
|
||||
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 = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Enable the logcheck cron job.
|
||||
'';
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
default = "logcheck";
|
||||
type = types.uniq types.string;
|
||||
description = ''
|
||||
Username for the logcheck user.
|
||||
'';
|
||||
};
|
||||
|
||||
timeOfDay = mkOption {
|
||||
default = "*";
|
||||
example = "6";
|
||||
type = types.uniq types.string;
|
||||
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 = mkOption {
|
||||
default = "root";
|
||||
example = "you@domain.com";
|
||||
type = types.uniq types.string;
|
||||
description = ''
|
||||
Email address to send reports to.
|
||||
'';
|
||||
};
|
||||
|
||||
level = mkOption {
|
||||
default = "server";
|
||||
type = types.uniq types.string;
|
||||
description = ''
|
||||
Set the logcheck level. Either "workstation", "server", or "paranoid".
|
||||
'';
|
||||
};
|
||||
|
||||
config = mkOption {
|
||||
default = "FQDN=1";
|
||||
type = types.string;
|
||||
description = ''
|
||||
Config options that you would like in logcheck.conf.
|
||||
'';
|
||||
};
|
||||
|
||||
files = mkOption {
|
||||
default = [ "/var/log/messages" ];
|
||||
type = types.listOf types.path;
|
||||
example = [ "/var/log/messages" "/var/log/mail" ];
|
||||
description = ''
|
||||
Which log files to check.
|
||||
'';
|
||||
};
|
||||
|
||||
extraRulesDirs = mkOption {
|
||||
default = [];
|
||||
example = "/etc/logcheck";
|
||||
type = types.listOf types.path;
|
||||
description = ''
|
||||
Directories with extra rules.
|
||||
'';
|
||||
};
|
||||
|
||||
ignore = mkOption {
|
||||
default = {};
|
||||
description = ''
|
||||
This option defines extra ignore rules.
|
||||
'';
|
||||
type = types.loaOf types.optionSet;
|
||||
options = [ ignoreOptions ];
|
||||
};
|
||||
|
||||
ignoreCron = mkOption {
|
||||
default = {};
|
||||
description = ''
|
||||
This option defines extra ignore rules for cronjobs.
|
||||
'';
|
||||
type = types.loaOf types.optionSet;
|
||||
options = [ ignoreOptions ignoreCronOptions ];
|
||||
};
|
||||
|
||||
extraGroups = mkOption {
|
||||
default = [];
|
||||
type = types.listOf types.string;
|
||||
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 = mkIf cfg.enable {
|
||||
services.logcheck.extraRulesDirs =
|
||||
mapAttrsToList writeIgnoreRule cfg.ignore
|
||||
++ mapAttrsToList writeIgnoreCronRule cfg.ignoreCron;
|
||||
|
||||
users.extraUsers = singleton
|
||||
{ name = cfg.user;
|
||||
shell = "/bin/sh";
|
||||
description = "Logcheck user account";
|
||||
extraGroups = cfg.extraGroups;
|
||||
};
|
||||
|
||||
system.activationScripts.logcheck = ''
|
||||
mkdir -m 700 -p /var/{lib,lock}/logcheck
|
||||
chown ${cfg.user} /var/{lib,lock}/logcheck
|
||||
'';
|
||||
|
||||
services.cron.systemCronJobs =
|
||||
let withTime = name: {timeArgs, ...}: ! (builtins.isNull timeArgs);
|
||||
mkCron = name: {user, cmdline, timeArgs, ...}: ''
|
||||
${timeArgs} ${user} ${cmdline}
|
||||
'';
|
||||
in mapAttrsToList mkCron (filterAttrs withTime cfg.ignoreCron)
|
||||
++ [ cronJob ];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{config, pkgs, ...}:
|
||||
|
||||
with pkgs.lib;
|
||||
|
||||
let
|
||||
cfg = config.services.logrotate;
|
||||
|
||||
configFile = pkgs.writeText "logrotate.conf"
|
||||
cfg.config;
|
||||
|
||||
cronJob = ''
|
||||
5 * * * * root ${pkgs.logrotate}/sbin/logrotate ${configFile}
|
||||
'';
|
||||
|
||||
in
|
||||
{
|
||||
options = {
|
||||
services.logrotate = {
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
description = ''
|
||||
Enable the logrotate cron job
|
||||
'';
|
||||
};
|
||||
|
||||
config = mkOption {
|
||||
default = "";
|
||||
description = ''
|
||||
The contents of the logrotate config file
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.cron.systemCronJobs = [ cronJob ];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
with pkgs.lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.services.logstash;
|
||||
|
||||
listToConfig = list: "[ " + (concatStringsSep ", " (map exprToConfig list)) + " ]";
|
||||
|
||||
hashToConfig = attrs:
|
||||
let
|
||||
attrNameToConfigList = name:
|
||||
[ (exprToConfig name) (exprToConfig (getAttr name attrs)) ];
|
||||
in
|
||||
"[ " +
|
||||
(concatStringsSep ", " (map attrNameToConfigList (attrNames attrs))) +
|
||||
" ]";
|
||||
|
||||
valueToConfig = nvpair: let name = nvpair.name; value = nvpair.value; in
|
||||
if (isAttrs value) && ((!(value ? __type)) || value.__type == "repeated")
|
||||
then ''
|
||||
${name} {
|
||||
${exprToConfig value}
|
||||
}
|
||||
''
|
||||
else "${name} => ${exprToConfig value}";
|
||||
|
||||
repeatedAttrsToConfig = values:
|
||||
concatStringsSep "\n" (map valueToConfig values);
|
||||
|
||||
attrsToConfig = attrs:
|
||||
let
|
||||
attrToConfig = name: valueToConfig {
|
||||
inherit name;
|
||||
value = (getAttr name attrs);
|
||||
};
|
||||
in
|
||||
concatStringsSep "\n" (map attrToConfig (attrNames attrs));
|
||||
|
||||
exprToConfig = expr:
|
||||
let
|
||||
isCustomType = expr: (isAttrs expr) && (expr ? __type);
|
||||
|
||||
isFloat = expr: (isCustomType expr) && (expr.__type == "float");
|
||||
|
||||
isHash = expr: (isCustomType expr) && (expr.__type == "hash");
|
||||
|
||||
isRepeatedAttrs = expr: (isCustomType expr) && (expr.__type == "repeated");
|
||||
in
|
||||
if builtins.isBool expr then (if expr then "true" else "false") else
|
||||
if builtins.isString expr then ''"${expr}"'' else
|
||||
if builtins.isInt expr then toString expr else
|
||||
if isFloat expr then expr.value else
|
||||
if isList expr then listToConfig expr else
|
||||
if isHash expr then hashToConfig expr.value else
|
||||
if isRepeatedAttrs expr then repeatedAttrsToConfig expr.values
|
||||
else attrsToConfig expr;
|
||||
|
||||
mergeConfigs = configs:
|
||||
let
|
||||
op = attrs: newAttrs:
|
||||
let
|
||||
isRepeated = newAttrs ? __type && newAttrs.__type == "repeated";
|
||||
in {
|
||||
values = attrs.values ++ (if isRepeated then newAttrs.values else
|
||||
map (name: { inherit name; value = getAttr name newAttrs; })
|
||||
(attrNames newAttrs));
|
||||
};
|
||||
in (foldl op { values = []; } configs) // { __type = "repeated"; };
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
services.logstash = {
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
description = ''
|
||||
Enable logstash.
|
||||
'';
|
||||
};
|
||||
|
||||
inputConfig = mkOption {
|
||||
default = {};
|
||||
description = ''
|
||||
An attribute set (or an expression generated by mkNameValuePairs)
|
||||
representing a logstash configuration's input section.
|
||||
Logstash configs are name-value pairs, where values can be bools,
|
||||
strings, numbers, arrays, hashes, or other name-value pairs,
|
||||
and names are strings that can be repeated. Name-value pairs with no
|
||||
repeats are represented by attr sets. Bools, strings, ints, and
|
||||
arrays are mapped directly. Name-value pairs with repeats can be
|
||||
generated by the config.lib.logstash.mkNameValuePairs function, which
|
||||
takes a list of attrsets and combines them while preserving attribute
|
||||
name duplicates if they occur. Similarly, there are the mkFloat and
|
||||
mkHash functions, which take a string representation of a float and an
|
||||
attrset, respectively.
|
||||
'';
|
||||
merge = mergeConfigs;
|
||||
};
|
||||
|
||||
filterConfig = mkOption {
|
||||
default = {};
|
||||
description = ''
|
||||
An attribute set (or an expression generated by mkNameValuePairs)
|
||||
representing a logstash configuration's filter section.
|
||||
See inputConfig description for details.
|
||||
'';
|
||||
merge = mergeConfigs;
|
||||
};
|
||||
|
||||
outputConfig = mkOption {
|
||||
default = {};
|
||||
description = ''
|
||||
An attribute set (or an expression generated by mkNameValuePairs)
|
||||
representing a logstash configuration's output section.
|
||||
See inputConfig description for details.
|
||||
'';
|
||||
merge = mergeConfigs;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkMerge [ {
|
||||
lib.logstash = {
|
||||
mkFloat = stringRep: { __type = "float"; value = stringRep; };
|
||||
|
||||
mkHash = attrs: { __type = "hash"; value = attrs; };
|
||||
|
||||
mkNameValuePairs = mergeConfigs;
|
||||
};
|
||||
} ( mkIf cfg.enable {
|
||||
systemd.services.logstash = with pkgs; {
|
||||
description = "Logstash daemon";
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
path = [ jre ];
|
||||
|
||||
script = "cd /tmp && exec java -jar ${logstash} agent -f ${writeText "logstash.conf" ''
|
||||
input {
|
||||
${exprToConfig cfg.inputConfig}
|
||||
}
|
||||
|
||||
filter {
|
||||
${exprToConfig cfg.filterConfig}
|
||||
}
|
||||
|
||||
output {
|
||||
${exprToConfig cfg.outputConfig}
|
||||
}
|
||||
''} &> /var/log/logstash.log";
|
||||
};
|
||||
})];
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
with pkgs.lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.services.rsyslogd;
|
||||
|
||||
syslogConf = pkgs.writeText "syslog.conf" ''
|
||||
$ModLoad imuxsock
|
||||
$SystemLogSocketName /run/systemd/journal/syslog
|
||||
$WorkDirectory /var/spool/rsyslog
|
||||
|
||||
${cfg.defaultConfig}
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
|
||||
defaultConf = ''
|
||||
# "local1" is used for dhcpd messages.
|
||||
local1.* -/var/log/dhcpd
|
||||
|
||||
mail.* -/var/log/mail
|
||||
|
||||
*.=warning;*.=err -/var/log/warn
|
||||
*.crit /var/log/warn
|
||||
|
||||
*.*;mail.none;local1.none -/var/log/messages
|
||||
'';
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
|
||||
services.rsyslogd = {
|
||||
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to enable syslogd. Note that systemd also logs
|
||||
syslog messages, so you normally don't need to run syslogd.
|
||||
'';
|
||||
};
|
||||
|
||||
defaultConfig = mkOption {
|
||||
type = types.string;
|
||||
default = defaultConf;
|
||||
description = ''
|
||||
The default <filename>syslog.conf</filename> file configures a
|
||||
fairly standard setup of log files, which can be extended by
|
||||
means of <varname>extraConfig</varname>.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.string;
|
||||
default = "";
|
||||
example = "news.* -/var/log/news";
|
||||
description = ''
|
||||
Additional text appended to <filename>syslog.conf</filename>,
|
||||
i.e. the contents of <varname>defaultConfig</varname>.
|
||||
'';
|
||||
};
|
||||
|
||||
extraParams = mkOption {
|
||||
type = types.listOf types.string;
|
||||
default = [ ];
|
||||
example = [ "-m 0" ];
|
||||
description = ''
|
||||
Additional parameters passed to <command>rsyslogd</command>.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
environment.systemPackages = [ pkgs.rsyslog ];
|
||||
|
||||
systemd.services.syslog =
|
||||
{ description = "Syslog Daemon";
|
||||
|
||||
requires = [ "syslog.socket" ];
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig =
|
||||
{ ExecStart = "${pkgs.rsyslog}/sbin/rsyslogd ${toString cfg.extraParams} -f ${syslogConf} -n";
|
||||
ExecStartPre = "${pkgs.coreutils}/bin/mkdir -p /var/spool/rsyslog";
|
||||
# Prevent syslogd output looping back through journald.
|
||||
StandardOutput = "null";
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
with pkgs.lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.services.syslogd;
|
||||
|
||||
syslogConf = pkgs.writeText "syslog.conf" ''
|
||||
${if (cfg.tty != "") then "kern.warning;*.err;authpriv.none /dev/${cfg.tty}" else ""}
|
||||
${cfg.defaultConfig}
|
||||
${cfg.extraConfig}
|
||||
'';
|
||||
|
||||
defaultConf = ''
|
||||
# Send emergency messages to all users.
|
||||
*.emerg *
|
||||
|
||||
# "local1" is used for dhcpd messages.
|
||||
local1.* -/var/log/dhcpd
|
||||
|
||||
mail.* -/var/log/mail
|
||||
|
||||
*.=warning;*.=err -/var/log/warn
|
||||
*.crit /var/log/warn
|
||||
|
||||
*.*;mail.none;local1.none -/var/log/messages
|
||||
'';
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
|
||||
services.syslogd = {
|
||||
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to enable syslogd. Note that systemd also logs
|
||||
syslog messages, so you normally don't need to run syslogd.
|
||||
'';
|
||||
};
|
||||
|
||||
tty = mkOption {
|
||||
type = types.uniq types.string;
|
||||
default = "tty10";
|
||||
description = ''
|
||||
The tty device on which syslogd will print important log
|
||||
messages. Leave this option blank to disable tty logging.
|
||||
'';
|
||||
};
|
||||
|
||||
defaultConfig = mkOption {
|
||||
type = types.string;
|
||||
default = defaultConf;
|
||||
description = ''
|
||||
The default <filename>syslog.conf</filename> file configures a
|
||||
fairly standard setup of log files, which can be extended by
|
||||
means of <varname>extraConfig</varname>.
|
||||
'';
|
||||
};
|
||||
|
||||
enableNetworkInput = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Accept logging through UDP. Option -r of syslogd(8).
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.string;
|
||||
default = "";
|
||||
example = "news.* -/var/log/news";
|
||||
description = ''
|
||||
Additional text appended to <filename>syslog.conf</filename>,
|
||||
i.e. the contents of <varname>defaultConfig</varname>.
|
||||
'';
|
||||
};
|
||||
|
||||
extraParams = mkOption {
|
||||
type = types.listOf types.string;
|
||||
default = [ ];
|
||||
example = [ "-m 0" ];
|
||||
description = ''
|
||||
Additional parameters passed to <command>syslogd</command>.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
environment.systemPackages = [ pkgs.sysklogd ];
|
||||
|
||||
services.syslogd.extraParams = optional cfg.enableNetworkInput "-r";
|
||||
|
||||
# FIXME: restarting syslog seems to break journal logging.
|
||||
systemd.services.syslog =
|
||||
{ description = "Syslog Daemon";
|
||||
|
||||
requires = [ "syslog.socket" ];
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig =
|
||||
{ ExecStart = "${pkgs.sysklogd}/sbin/syslogd ${toString cfg.extraParams} -f ${syslogConf} -n";
|
||||
# Prevent syslogd output looping back through journald.
|
||||
StandardOutput = "null";
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user