about summary refs log tree commit diff
path: root/nixos/modules
diff options
context:
space:
mode:
authorThomas Tuegel <ttuegel@mailbox.org>2017-07-21 20:36:34 -0500
committerThomas Tuegel <ttuegel@mailbox.org>2017-07-21 20:36:34 -0500
commit6a004bf9c896e7570f85ba9296b51ff90a545842 (patch)
treebc7cc568283165c2f205d2bda568a148381a532d /nixos/modules
parentbec5797290754fa783b77a49149254417cde1344 (diff)
parent827b0e1b815772458954e330327dcd7491ec485d (diff)
downloadnixlib-6a004bf9c896e7570f85ba9296b51ff90a545842.tar
nixlib-6a004bf9c896e7570f85ba9296b51ff90a545842.tar.gz
nixlib-6a004bf9c896e7570f85ba9296b51ff90a545842.tar.bz2
nixlib-6a004bf9c896e7570f85ba9296b51ff90a545842.tar.lz
nixlib-6a004bf9c896e7570f85ba9296b51ff90a545842.tar.xz
nixlib-6a004bf9c896e7570f85ba9296b51ff90a545842.tar.zst
nixlib-6a004bf9c896e7570f85ba9296b51ff90a545842.zip
Merge branch 'master' into bugfix/staging/stdenv
Diffstat (limited to 'nixos/modules')
-rw-r--r--nixos/modules/installer/tools/nix-fallback-paths.nix6
-rw-r--r--nixos/modules/module-list.nix1
-rw-r--r--nixos/modules/programs/gnupg.nix2
-rw-r--r--nixos/modules/services/logging/journalwatch.nix246
-rw-r--r--nixos/modules/services/networking/bitlbee.nix27
-rw-r--r--nixos/modules/services/networking/strongswan.nix2
-rw-r--r--nixos/modules/services/networking/wireguard.nix85
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix1
-rw-r--r--nixos/modules/virtualisation/azure-images.nix5
-rw-r--r--nixos/modules/virtualisation/gce-images.nix8
10 files changed, 350 insertions, 33 deletions
diff --git a/nixos/modules/installer/tools/nix-fallback-paths.nix b/nixos/modules/installer/tools/nix-fallback-paths.nix
index 8703ea1ca54f..4568a20e7789 100644
--- a/nixos/modules/installer/tools/nix-fallback-paths.nix
+++ b/nixos/modules/installer/tools/nix-fallback-paths.nix
@@ -1,5 +1,5 @@
 {
-  x86_64-linux = "/nix/store/2y3cn6siixhr7pbsz2grry89jzchkxyd-nix-1.11.12";
-  i686-linux = "/nix/store/sbz8z995lysxja8brnxmw7hgi6ljigrq-nix-1.11.12";
-  x86_64-darwin = "/nix/store/gs2z548x41ah2h8fqnbn87syzazrlsb8-nix-1.11.12";
+  x86_64-linux = "/nix/store/avwiw7hb1qckag864sc6ixfxr8qmf94w-nix-1.11.13";
+  i686-linux = "/nix/store/8wv3ms0afw95hzsz4lxzv0nj4w3614z9-nix-1.11.13";
+  x86_64-darwin = "/nix/store/z21lvakv1l7lhasmv5fvaz8mlzxia8k9-nix-1.11.13";
 }
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 4335a4b3eece..726c55539190 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -243,6 +243,7 @@
   ./services/logging/graylog.nix
   ./services/logging/heartbeat.nix
   ./services/logging/journalbeat.nix
+  ./services/logging/journalwatch.nix
   ./services/logging/klogd.nix
   ./services/logging/logcheck.nix
   ./services/logging/logrotate.nix
diff --git a/nixos/modules/programs/gnupg.nix b/nixos/modules/programs/gnupg.nix
index ea46d5934d9f..8af55f38992f 100644
--- a/nixos/modules/programs/gnupg.nix
+++ b/nixos/modules/programs/gnupg.nix
@@ -77,7 +77,7 @@ in
 
     systemd.packages = [ pkgs.gnupg ];
 
-    environment.interactiveShellInit = ''
+    environment.extraInit = ''
       # Bind gpg-agent to this TTY if gpg commands are used.
       export GPG_TTY=$(tty)
 
