From 05262ad35d9fb7db15ca097f8c931f6c5b3999fe Mon Sep 17 00:00:00 2001 From: Mathijs Kwik Date: Fri, 24 Aug 2012 00:27:07 +0200 Subject: [PATCH 01/12] postfix: allow specifying 'virtual' mappings mainly useful for having a few local addresses (me@host.domain.com) while the majority of addresses are on the domain (you@domain.com) --- modules/services/mail/postfix.nix | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/modules/services/mail/postfix.nix b/modules/services/mail/postfix.nix index 842427f6d05..3784ae3d39f 100644 --- a/modules/services/mail/postfix.nix +++ b/modules/services/mail/postfix.nix @@ -80,6 +80,9 @@ let recipientDelimiter = ${cfg.recipientDelimiter} '' + + optionalString (cfg.virtual != "") '' + virtual_alias_maps = hash:/etc/postfix/virtual + '' + cfg.extraConfig; aliases = @@ -93,6 +96,7 @@ let ; aliasesFile = pkgs.writeText "postfix-aliases" aliases; + virtualFile = pkgs.writeText "postfix-virtual" cfg.virtual; mainCfFile = pkgs.writeText "postfix-main.cf" mainCf; in @@ -255,6 +259,13 @@ in "; }; + virtual = mkOption { + default = ""; + description = " + Entries for the virtual alias map. + "; + }; + }; }; @@ -338,9 +349,11 @@ in ln -sf ${pkgs.postfix}/share/postfix/conf/* /var/postfix/conf ln -sf ${aliasesFile} /var/postfix/conf/aliases + ln -sf ${virtualFile} /var/postfix/conf/virtual ln -sf ${mainCfFile} /var/postfix/conf/main.cf ${pkgs.postfix}/sbin/postalias -c /var/postfix/conf /var/postfix/conf/aliases + ${pkgs.postfix}/sbin/postmap -c /var/postfix/conf /var/postfix/conf/virtual exec ${pkgs.postfix}/sbin/postfix -c /var/postfix/conf start ''; # */ From aba9f76105de058a6d0f9b5a11eb6a03a581b296 Mon Sep 17 00:00:00 2001 From: Mathijs Kwik Date: Sun, 26 Aug 2012 10:17:22 +0200 Subject: [PATCH 02/12] change permission of /run/lock to allow non-root access to subdirectories --- modules/system/boot/stage-2-init.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/system/boot/stage-2-init.sh b/modules/system/boot/stage-2-init.sh index f0e04aed179..256792460d0 100644 --- a/modules/system/boot/stage-2-init.sh +++ b/modules/system/boot/stage-2-init.sh @@ -133,7 +133,7 @@ if ! mountpoint -q /run; then mount -t tmpfs -o "mode=0755,size=@runSize@" none /run fi -mkdir -m 0700 -p /run/lock +mkdir -m 0755 -p /run/lock # For backwards compatibility, symlink /var/run to /run, and /var/lock From 2769f594f3c073715ecf8d6fc5bfb68a3e1f2888 Mon Sep 17 00:00:00 2001 From: Mathijs Kwik Date: Sat, 25 Aug 2012 11:11:37 +0200 Subject: [PATCH 03/12] add logcheck module --- modules/module-list.nix | 1 + modules/services/logging/logcheck.nix | 138 ++++++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 modules/services/logging/logcheck.nix diff --git a/modules/module-list.nix b/modules/module-list.nix index 697cc60e35e..08927d747ff 100644 --- a/modules/module-list.nix +++ b/modules/module-list.nix @@ -80,6 +80,7 @@ ./services/hardware/udisks.nix ./services/hardware/upower.nix ./services/logging/klogd.nix + ./services/logging/logcheck.nix ./services/logging/logrotate.nix ./services/logging/logstash.nix ./services/logging/syslogd.nix diff --git a/modules/services/logging/logcheck.nix b/modules/services/logging/logcheck.nix new file mode 100644 index 00000000000..30a9bf870e9 --- /dev/null +++ b/modules/services/logging/logcheck.nix @@ -0,0 +1,138 @@ +{config, pkgs, ...}: + +with pkgs.lib; + +let + cfg = config.services.logcheck; + + rulesDir = pkgs.runCommand "logcheck-rules-dir" + {} ( + '' + mkdir $out + cp -prd ${pkgs.logcheck}/etc/logcheck/* $out/ + rm $out/logcheck.* + '' + optionalString (! builtins.isNull cfg.extraRulesDir) '' + cp -prd ${cfg.extraRulesDir}/* $out/ + '' ); + + 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} + ''; + +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. + ''; + }; + + extraRulesDir = mkOption { + default = null; + example = "/etc/logcheck"; + type = types.nullOr types.path; + description = '' + Directory with extra rules. + Will be merged with bundled rules, so it's possible to override certain behaviour. + ''; + }; + + 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 { + 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 = [ cronJob ]; + }; +} From 51e58dafca6303a3e98c728b157753d8567bac76 Mon Sep 17 00:00:00 2001 From: Peter Simons Date: Tue, 28 Aug 2012 16:27:28 +0200 Subject: [PATCH 04/12] spamassassin: use a dedicated user for running spamd --- modules/misc/ids.nix | 1 + modules/services/mail/spamassassin.nix | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/misc/ids.nix b/modules/misc/ids.nix index bd38b5f9a42..ea28162686e 100644 --- a/modules/misc/ids.nix +++ b/modules/misc/ids.nix @@ -73,6 +73,7 @@ in fprot = 52; bind = 53; wwwrun = 54; + spamd = 55; # When adding a uid, make sure it doesn't match an existing gid. diff --git a/modules/services/mail/spamassassin.nix b/modules/services/mail/spamassassin.nix index 69d3c390bc9..9b387eb940f 100644 --- a/modules/services/mail/spamassassin.nix +++ b/modules/services/mail/spamassassin.nix @@ -33,11 +33,17 @@ in # Allow users to run 'spamc'. environment.systemPackages = [ pkgs.spamassassin ]; + users.extraUsers = singleton + { name = "spamd"; + description = "Spam Assassin Daemon"; + uid = config.ids.uids.spamd; + }; + jobs.spamd = { description = "Spam Assassin Server"; startOn = "started networking and filesystem"; environment.TZ = config.time.timeZone; - exec = "${pkgs.spamassassin}/bin/spamd -C /etc/spamassassin/init.pre --siteconfigpath=/etc/spamassassin --debug --pidfile=/var/run/spamd.pid"; + exec = "${pkgs.spamassassin}/bin/spamd -C /etc/spamassassin/init.pre --siteconfigpath=/etc/spamassassin --username=spamd --pidfile=/var/run/spamd.pid"; }; }; From d106a8a29646da45617cfc8c20882d14824015a8 Mon Sep 17 00:00:00 2001 From: Mathijs Kwik Date: Tue, 28 Aug 2012 00:34:13 +0200 Subject: [PATCH 05/12] logcheck: make sure directories are writable during merge phase --- modules/services/logging/logcheck.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/services/logging/logcheck.nix b/modules/services/logging/logcheck.nix index 30a9bf870e9..40d736255ec 100644 --- a/modules/services/logging/logcheck.nix +++ b/modules/services/logging/logcheck.nix @@ -11,6 +11,7 @@ let mkdir $out cp -prd ${pkgs.logcheck}/etc/logcheck/* $out/ rm $out/logcheck.* + chmod u+w $out/* '' + optionalString (! builtins.isNull cfg.extraRulesDir) '' cp -prd ${cfg.extraRulesDir}/* $out/ '' ); From 0dd46d133544b5fa850540faa5d663cc75aeaf3d Mon Sep 17 00:00:00 2001 From: Mathijs Kwik Date: Wed, 29 Aug 2012 22:15:04 +0200 Subject: [PATCH 06/12] networking: add options for configuring virtual devices (tun/tap) These are mainly useful for network tunnels (vpn/ipv6) and creating bridges for virtual machines --- modules/tasks/network-interfaces.nix | 33 +++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/modules/tasks/network-interfaces.nix b/modules/tasks/network-interfaces.nix index c12f9b28ca9..e534bf8cc56 100644 --- a/modules/tasks/network-interfaces.nix +++ b/modules/tasks/network-interfaces.nix @@ -5,6 +5,7 @@ with pkgs.lib; let cfg = config.networking; + hasVirtuals = any (i: i.virtual) cfg.interfaces; in @@ -119,6 +120,26 @@ in ''; }; + virtual = mkOption { + default = false; + type = types.bool; + description = '' + Whether this interface is virtual and should be created by tunctl. + This is mainly useful for creating bridges between a host a virtual + network such as VPN or a virtual machine. + + Defaults to tap device, unless interface contains "tun" in its name. + ''; + }; + + virtualOwner = mkOption { + default = "root"; + type = types.uniq types.string; + description = '' + In case of a virtual device, the user who owns it. + ''; + }; + }; }; @@ -179,7 +200,7 @@ in config = { - boot.kernelModules = optional cfg.enableIPv6 "ipv6"; + boot.kernelModules = optional cfg.enableIPv6 "ipv6" ++ optional hasVirtuals "tun"; environment.systemPackages = [ pkgs.host @@ -191,6 +212,7 @@ in pkgs.openresolv ] ++ optional (cfg.bridges != {}) pkgs.bridge_utils + ++ optional hasVirtuals pkgs.tunctl ++ optional cfg.enableIPv6 pkgs.ndisc6; security.setuidPrograms = [ "ping" "ping6" ]; @@ -206,6 +228,15 @@ in '' set +e # continue in case of errors + # Create virtual network interfaces + ${flip concatMapStrings cfg.interfaces (i: + optionalString i.virtual + '' + echo "Creating virtual network interface ${i.name}..." + ${pkgs.tunctl}/bin/tunctl -t "${i.name}" -u "${i.virtualOwner}" + '') + } + # Set MAC addresses of interfaces, if desired. ${flip concatMapStrings cfg.interfaces (i: optionalString (i.macAddress != "") From a502ce1128d13aa9dbdaf10b0199c7428c12666a Mon Sep 17 00:00:00 2001 From: Mathijs Kwik Date: Wed, 29 Aug 2012 22:17:40 +0200 Subject: [PATCH 07/12] networking: add proxy_arp / proxy_ndp options. proxy_arp (and proxy_ndp for ipv6) can be turned on on a few interfaces (at least 2). This is mainly useful for creating pseudo-bridges between a real interface and a virtual network such as VPN or a virtual machine for interfaces that don't support real bridging (most wlan interfaces). As ARP proxying acts slightly above the link-layer, below-ip traffic isn't bridged, so things like DHCP won't work. The advantage above using NAT lies in the fact that no IP addresses are shared, so all hosts are reachable/routeable. --- modules/tasks/network-interfaces.nix | 31 ++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/modules/tasks/network-interfaces.nix b/modules/tasks/network-interfaces.nix index e534bf8cc56..4389d6421c5 100644 --- a/modules/tasks/network-interfaces.nix +++ b/modules/tasks/network-interfaces.nix @@ -140,6 +140,24 @@ in ''; }; + proxyARP = mkOption { + default = false; + type = types.bool; + description = '' + Turn on proxy_arp for this device (and proxy_ndp for ipv6). + This is mainly useful for creating pseudo-bridges between a real + interface and a virtual network such as VPN or a virtual machine for + interfaces that don't support real bridging (most wlan interfaces). + As ARP proxying acts slightly above the link-layer, below-ip traffic + isn't bridged, so things like DHCP won't work. The advantage above + using NAT lies in the fact that no IP addresses are shared, so all + hosts are reachable/routeable. + + WARNING: turns on ip-routing, so if you have multiple interfaces, you + should think of the consequence and setup firewall rules to limit this. + ''; + }; + }; }; @@ -275,6 +293,14 @@ in echo "Configuring interface ${i.name}..." ip addr add "${i.ipAddress}""${optionalString (i.subnetMask != "") ("/" + i.subnetMask)}" \ dev "${i.name}" + '' + + optionalString i.proxyARP + '' + echo 1 > /proc/sys/net/ipv4/conf/${i.name}/proxy_arp + '' + + optionalString (i.proxyARP && cfg.enableIPv6) + '' + echo 1 > /proc/sys/net/ipv6/conf/${i.name}/proxy_ndp '') } @@ -293,6 +319,11 @@ in ip route add default via "${cfg.defaultGateway}" ''} + # turn on forwarding if any interface has enabled proxy_arp + ${optionalString (any (i: i.proxyARP) cfg.interfaces) '' + echo 1 > /proc/sys/net/ipv4/ip_forward + ''} + # Run any user-specified commands. ${pkgs.stdenv.shell} ${pkgs.writeText "local-net-cmds" cfg.localCommands} From bce1cdd59cbc3e7572c3b7f09e9d17d96de23df4 Mon Sep 17 00:00:00 2001 From: Mathijs Kwik Date: Thu, 30 Aug 2012 18:31:45 +0200 Subject: [PATCH 08/12] fix kernel 3.4+ early cifs mounting (qemu-vm target) kernel 3.4+ needs cifs-utils to mount CIFS filesystems. the kernel itself (and busybox's cifs mount code) are no longer able to do this in some/most cases and will error out saying: "CIFS VFS: connecting to DFS root not implemented yet" Nixos' qemu-vm target is hurt by this, as it wants to mount /nix/store via cifs very early in the boot process. This commit makes sure the initrd for affected kernels is built with cifs-utils if needed. --- modules/system/boot/stage-1.nix | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/modules/system/boot/stage-1.nix b/modules/system/boot/stage-1.nix index 265adf163fc..d7925c0f7d3 100644 --- a/modules/system/boot/stage-1.nix +++ b/modules/system/boot/stage-1.nix @@ -121,6 +121,20 @@ let enableSplashScreen = config.boot.vesa && config.boot.initrd.enableSplashScreen && kernelPackages.splashutils != null; + needsCifsUtils = kernelPackages.kernel ? features + && kernelPackages.kernel.features ? needsCifsUtils + && kernelPackages.kernel.features.needsCifsUtils + && any (fs: fs.fsType == "cifs") fileSystems; + + busybox = if needsCifsUtils + then pkgs.busybox.override { + extraConfig = '' + CONFIG_FEATURE_MOUNT_CIFS n + CONFIG_FEATURE_MOUNT_HELPERS y + ''; + } + else pkgs.busybox; + # Some additional utilities needed in stage 1, like mount, lvm, fsck # etc. We don't want to bring in all of those packages, so we just @@ -146,7 +160,7 @@ let cp -pv ${pkgs.gcc.gcc}/lib*/libgcc_s.so.* $out/lib # Copy BusyBox. - cp -rvd ${pkgs.busybox}/{bin,sbin} $out/ + cp -rvd ${busybox}/{bin,sbin} $out/ chmod -R u+w $out # Copy some utillinux stuff. @@ -175,6 +189,11 @@ let cp ${kernelPackages.splashutils}/${kernelPackages.splashutils.helperName} $out/bin/splash_helper ''} + # Maybe copy cifs utils + ${optionalString needsCifsUtils '' + cp -v ${pkgs.cifs_utils}/sbin/mount.cifs $out/bin + ''} + ${config.boot.initrd.extraUtilsCommands} # Strip binaries further than normal. From 4be367ec47fac9397bc329f5d404a6f7748bee67 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Mon, 3 Sep 2012 10:35:45 -0400 Subject: [PATCH 09/12] Damn NixOS lack of laziness... --- modules/hardware/network/b43.nix | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/hardware/network/b43.nix b/modules/hardware/network/b43.nix index 077e0a1e11e..caf40f68058 100644 --- a/modules/hardware/network/b43.nix +++ b/modules/hardware/network/b43.nix @@ -22,9 +22,11 @@ let kernelVersion = config.boot.kernelPackages.kernel.version; in ###### implementation config = pkgs.lib.mkIf config.networking.enableB43Firmware { - hardware.firmware = if builtins.lessThan (builtins.compareVersions kernelVersion "3.2") 0 then - throw "b43 firmware for kernels older than 3.2 not packaged yet!" else - [ pkgs.b43Firmware_5_1_138 ]; + assertions = [ { + assertion = builtins.lessThan (builtins.compareVersions kernelVersion "3.2") 0; + message = "b43 firmware for kernels older than 3.2 not packaged yet!"; + } ]; + hardware.firmware = [ pkgs.b43Firmware_5_1_138 ]; }; } From f701e8d420c1a0114239bab3b9196a2c98f6f813 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Mon, 3 Sep 2012 12:11:07 -0400 Subject: [PATCH 10/12] d'oh --- modules/hardware/network/b43.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/hardware/network/b43.nix b/modules/hardware/network/b43.nix index caf40f68058..8f45bd4d3f1 100644 --- a/modules/hardware/network/b43.nix +++ b/modules/hardware/network/b43.nix @@ -23,7 +23,7 @@ let kernelVersion = config.boot.kernelPackages.kernel.version; in config = pkgs.lib.mkIf config.networking.enableB43Firmware { assertions = [ { - assertion = builtins.lessThan (builtins.compareVersions kernelVersion "3.2") 0; + assertion = builtins.lessThan 0 (builtins.compareVersions kernelVersion "3.2"); message = "b43 firmware for kernels older than 3.2 not packaged yet!"; } ]; hardware.firmware = [ pkgs.b43Firmware_5_1_138 ]; From 27880ed729d4b38a8076f74c0f511b42e7ea1138 Mon Sep 17 00:00:00 2001 From: Rob Vermaas Date: Thu, 6 Sep 2012 12:31:15 +0200 Subject: [PATCH 11/12] Change logstash job startOn attribute to include networking --- modules/services/logging/logstash.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/services/logging/logstash.nix b/modules/services/logging/logstash.nix index bb3b83dd230..f4c226ac349 100644 --- a/modules/services/logging/logstash.nix +++ b/modules/services/logging/logstash.nix @@ -141,6 +141,7 @@ in jobs.logstash = with pkgs; { description = "Logstash daemon"; + startOn = "started networking and filesystem"; path = [ jre ]; From f7530dc5ee6b4a0118ff7456511fc2aa4693695c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= Date: Fri, 7 Sep 2012 10:58:53 +0200 Subject: [PATCH 12/12] avahi: Never set `host-name' to the empty string in `avahi-daemon.conf'. --- modules/services/networking/avahi-daemon.nix | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/services/networking/avahi-daemon.nix b/modules/services/networking/avahi-daemon.nix index 791109dcda2..3603d677837 100644 --- a/modules/services/networking/avahi-daemon.nix +++ b/modules/services/networking/avahi-daemon.nix @@ -11,7 +11,13 @@ let avahiDaemonConf = with cfg; pkgs.writeText "avahi-daemon.conf" '' [server] - host-name=${hostName} + ${# Users can set `networking.hostName' to the empty string, when getting + # a host name from DHCP. In that case, let Avahi take whatever the + # current host name is; setting `host-name' to the empty string in + # `avahi-daemon.conf' would be invalid. + if hostName != "" + then "host-name=${hostName}" + else ""} browse-domains=${concatStringsSep ", " browseDomains} use-ipv4=${if ipv4 then "yes" else "no"} use-ipv6=${if ipv6 then "yes" else "no"}