diff --git a/nixos/modules/services/logging/journalwatch.nix b/nixos/modules/services/logging/journalwatch.nix
new file mode 100644
index 000000000000..d49795fe2b77
--- /dev/null
+++ b/nixos/modules/services/logging/journalwatch.nix
@@ -0,0 +1,246 @@
+{ config, lib, pkgs, services, ... }:
+with lib;
+
+let
+  cfg = config.services.journalwatch;
+  user = "journalwatch";
+  dataDir = "/var/lib/${user}";
+
+  journalwatchConfig = pkgs.writeText "config" (''
+    # (File Generated by NixOS journalwatch module.)
+    [DEFAULT]
+    mail_binary = ${cfg.mailBinary}
+    priority = ${toString cfg.priority}
+    mail_from = ${cfg.mailFrom}
+  ''
+  + optionalString (cfg.mailTo != null) ''
+    mail_to = ${cfg.mailTo}
+  ''
+  + cfg.extraConfig);
+
+  journalwatchPatterns = pkgs.writeText "patterns" ''
+    # (File Generated by NixOS journalwatch module.)
+
+    ${mkPatterns cfg.filterBlocks}
+  '';
+
+  # empty line at the end needed to to separate the blocks
+  mkPatterns = filterBlocks: concatStringsSep "\n" (map (block: ''
+    ${block.match}
+    ${block.filters}
+
+  '') filterBlocks);
+
+
+in {
+  options = {
+    services.journalwatch = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          If enabled, periodically check the journal with journalwatch and report the results by mail.
+        '';
+      };
+
+      priority = mkOption {
+        type = types.int;
+        default = 6;
+        description = ''
+          Lowest priority of message to be considered.
+          A value between 7 ("debug"), and 0 ("emerg"). Defaults to 6 ("info").
+          If you don't care about anything with "info" priority, you can reduce
+          this to e.g. 5 ("notice") to considerably reduce the amount of
+          messages without needing many <option>filterBlocks</option>.
+        '';
+      };
+
+      # HACK: this is a workaround for journalwatch's usage of socket.getfqdn() which always returns localhost if
+      # there's an alias for the localhost on a separate line in /etc/hosts, or take for ages if it's not present and
+      # then return something right-ish in the direction of /etc/hostname. Just bypass it completely.
+      mailFrom = mkOption {
+        type = types.str;
+        default = "journalwatch@${config.networking.hostName}";
+        description = ''
+          Mail address to send journalwatch reports from.
+        '';
+      };
+
+      mailTo = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        description = ''
+          Mail address to send journalwatch reports to.
+        '';
+      };
+
+      mailBinary = mkOption {
+        type = types.path;
+        default = "/run/wrappers/bin/sendmail";
+        description = ''
+          Sendmail-compatible binary to be used to send the messages.
+        '';
+      };
+
+      extraConfig = mkOption {
+        type = types.str;
+        default = "";
+        description = ''
+          Extra lines to be added verbatim to the journalwatch/config configuration file.
+          You can add any commandline argument to the config, without the '--'.
+          See <literal>journalwatch --help</literal> for all arguments and their description.
+          '';
+      };
+
+      filterBlocks = mkOption {
+        type = types.listOf (types.submodule {
+          options = {
+           match = mkOption {
+              type = types.str;
+              example = "SYSLOG_IDENTIFIER = systemd";
+              description = ''
+                Syntax: <literal>field = value</literal>
+                Specifies the log entry <literal>field</literal> this block should apply to.
+                If the <literal>field</literal> of a message matches this <literal>value</literal>,
+                this patternBlock's <option>filters</option> are applied.
+                If <literal>value</literal> starts and ends with a slash, it is interpreted as
+                an extended python regular expression, if not, it's an exact match.
+                The journal fields are explained in systemd.journal-fields(7).
+              '';
+            };
+
+            filters = mkOption {
+              type = types.str;
+              example = ''
+                (Stopped|Stopping|Starting|Started) .*
+                (Reached target|Stopped target) .*
+              '';
+              description = ''
+                The filters to apply on all messages which satisfy <option>match</option>.
+                Any of those messages that match any specified filter will be removed from journalwatch's output.
+                Each filter is an extended Python regular expression.
+                You can specify multiple filters and separate them by newlines.
+                Lines starting with '#' are comments. Inline-comments are not permitted.
+              '';
+            };
+          };
+        });
+
+        example = [
+          # examples taken from upstream
+          {
+            match = "_SYSTEMD_UNIT = systemd-logind.service";
+            filters = ''
+              New session [a-z]?\d+ of user \w+\.
+              Removed session [a-z]?\d+\.
+            '';
+          }
+
+          {
+            match = "SYSLOG_IDENTIFIER = /(CROND|crond)/";
+            filters = ''
+              pam_unix\(crond:session\): session (opened|closed) for user \w+
+              \(\w+\) CMD .*
+            '';
+          }
+        ];
+
+        # another example from upstream.
+        # very useful on priority = 6, and required as journalwatch throws an error when no pattern is defined at all.
+        default = [
+          {
+            match = "SYSLOG_IDENTIFIER = systemd";
+            filters = ''
+              (Stopped|Stopping|Starting|Started) .*
+              (Created slice|Removed slice) user-\d*\.slice\.
+              Received SIGRTMIN\+24 from PID .*
+              (Reached target|Stopped target) .*
+              Startup finished in \d*ms\.
+            '';
+          }
+        ];
+
+
+        description = ''
+          filterBlocks can be defined to blacklist journal messages which are not errors.
+          Each block matches on a log entry field, and the filters in that block then are matched
+          against all messages with a matching log entry field.
+
+          All messages whose PRIORITY is at least 6 (INFO) are processed by journalwatch.
+          If you don't specify any filterBlocks, PRIORITY is reduced to 5 (NOTICE) by default.
+
+          All regular expressions are extended Python regular expressions, for details
+          see: http://doc.pyschools.com/html/regex.html
+        '';
+      };
+
+      interval = mkOption {
+        type = types.str;
+        default = "hourly";
+        description = ''
+          How often to run journalwatch.
+
+          The format is described in systemd.time(7).
+        '';
+      };
+      accuracy = mkOption {
+        type = types.str;
+        default = "10min";
+        description = ''
+          The time window around the interval in which the journalwatch run will be scheduled.
+
+          The format is described in systemd.time(7).
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    users.extraUsers.${user} = {
+      isSystemUser = true;
+      createHome = true;
+      home = dataDir;
+      # for journal access
+      group = "systemd-journal";
+    };
+
+    systemd.services.journalwatch = {
+      environment = {
+        XDG_DATA_HOME = "${dataDir}/share";
+        XDG_CONFIG_HOME = "${dataDir}/config";
+      };
+      serviceConfig = {
+        User = user;
+        Type = "oneshot";
+        PermissionsStartOnly = true;
+        ExecStart = "${pkgs.python3Packages.journalwatch}/bin/journalwatch mail";
+        # lowest CPU and IO priority, but both still in best-effort class to prevent starvation
+        Nice=19;
+        IOSchedulingPriority=7;
+      };
+      preStart = ''
+        chown -R ${user}:systemd-journal ${dataDir}
+        chmod -R u+rwX,go-w ${dataDir}
+        mkdir -p ${dataDir}/config/journalwatch
+        ln -sf ${journalwatchConfig} ${dataDir}/config/journalwatch/config
+        ln -sf ${journalwatchPatterns} ${dataDir}/config/journalwatch/patterns
+      '';
+    };
+
+    systemd.timers.journalwatch = {
+      description = "Periodic journalwatch run";
+      wantedBy = [ "timers.target" ];
+      timerConfig = {
+        OnCalendar = cfg.interval;
+        AccuracySec = cfg.accuracy;
+        Persistent = true;
+      };
+    };
+
+  };
+
+  meta = {
+    maintainers = with stdenv.lib.maintainers; [ florianjacob ];
+  };
+}
diff --git a/nixos/modules/services/networking/bitlbee.nix b/nixos/modules/services/networking/bitlbee.nix
index e72ea20cccee..bd26804788f3 100644
--- a/nixos/modules/services/networking/bitlbee.nix
+++ b/nixos/modules/services/networking/bitlbee.nix
@@ -7,6 +7,10 @@ let
   cfg = config.services.bitlbee;
   bitlbeeUid = config.ids.uids.bitlbee;
 
+  bitlbeePkg = if cfg.libpurple_plugins == []
+  then pkgs.bitlbee
+  else pkgs.bitlbee.override { enableLibPurple = true; };
+
   bitlbeeConfig = pkgs.writeText "bitlbee.conf"
     ''
     [settings]
@@ -25,6 +29,12 @@ let
     ${cfg.extraDefaults}
     '';
 
+  purple_plugin_path =
+    lib.concatMapStringsSep ":"
+      (plugin: "${plugin}/lib/pidgin/")
+      cfg.libpurple_plugins
+    ;
+
 in
 
 {
@@ -90,6 +100,15 @@ in
         '';
       };
 
+      libpurple_plugins = mkOption {
+        type = types.listOf types.package;
+        default = [];
+        example = literalExample "[ pkgs.purple-matrix ]";
+        description = ''
+          The list of libpurple plugins to install.
+        '';
+      };
+
       configDir = mkOption {
         default = "/var/lib/bitlbee";
         type = types.path;
@@ -144,14 +163,16 @@ in
       };
 
     systemd.services.bitlbee =
-      { description = "BitlBee IRC to other chat networks gateway";
+      {
+        environment.PURPLE_PLUGIN_PATH = purple_plugin_path;
+        description = "BitlBee IRC to other chat networks gateway";
         after = [ "network.target" ];
         wantedBy = [ "multi-user.target" ];
         serviceConfig.User = "bitlbee";
-        serviceConfig.ExecStart = "${pkgs.bitlbee}/sbin/bitlbee -F -n -c ${bitlbeeConfig}";
+        serviceConfig.ExecStart = "${bitlbeePkg}/sbin/bitlbee -F -n -c ${bitlbeeConfig}";
       };
 
-    environment.systemPackages = [ pkgs.bitlbee ];
+    environment.systemPackages = [ bitlbeePkg ];
 
   };
 
diff --git a/nixos/modules/services/networking/strongswan.nix b/nixos/modules/services/networking/strongswan.nix
index 8778b0364f9a..b0eb0460b9ba 100644
--- a/nixos/modules/services/networking/strongswan.nix
+++ b/nixos/modules/services/networking/strongswan.nix
@@ -120,7 +120,7 @@ in
       wantedBy = [ "multi-user.target" ];
       path = with pkgs; [ kmod iproute iptables utillinux ]; # XXX Linux
       wants = [ "keys.target" ];
-      after = [ "network.target" "keys.target" ];
+      after = [ "network-online.target" "keys.target" ];
       environment = {
         STRONGSWAN_CONF = strongswanConf { inherit setup connections ca secrets; };
       };
diff --git a/nixos/modules/services/networking/wireguard.nix b/nixos/modules/services/networking/wireguard.nix
index 62ff708d244c..d5b21ef1a23b 100644
--- a/nixos/modules/services/networking/wireguard.nix
+++ b/nixos/modules/services/networking/wireguard.nix
@@ -23,8 +23,23 @@ let
 
       privateKey = mkOption {
         example = "yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=";
-        type = types.str;
-        description = "Base64 private key generated by wg genkey.";
+        type = with types; nullOr str;
+        default = null;
+        description = ''
+          Base64 private key generated by wg genkey.
+
+          Warning: Consider using privateKeyFile instead if you do not
+          want to store the key in the world-readable Nix store.
+        '';
+      };
+
+      privateKeyFile = mkOption {
+        example = "/private/wireguard_key";
+        type = with types; nullOr str;
+        default = null;
+        description = ''
+          Private key file as generated by wg genkey.
+        '';
       };
 
       listenPort = mkOption {
@@ -91,7 +106,22 @@ let
         example = "rVXs/Ni9tu3oDBLS4hOyAUAa1qTWVA3loR8eL20os3I=";
         type = with types; nullOr str;
         description = ''
-          base64 preshared key generated by wg genpsk. Optional,
+          Base64 preshared key generated by wg genpsk. Optional,
+          and may be omitted. This option adds an additional layer of
+          symmetric-key cryptography to be mixed into the already existing
+          public-key cryptography, for post-quantum resistance.
+
+          Warning: Consider using presharedKeyFile instead if you do not
+          want to store the key in the world-readable Nix store.
+        '';
+      };
+
+      presharedKeyFile = mkOption {
+        default = null;
+        example = "/private/wireguard_psk";
+        type = with types; nullOr str;
+        description = ''
+          File pointing to preshared key as generated by wg pensk. Optional,
           and may be omitted. This option adds an additional layer of
           symmetric-key cryptography to be mixed into the already existing
           public-key cryptography, for post-quantum resistance.
@@ -134,54 +164,59 @@ let
 
   };
 
-  generateConf = name: values: pkgs.writeText "wireguard-${name}.conf" ''
-    [Interface]
-    PrivateKey = ${values.privateKey}
-    ${optionalString (values.listenPort != null)   "ListenPort = ${toString values.listenPort}"}
-
-    ${concatStringsSep "\n\n" (map (peer: ''
-    [Peer]
-    PublicKey = ${peer.publicKey}
-    ${optionalString (peer.presharedKey != null) "PresharedKey = ${peer.presharedKey}"}
-    ${optionalString (peer.allowedIPs != []) "AllowedIPs = ${concatStringsSep ", " peer.allowedIPs}"}
-    ${optionalString (peer.endpoint != null) "Endpoint = ${peer.endpoint}"}
-    ${optionalString (peer.persistentKeepalive != null) "PersistentKeepalive = ${toString peer.persistentKeepalive}"}
-    '') values.peers)}
-  '';
-
   ipCommand = "${pkgs.iproute}/bin/ip";
   wgCommand = "${pkgs.wireguard}/bin/wg";
 
   generateUnit = name: values:
+    # exactly one way to specify the private key must be set
+    assert (values.privateKey != null) != (values.privateKeyFile != null);
+    let privKey = if values.privateKeyFile != null then values.privateKeyFile else pkgs.writeText "wg-key" values.privateKey;
+    in
     nameValuePair "wireguard-${name}"
       {
         description = "WireGuard Tunnel - ${name}";
         after = [ "network.target" ];
         wantedBy = [ "multi-user.target" ];
+
         serviceConfig = {
           Type = "oneshot";
           RemainAfterExit = true;
-          ExecStart = lib.flatten([
+          ExecStart = flatten([
             values.preSetup
 
             "-${ipCommand} link del dev ${name}"
             "${ipCommand} link add dev ${name} type wireguard"
-            "${wgCommand} setconf ${name} ${generateConf name values}"
 
             (map (ip:
-            ''${ipCommand} address add ${ip} dev ${name}''
+            "${ipCommand} address add ${ip} dev ${name}"
             ) values.ips)
 
+            ("${wgCommand} set ${name} private-key ${privKey}" +
+            optionalString (values.listenPort != null) " listen-port ${toString values.listenPort}")
+
+            (map (peer:
+            assert (peer.presharedKeyFile == null) || (peer.presharedKey == null); # at most one of the two must be set
+            let psk = if peer.presharedKey != null then pkgs.writeText "wg-psk" peer.presharedKey else peer.presharedKeyFile;
+            in
+            "${wgCommand} set ${name} peer ${peer.publicKey}" +
+            optionalString (psk != null) " preshared-key ${psk}" +
+            optionalString (peer.endpoint != null) " endpoint ${peer.endpoint}" +
+            optionalString (peer.persistentKeepalive != null) " persistent-keepalive ${toString peer.persistentKeepalive}" +
+            optionalString (peer.allowedIPs != []) " allowed-ips ${concatStringsSep "," peer.allowedIPs}"
+            ) values.peers)
+
             "${ipCommand} link set up dev ${name}"
 
-            (flatten (map (peer: (map (ip:
+            (map (peer: (map (ip:
             "${ipCommand} route add ${ip} dev ${name}"
-            ) peer.allowedIPs)) values.peers))
+            ) peer.allowedIPs)) values.peers)
 
             values.postSetup
           ]);
-
-          ExecStop = [ ''${ipCommand} link del dev "${name}"'' ] ++ values.postShutdown;
+          ExecStop = flatten([
+            "${ipCommand} link del dev ${name}"
+            values.postShutdown
+          ]);
         };
       };
 
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index f83413b4534e..2310912d0fde 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -65,6 +65,7 @@ let
         gzip_proxied any;
         gzip_comp_level 9;
         gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
+        gzip_vary on;
       ''}
 
       ${optionalString (cfg.recommendedProxySettings) ''
diff --git a/nixos/modules/virtualisation/azure-images.nix b/nixos/modules/virtualisation/azure-images.nix
new file mode 100644
index 000000000000..22c82fc14f65
--- /dev/null
+++ b/nixos/modules/virtualisation/azure-images.nix
@@ -0,0 +1,5 @@
+let self = {
+  "16.09" = "https://nixos.blob.core.windows.net/images/nixos-image-16.09.1694.019dcc3-x86_64-linux.vhd";
+
+  latest = self."16.09";
+}; in self
diff --git a/nixos/modules/virtualisation/gce-images.nix b/nixos/modules/virtualisation/gce-images.nix
new file mode 100644
index 000000000000..8a9bda1b60c2
--- /dev/null
+++ b/nixos/modules/virtualisation/gce-images.nix
@@ -0,0 +1,8 @@
+let self = {
+  "14.12" = "gs://nixos-cloud-images/nixos-14.12.471.1f09b77-x86_64-linux.raw.tar.gz";
+  "15.09" = "gs://nixos-cloud-images/nixos-15.09.425.7870f20-x86_64-linux.raw.tar.gz";
+  "16.03" = "gs://nixos-cloud-images/nixos-image-16.03.847.8688c17-x86_64-linux.raw.tar.gz";
+  "17.03" = "gs://nixos-cloud-images/nixos-image-17.03.1082.4aab5c5798-x86_64-linux.raw.tar.gz";
+
+  latest = self."17.03";
+}; in self