about summary refs log tree commit diff
path: root/nixpkgs/nixos
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2020-04-06 16:18:51 +0000
committerAlyssa Ross <hi@alyssa.is>2020-04-06 16:18:51 +0000
commit9afbeb71219925d54b72b0170b2e3be76bad1e28 (patch)
treed80c6bf0441de5412475859de320806b0e5a454c /nixpkgs/nixos
parent75eafe97f7df0d653bec67f3962214d7c357831f (diff)
parentae6bdcc53584aaf20211ce1814bea97ece08a248 (diff)
downloadnixlib-9afbeb71219925d54b72b0170b2e3be76bad1e28.tar
nixlib-9afbeb71219925d54b72b0170b2e3be76bad1e28.tar.gz
nixlib-9afbeb71219925d54b72b0170b2e3be76bad1e28.tar.bz2
nixlib-9afbeb71219925d54b72b0170b2e3be76bad1e28.tar.lz
nixlib-9afbeb71219925d54b72b0170b2e3be76bad1e28.tar.xz
nixlib-9afbeb71219925d54b72b0170b2e3be76bad1e28.tar.zst
nixlib-9afbeb71219925d54b72b0170b2e3be76bad1e28.zip
Merge commit 'ae6bdcc53584aaf20211ce1814bea97ece08a248'
# Conflicts:
#	nixpkgs/pkgs/build-support/rust/default.nix
#	nixpkgs/pkgs/development/go-modules/generic/default.nix
Diffstat (limited to 'nixpkgs/nixos')
-rw-r--r--nixpkgs/nixos/doc/manual/installation/installing.xml3
-rw-r--r--nixpkgs/nixos/doc/manual/release-notes/rl-2003.xml73
-rw-r--r--nixpkgs/nixos/doc/manual/release-notes/rl-2009.xml22
-rw-r--r--nixpkgs/nixos/lib/eval-config.nix4
-rw-r--r--nixpkgs/nixos/lib/make-options-doc/default.nix4
-rw-r--r--nixpkgs/nixos/lib/test-driver/test-driver.py5
-rw-r--r--nixpkgs/nixos/maintainers/scripts/ec2/amazon-image.nix11
-rw-r--r--nixpkgs/nixos/modules/hardware/wooting.nix12
-rw-r--r--nixpkgs/nixos/modules/installer/tools/tools.nix8
-rw-r--r--nixpkgs/nixos/modules/misc/documentation.nix18
-rw-r--r--nixpkgs/nixos/modules/misc/nixpkgs.nix4
-rw-r--r--nixpkgs/nixos/modules/module-list.nix5
-rw-r--r--nixpkgs/nixos/modules/profiles/installation-device.nix4
-rw-r--r--nixpkgs/nixos/modules/programs/ssmtp.nix12
-rw-r--r--nixpkgs/nixos/modules/security/duosec.nix96
-rw-r--r--nixpkgs/nixos/modules/services/databases/mysql.nix17
-rw-r--r--nixpkgs/nixos/modules/services/desktops/gnome3/rygel.nix2
-rw-r--r--nixpkgs/nixos/modules/services/misc/nixos-manual.nix73
-rw-r--r--nixpkgs/nixos/modules/services/misc/rogue.nix62
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/graphite.nix137
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/netdata.nix35
-rw-r--r--nixpkgs/nixos/modules/services/networking/firewall.nix10
-rw-r--r--nixpkgs/nixos/modules/services/networking/iodine.nix163
-rw-r--r--nixpkgs/nixos/modules/services/networking/resilio.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/supplicant.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/supybot.nix109
-rw-r--r--nixpkgs/nixos/modules/services/networking/tailscale.nix46
-rw-r--r--nixpkgs/nixos/modules/services/networking/zerotierone.nix17
-rw-r--r--nixpkgs/nixos/modules/services/security/fail2ban.nix4
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/gerrit.nix218
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/nextcloud.nix44
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/nextcloud.xml48
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/kodi.nix2
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix44
-rw-r--r--nixpkgs/nixos/modules/system/activation/top-level.nix2
-rw-r--r--nixpkgs/nixos/modules/system/boot/kernel.nix265
-rw-r--r--nixpkgs/nixos/modules/system/boot/networkd.nix75
-rw-r--r--nixpkgs/nixos/modules/system/boot/stage-1.nix13
-rw-r--r--nixpkgs/nixos/release-small.nix2
-rw-r--r--nixpkgs/nixos/tests/all-tests.nix2
-rw-r--r--nixpkgs/nixos/tests/fenics.nix50
-rw-r--r--nixpkgs/nixos/tests/gerrit.nix56
-rw-r--r--nixpkgs/nixos/tests/graphite.nix18
-rw-r--r--nixpkgs/nixos/tests/installer.nix1
-rw-r--r--nixpkgs/nixos/tests/iodine.nix63
-rw-r--r--nixpkgs/nixos/tests/mongodb.nix84
-rw-r--r--nixpkgs/nixos/tests/mysql.nix27
-rw-r--r--nixpkgs/nixos/tests/networking.nix25
48 files changed, 1348 insertions, 651 deletions
diff --git a/nixpkgs/nixos/doc/manual/installation/installing.xml b/nixpkgs/nixos/doc/manual/installation/installing.xml
index 4041b4ad163a..0dbfb39c32b2 100644
--- a/nixpkgs/nixos/doc/manual/installation/installing.xml
+++ b/nixpkgs/nixos/doc/manual/installation/installing.xml
@@ -24,8 +24,7 @@
   </para>
 
   <para>
-   The NixOS manual is available on virtual console 8 (press Alt+F8 to access)
-   or by running <command>nixos-help</command>.
+   The NixOS manual is available by running <command>nixos-help</command>.
   </para>
 
   <para>
diff --git a/nixpkgs/nixos/doc/manual/release-notes/rl-2003.xml b/nixpkgs/nixos/doc/manual/release-notes/rl-2003.xml
index 20f232c9110e..7674b0a5c0de 100644
--- a/nixpkgs/nixos/doc/manual/release-notes/rl-2003.xml
+++ b/nixpkgs/nixos/doc/manual/release-notes/rl-2003.xml
@@ -235,7 +235,7 @@ services.xserver.displayManager.defaultSession = "xfce+icewm";
    <listitem>
     <para>
       The <literal>buildRustCrate</literal> infrastructure now produces <literal>lib</literal> outputs in addition to the <literal>out</literal> output.
-      This has led to drastically reduced closed sizes for some rust crates since development dependencies are now in the <literal>lib</literal> output.
+      This has led to drastically reduced closure sizes for some rust crates since development dependencies are now in the <literal>lib</literal> output.
     </para>
     </listitem>
    <listitem>
@@ -641,6 +641,62 @@ auth required pam_succeed_if.so uid >= 1000 quiet
      The previous behavior can be restored by setting <literal>config.riot-web.conf = { disable_guests = false; piwik = true; }</literal>.
     </para>
    </listitem>
+   <listitem>
+     <para>
+       Stand-alone usage of <literal>Upower</literal> now requires
+       <option>services.upower.enable</option> instead of just installing into
+       <xref linkend="opt-environment.systemPackages"/>.
+     </para>
+   </listitem>
+   <listitem>
+    <para>
+     <package>nextcloud</package> has been updated to <literal>v18.0.2</literal>. This means
+     that users from NixOS 19.09 can't upgrade directly since you can only move one version
+      forward and 19.09 uses <literal>v16.0.8</literal>.
+    </para>
+    <para>
+     To provide a safe upgrade-path and to circumvent similar issues in the future, the following
+     measures were taken:
+     <itemizedlist>
+      <listitem>
+       <para>
+        The <package>pkgs.nextcloud</package>-attribute has been removed and replaced with
+        versioned attributes (currently <package>pkgs.nextcloud17</package> and
+        <package>pkgs.nextcloud18</package>). With this change major-releases can be backported
+        without breaking stuff and to make upgrade-paths easier.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+        Existing setups will be detected using
+        <link linkend="opt-system.stateVersion">system.stateVersion</link>: by default,
+        <package>nextcloud17</package> will be used, but will raise a warning which notes
+        that after that deploy it's recommended to update to the latest stable version
+        (<package>nextcloud18</package>) by declaring the newly introduced setting
+        <link linkend="opt-services.nextcloud.package">services.nextcloud.package</link>.
+       </para>
+      </listitem>
+      <listitem>
+       <para>
+        Users with an overlay (e.g. to use <package>nextcloud</package> at version
+        <literal>v18</literal> on <literal>19.09</literal>) will get an evaluation error
+        by default. This is done to ensure that our
+        <link linkend="opt-services.nextcloud.package">package</link>-option doesn't select an
+        older version by accident. It's recommended to use <package>pkgs.nextcloud18</package>
+        or to set <link linkend="opt-services.nextcloud.package">package</link> to
+        <package>pkgs.nextcloud</package> explicitly.
+       </para>
+      </listitem>
+     </itemizedlist>
+    </para>
+    <warning>
+     <para>
+      Please note that if you're comming from <literal>19.03</literal> or older, you have
+      to manually upgrade to <literal>19.09</literal> first to upgrade your server
+      to Nextcloud v16.
+     </para>
+    </warning>
+   </listitem>
   </itemizedlist>
  </section>
 
@@ -760,7 +816,20 @@ auth required pam_succeed_if.so uid >= 1000 quiet
       </para></listitem>
      </itemizedlist>
     </para>
-   </listitem>
+  </listitem>
+  <listitem>
+   <para>
+    The <link linkend="opt-systemd.network.links">systemd.network.links</link> option is now respected
+    even when <link linkend="opt-systemd.network.enable">systemd-networkd</link> is disabled.
+    This mirrors the behaviour of systemd - It's udev that parses <literal>.link</literal> files,
+    not <command>systemd-networkd</command>.
+   </para>
+  </listitem>
+  <listitem>
+   <para>
+    <package>mongodb</package> has been updated to version <literal>3.4.24</literal>.
+   </para>
+  </listitem>
   </itemizedlist>
  </section>
 </section>
diff --git a/nixpkgs/nixos/doc/manual/release-notes/rl-2009.xml b/nixpkgs/nixos/doc/manual/release-notes/rl-2009.xml
index 72474e5dbd4a..a9a6003d1e8a 100644
--- a/nixpkgs/nixos/doc/manual/release-notes/rl-2009.xml
+++ b/nixpkgs/nixos/doc/manual/release-notes/rl-2009.xml
@@ -86,6 +86,28 @@
 }</programlisting>
     </para>
    </listitem>
+   <listitem>
+    <para>
+      The <link linkend="opt-services.supybot.enable">supybot</link> module now uses <literal>/var/lib/supybot</literal>
+      as its default <link linkend="opt-services.supybot.stateDir">stateDir</link> path if <literal>stateVersion</literal>
+      is 20.09 or higher. It also enables number of
+      <link xlink:href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Sandboxing">systemd sandboxing options</link>
+      which may possibly interfere with some plugins. If this is the case you can disable the options through attributes in
+      <option>systemd.services.supybot.serviceConfig</option>.
+    </para>
+   </listitem>
+   <listitem>
+    <para>
+      The <literal>security.duosec.skey</literal> option, which stored a secret in the
+      nix store, has been replaced by a new
+      <link linkend="opt-security.duosec.secretKeyFile">security.duosec.secretKeyFile</link>
+      option for better security.
+    </para>
+    <para>
+      <literal>security.duosec.ikey</literal> has been renamed to
+      <link linkend="opt-security.duosec.integrationKey">security.duosec.integrationKey</link>.
+    </para>
+   </listitem>
   </itemizedlist>
  </section>
 
diff --git a/nixpkgs/nixos/lib/eval-config.nix b/nixpkgs/nixos/lib/eval-config.nix
index 9892d6f160f7..c8824c2690d3 100644
--- a/nixpkgs/nixos/lib/eval-config.nix
+++ b/nixpkgs/nixos/lib/eval-config.nix
@@ -61,7 +61,7 @@ in rec {
     args = extraArgs;
     specialArgs =
       { modulesPath = builtins.toString ../modules; } // specialArgs;
-  }) config options;
+  }) config options _module;
 
   # These are the extra arguments passed to every module.  In
   # particular, Nixpkgs is passed through the "pkgs" argument.
@@ -69,5 +69,5 @@ in rec {
     inherit baseModules extraModules modules;
   };
 
-  inherit (config._module.args) pkgs;
+  inherit (_module.args) pkgs;
 }
diff --git a/nixpkgs/nixos/lib/make-options-doc/default.nix b/nixpkgs/nixos/lib/make-options-doc/default.nix
index eee8f612410d..e5813d9a3ef9 100644
--- a/nixpkgs/nixos/lib/make-options-doc/default.nix
+++ b/nixpkgs/nixos/lib/make-options-doc/default.nix
@@ -133,6 +133,7 @@ in {
 
   optionsJSON = pkgs.runCommand "options.json"
     { meta.description = "List of NixOS options in JSON format";
+      buildInputs = [ pkgs.brotli ];
     }
     ''
       # Export list of options in different format.
@@ -141,8 +142,11 @@ in {
 
       cp ${builtins.toFile "options.json" (builtins.unsafeDiscardStringContext (builtins.toJSON optionsNix))} $dst/options.json
 
+      brotli -9 < $dst/options.json > $dst/options.json.br
+
       mkdir -p $out/nix-support
       echo "file json $dst/options.json" >> $out/nix-support/hydra-build-products
+      echo "file json-br $dst/options.json.br" >> $out/nix-support/hydra-build-products
     ''; # */
 
   optionsDocBook = pkgs.runCommand "options-docbook.xml" {} ''
diff --git a/nixpkgs/nixos/lib/test-driver/test-driver.py b/nixpkgs/nixos/lib/test-driver/test-driver.py
index c27947bc610d..7825025893d3 100644
--- a/nixpkgs/nixos/lib/test-driver/test-driver.py
+++ b/nixpkgs/nixos/lib/test-driver/test-driver.py
@@ -6,6 +6,7 @@ from xml.sax.saxutils import XMLGenerator
 import _thread
 import atexit
 import base64
+import codecs
 import os
 import pathlib
 import ptpython.repl
@@ -115,6 +116,7 @@ def create_vlan(vlan_nr: str) -> Tuple[str, str, "subprocess.Popen[bytes]", Any]
     fd.write("version\n")
     # TODO: perl version checks if this can be read from
     # an if not, dies. we could hang here forever. Fix it.
+    assert vde_process.stdout is not None
     vde_process.stdout.readline()
     if not os.path.exists(os.path.join(vde_socket, "ctl")):
         raise Exception("cannot start vde_switch")
@@ -139,7 +141,7 @@ def retry(fn: Callable) -> None:
 class Logger:
     def __init__(self) -> None:
         self.logfile = os.environ.get("LOGFILE", "/dev/null")
-        self.logfile_handle = open(self.logfile, "wb")
+        self.logfile_handle = codecs.open(self.logfile, "wb")
         self.xml = XMLGenerator(self.logfile_handle, encoding="utf-8")
         self.queue: "Queue[Dict[str, str]]" = Queue(1000)
 
@@ -739,6 +741,7 @@ class Machine:
         self.shell, _ = self.shell_socket.accept()
 
         def process_serial_output() -> None:
+            assert self.process.stdout is not None
             for _line in self.process.stdout:
                 # Ignore undecodable bytes that may occur in boot menus
                 line = _line.decode(errors="ignore").replace("\r", "").rstrip()
diff --git a/nixpkgs/nixos/maintainers/scripts/ec2/amazon-image.nix b/nixpkgs/nixos/maintainers/scripts/ec2/amazon-image.nix
index 31e15537179a..36f3e7af873d 100644
--- a/nixpkgs/nixos/maintainers/scripts/ec2/amazon-image.nix
+++ b/nixpkgs/nixos/maintainers/scripts/ec2/amazon-image.nix
@@ -8,10 +8,15 @@ in {
 
   imports = [ ../../../modules/virtualisation/amazon-image.nix ];
 
-  # Required to provide good EBS experience,
+  # Amazon recomments setting this to the highest possible value for a good EBS
+  # experience, which prior to 4.15 was 255.
   # https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nvme-ebs-volumes.html#timeout-nvme-ebs-volumes
-  # TODO change value to 4294967295 when kernel is updated to 4.15 or later
-  config.boot.kernelParams = [ "nvme_core.io_timeout=255" ];
+  config.boot.kernelParams =
+    let timeout =
+      if pkgs.lib.versionAtLeast config.boot.kernelPackages.kernel.version "4.15"
+      then "4294967295"
+      else  "255";
+    in [ "nvme_core.io_timeout=${timeout}" ];
 
   options.amazonImage = {
     name = mkOption {
diff --git a/nixpkgs/nixos/modules/hardware/wooting.nix b/nixpkgs/nixos/modules/hardware/wooting.nix
new file mode 100644
index 000000000000..ee550cbbf6b8
--- /dev/null
+++ b/nixpkgs/nixos/modules/hardware/wooting.nix
@@ -0,0 +1,12 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+{
+  options.hardware.wooting.enable =
+    mkEnableOption "Enable support for Wooting keyboards";
+
+  config = mkIf config.hardware.wooting.enable {
+    environment.systemPackages = [ pkgs.wootility ];
+    services.udev.packages = [ pkgs.wooting-udev-rules ];
+  };
+}
diff --git a/nixpkgs/nixos/modules/installer/tools/tools.nix b/nixpkgs/nixos/modules/installer/tools/tools.nix
index 833865e99bb3..655d77db157d 100644
--- a/nixpkgs/nixos/modules/installer/tools/tools.nix
+++ b/nixpkgs/nixos/modules/installer/tools/tools.nix
@@ -42,7 +42,10 @@ let
     inherit (config.system.nixos-generate-config) configuration;
   };
 
-  nixos-option = pkgs.callPackage ./nixos-option { };
+  nixos-option =
+    if lib.versionAtLeast (lib.getVersion pkgs.nix) "2.4pre"
+    then null
+    else pkgs.callPackage ./nixos-option { };
 
   nixos-version = makeProg {
     name = "nixos-version";
@@ -184,10 +187,9 @@ in
         nixos-install
         nixos-rebuild
         nixos-generate-config
-        nixos-option
         nixos-version
         nixos-enter
-      ];
+      ] ++ lib.optional (nixos-option != null) nixos-option;
 
     system.build = {
       inherit nixos-install nixos-generate-config nixos-option nixos-rebuild nixos-enter;
diff --git a/nixpkgs/nixos/modules/misc/documentation.nix b/nixpkgs/nixos/modules/misc/documentation.nix
index d09afadd6097..7ad4be9a02e6 100644
--- a/nixpkgs/nixos/modules/misc/documentation.nix
+++ b/nixpkgs/nixos/modules/misc/documentation.nix
@@ -17,6 +17,7 @@ let
     inherit pkgs config;
     version = config.system.nixos.release;
     revision = "release-${version}";
+    extraSources = cfg.nixos.extraModuleSources;
     options =
       let
         scrubbedEval = evalModules {
@@ -163,6 +164,19 @@ in
         '';
       };
 
+      nixos.extraModuleSources = mkOption {
+        type = types.listOf (types.either types.path types.str);
+        default = [ ];
+        description = ''
+          Which extra NixOS module paths the generated NixOS's documentation should strip
+          from options.
+        '';
+        example = literalExample ''
+          # e.g. with options from modules in ''${pkgs.customModules}/nix:
+          [ pkgs.customModules ]
+        '';
+      };
+
     };
 
   };
@@ -204,9 +218,7 @@ in
            ++ optionals config.services.xserver.enable [ desktopItem pkgs.nixos-icons ]);
 
       services.mingetty.helpLine = mkIf cfg.doc.enable (
-          "\nRun `nixos-help` "
-        + optionalString config.services.nixosManual.showManual "or press <Alt-F${toString config.services.nixosManual.ttyNumber}> "
-        + "for the NixOS manual."
+          "\nRun 'nixos-help' for the NixOS manual."
       );
     })
 
diff --git a/nixpkgs/nixos/modules/misc/nixpkgs.nix b/nixpkgs/nixos/modules/misc/nixpkgs.nix
index 011d493c1538..4f5a9250eaae 100644
--- a/nixpkgs/nixos/modules/misc/nixpkgs.nix
+++ b/nixpkgs/nixos/modules/misc/nixpkgs.nix
@@ -236,8 +236,8 @@ in
         let
           nixosExpectedSystem =
             if config.nixpkgs.crossSystem != null
-            then config.nixpkgs.crossSystem.system
-            else config.nixpkgs.localSystem.system;
+            then config.nixpkgs.crossSystem.system or (lib.systems.parse.doubleFromSystem (lib.systems.parse.mkSystemFromString config.nixpkgs.crossSystem.config))
+            else config.nixpkgs.localSystem.system or (lib.systems.parse.doubleFromSystem (lib.systems.parse.mkSystemFromString config.nixpkgs.localSystem.config));
           nixosOption =
             if config.nixpkgs.crossSystem != null
             then "nixpkgs.crossSystem"
diff --git a/nixpkgs/nixos/modules/module-list.nix b/nixpkgs/nixos/modules/module-list.nix
index 55d440434344..be52b56d054b 100644
--- a/nixpkgs/nixos/modules/module-list.nix
+++ b/nixpkgs/nixos/modules/module-list.nix
@@ -64,6 +64,7 @@
   ./hardware/tuxedo-keyboard.nix
   ./hardware/usb-wwan.nix
   ./hardware/onlykey.nix
+  ./hardware/wooting.nix
   ./hardware/video/amdgpu.nix
   ./hardware/video/amdgpu-pro.nix
   ./hardware/video/ati.nix
@@ -470,7 +471,6 @@
   ./services/misc/nix-daemon.nix
   ./services/misc/nix-gc.nix
   ./services/misc/nix-optimise.nix
-  ./services/misc/nixos-manual.nix
   ./services/misc/nix-ssh-serve.nix
   ./services/misc/novacomd.nix
   ./services/misc/nzbget.nix
@@ -486,7 +486,6 @@
   ./services/misc/redmine.nix
   ./services/misc/rippled.nix
   ./services/misc/ripple-data-api.nix
-  ./services/misc/rogue.nix
   ./services/misc/serviio.nix
   ./services/misc/safeeyes.nix
   ./services/misc/sickbeard.nix
@@ -730,6 +729,7 @@
   ./services/networking/syncthing.nix
   ./services/networking/syncthing-relay.nix
   ./services/networking/syncplay.nix
+  ./services/networking/tailscale.nix
   ./services/networking/tcpcrypt.nix
   ./services/networking/teamspeak3.nix
   ./services/networking/tedicross.nix
@@ -823,6 +823,7 @@
   ./services/web-apps/documize.nix
   ./services/web-apps/dokuwiki.nix
   ./services/web-apps/frab.nix
+  ./services/web-apps/gerrit.nix
   ./services/web-apps/gotify-server.nix
   ./services/web-apps/grocy.nix
   ./services/web-apps/icingaweb2/icingaweb2.nix
diff --git a/nixpkgs/nixos/modules/profiles/installation-device.nix b/nixpkgs/nixos/modules/profiles/installation-device.nix
index 4596e163404c..d05c0c50e82c 100644
--- a/nixpkgs/nixos/modules/profiles/installation-device.nix
+++ b/nixpkgs/nixos/modules/profiles/installation-device.nix
@@ -26,10 +26,6 @@ with lib;
 
     # Show the manual.
     documentation.nixos.enable = mkForce true;
-    services.nixosManual.showManual = true;
-
-    # Let the user play Rogue on TTY 8 during the installation.
-    #services.rogue.enable = true;
 
     # Use less privileged nixos user
     users.users.nixos = {
diff --git a/nixpkgs/nixos/modules/programs/ssmtp.nix b/nixpkgs/nixos/modules/programs/ssmtp.nix
index f794eac8af00..c7a947393496 100644
--- a/nixpkgs/nixos/modules/programs/ssmtp.nix
+++ b/nixpkgs/nixos/modules/programs/ssmtp.nix
@@ -14,8 +14,16 @@ in
 {
 
   imports = [
-    (mkRenamedOptionModule [ "networking" "defaultMailServer" ] [ "services" "ssmtp" ])
-    (mkRenamedOptionModule [ "services" "ssmtp" "directDelivery" ] [ "services" "ssmtp" "enable" ])
+    (mkRenamedOptionModule [ "networking" "defaultMailServer" "directDelivery" ] [ "services" "ssmtp" "enable" ])
+    (mkRenamedOptionModule [ "networking" "defaultMailServer" "hostName" ] [ "services" "ssmtp" "hostName" ])
+    (mkRenamedOptionModule [ "networking" "defaultMailServer" "domain" ] [ "services" "ssmtp" "domain" ])
+    (mkRenamedOptionModule [ "networking" "defaultMailServer" "root" ] [ "services" "ssmtp" "root" ])
+    (mkRenamedOptionModule [ "networking" "defaultMailServer" "useTLS" ] [ "services" "ssmtp" "useTLS" ])
+    (mkRenamedOptionModule [ "networking" "defaultMailServer" "useSTARTTLS" ] [ "services" "ssmtp" "useSTARTTLS" ])
+    (mkRenamedOptionModule [ "networking" "defaultMailServer" "authUser" ] [ "services" "ssmtp" "authUser" ])
+    (mkRenamedOptionModule [ "networking" "defaultMailServer" "authPass" ] [ "services" "ssmtp" "authPass" ])
+    (mkRenamedOptionModule [ "networking" "defaultMailServer" "authPassFile" ] [ "services" "ssmtp" "authPassFile" ])
+    (mkRenamedOptionModule [ "networking" "defaultMailServer" "setSendmail" ] [ "services" "ssmtp" "setSendmail" ])
   ];
 
   options = {
diff --git a/nixpkgs/nixos/modules/security/duosec.nix b/nixpkgs/nixos/modules/security/duosec.nix
index c686a6861d0f..71428b82f5da 100644
--- a/nixpkgs/nixos/modules/security/duosec.nix
+++ b/nixpkgs/nixos/modules/security/duosec.nix
@@ -9,8 +9,7 @@ let
 
   configFilePam = ''
     [duo]
-    ikey=${cfg.ikey}
-    skey=${cfg.skey}
+    ikey=${cfg.integrationKey}
     host=${cfg.host}
     ${optionalString (cfg.groups != "") ("groups="+cfg.groups)}
     failmode=${cfg.failmode}
@@ -24,26 +23,12 @@ let
     motd=${boolToStr cfg.motd}
     accept_env_factor=${boolToStr cfg.acceptEnvFactor}
   '';
-
-  loginCfgFile = optionalAttrs cfg.ssh.enable {
-    "duo/login_duo.conf" =
-      { source = pkgs.writeText "login_duo.conf" configFileLogin;
-        mode   = "0600";
-        user   = "sshd";
-      };
-  };
-
-  pamCfgFile = optional cfg.pam.enable {
-    "duo/pam_duo.conf" =
-      { source = pkgs.writeText "pam_duo.conf" configFilePam;
-        mode   = "0600";
-        user   = "sshd";
-      };
-  };
 in
 {
   imports = [
     (mkRenamedOptionModule [ "security" "duosec" "group" ] [ "security" "duosec" "groups" ])
+    (mkRenamedOptionModule [ "security" "duosec" "ikey" ] [ "security" "duosec" "integrationKey" ])
+    (mkRemovedOptionModule [ "security" "duosec" "skey" ] "The insecure security.duosec.skey option has been replaced by a new security.duosec.secretKeyFile option. Use this new option to store a secure copy of your key instead.")
   ];
 
   options = {
@@ -60,14 +45,18 @@ in
         description = "If enabled, protect logins with Duo Security using PAM support.";
       };
 
-      ikey = mkOption {
+      integrationKey = mkOption {
         type = types.str;
         description = "Integration key.";
       };
 
-      skey = mkOption {
-        type = types.str;
-        description = "Secret key.";
+      secretKeyFile = mkOption {
+        type = types.path;
+        default = null;
+        description = ''
+          A file containing your secret key. The security of your Duo application is tied to the security of your secret key.
+        '';
+        example = "/run/keys/duo-skey";
       };
 
       host = mkOption {
@@ -195,21 +184,52 @@ in
   };
 
   config = mkIf (cfg.ssh.enable || cfg.pam.enable) {
-     environment.systemPackages = [ pkgs.duo-unix ];
-
-     security.wrappers.login_duo.source = "${pkgs.duo-unix.out}/bin/login_duo";
-     environment.etc = loginCfgFile // pamCfgFile;
-
-     /* If PAM *and* SSH are enabled, then don't do anything special.
-     If PAM isn't used, set the default SSH-only options. */
-     services.openssh.extraConfig = mkIf (cfg.ssh.enable || cfg.pam.enable) (
-     if cfg.pam.enable then "UseDNS no" else ''
-       # Duo Security configuration
-       ForceCommand ${config.security.wrapperDir}/login_duo
-       PermitTunnel no
-       ${optionalString (!cfg.allowTcpForwarding) ''
-         AllowTcpForwarding no
-       ''}
-     '');
+    environment.systemPackages = [ pkgs.duo-unix ];
+
+    security.wrappers.login_duo.source = "${pkgs.duo-unix.out}/bin/login_duo";
+
+    system.activationScripts = {
+      login_duo = mkIf cfg.ssh.enable ''
+        if test -f "${cfg.secretKeyFile}"; then
+          mkdir -m 0755 -p /etc/duo
+
+          umask 0077
+          conf="$(mktemp)"
+          {
+            cat ${pkgs.writeText "login_duo.conf" configFileLogin}
+            printf 'skey = %s\n' "$(cat ${cfg.secretKeyFile})"
+          } >"$conf"
+
+          chown sshd "$conf"
+          mv -fT "$conf" /etc/duo/login_duo.conf
+        fi
+      '';
+      pam_duo = mkIf cfg.pam.enable ''
+        if test -f "${cfg.secretKeyFile}"; then
+          mkdir -m 0755 -p /etc/duo
+
+          umask 0077
+          conf="$(mktemp)"
+          {
+            cat ${pkgs.writeText "login_duo.conf" configFilePam}
+            printf 'skey = %s\n' "$(cat ${cfg.secretKeyFile})"
+          } >"$conf"
+
+          mv -fT "$conf" /etc/duo/pam_duo.conf
+        fi
+      '';
+    };
+
+    /* If PAM *and* SSH are enabled, then don't do anything special.
+    If PAM isn't used, set the default SSH-only options. */
+    services.openssh.extraConfig = mkIf (cfg.ssh.enable || cfg.pam.enable) (
+    if cfg.pam.enable then "UseDNS no" else ''
+      # Duo Security configuration
+      ForceCommand ${config.security.wrapperDir}/login_duo
+      PermitTunnel no
+      ${optionalString (!cfg.allowTcpForwarding) ''
+        AllowTcpForwarding no
+      ''}
+    '');
   };
 }
diff --git a/nixpkgs/nixos/modules/services/databases/mysql.nix b/nixpkgs/nixos/modules/services/databases/mysql.nix
index 248bf0ebc915..f9e657f57742 100644
--- a/nixpkgs/nixos/modules/services/databases/mysql.nix
+++ b/nixpkgs/nixos/modules/services/databases/mysql.nix
@@ -10,16 +10,8 @@ let
 
   isMariaDB = lib.getName mysql == lib.getName pkgs.mariadb;
 
-  isMysqlAtLeast57 =
-    (lib.getName mysql == lib.getName pkgs.mysql57)
-     && (builtins.compareVersions mysql.version "5.7" >= 0);
-
   mysqldOptions =
     "--user=${cfg.user} --datadir=${cfg.dataDir} --basedir=${mysql}";
-  # For MySQL 5.7+, --insecure creates the root user without password
-  # (earlier versions and MariaDB do this by default).
-  installOptions =
-    "${mysqldOptions} ${lib.optionalString isMysqlAtLeast57 "--insecure"}";
 
   settingsFile = pkgs.writeText "my.cnf" (
     generators.toINI { listsAsDuplicateKeys = true; } cfg.settings +
@@ -366,9 +358,14 @@ in
           pkgs.nettools
         ];
 
-        preStart = ''
+        preStart = if isMariaDB then ''
+          if ! test -e ${cfg.dataDir}/mysql; then
+            ${mysql}/bin/mysql_install_db --defaults-file=/etc/my.cnf ${mysqldOptions}
+            touch /tmp/mysql_init
+          fi
+        '' else ''
           if ! test -e ${cfg.dataDir}/mysql; then
-            ${mysql}/bin/mysql_install_db --defaults-file=/etc/my.cnf ${installOptions}
+            ${mysql}/bin/mysqld --defaults-file=/etc/my.cnf ${mysqldOptions} --initialize-insecure
             touch /tmp/mysql_init
           fi
         '';
diff --git a/nixpkgs/nixos/modules/services/desktops/gnome3/rygel.nix b/nixpkgs/nixos/modules/services/desktops/gnome3/rygel.nix
index 55d5e703aa19..dfe4333a8adb 100644
--- a/nixpkgs/nixos/modules/services/desktops/gnome3/rygel.nix
+++ b/nixpkgs/nixos/modules/services/desktops/gnome3/rygel.nix
@@ -26,5 +26,7 @@ with lib;
     services.dbus.packages = [ pkgs.gnome3.rygel ];
 
     systemd.packages = [ pkgs.gnome3.rygel ];
+
+    environment.etc."rygel.conf".source = "${pkgs.gnome3.rygel}/etc/rygel.conf";
   };
 }
diff --git a/nixpkgs/nixos/modules/services/misc/nixos-manual.nix b/nixpkgs/nixos/modules/services/misc/nixos-manual.nix
deleted file mode 100644
index ab73f49d4be5..000000000000
--- a/nixpkgs/nixos/modules/services/misc/nixos-manual.nix
+++ /dev/null
@@ -1,73 +0,0 @@
-# This module optionally starts a browser that shows the NixOS manual
-# on one of the virtual consoles which is useful for the installation
-# CD.
-
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-  cfg = config.services.nixosManual;
-  cfgd = config.documentation;
-in
-
-{
-
-  options = {
-
-    # TODO(@oxij): rename this to `.enable` eventually.
-    services.nixosManual.showManual = mkOption {
-      type = types.bool;
-      default = false;
-      description = ''
-        Whether to show the NixOS manual on one of the virtual
-        consoles.
-      '';
-    };
-
-    services.nixosManual.ttyNumber = mkOption {
-      type = types.int;
-      default = 8;
-      description = ''
-        Virtual console on which to show the manual.
-      '';
-    };
-
-    services.nixosManual.browser = mkOption {
-      type = types.path;
-      default = "${pkgs.w3m-nographics}/bin/w3m";
-      description = ''
-        Browser used to show the manual.
-      '';
-    };
-
-  };
-
-
-  config = mkMerge [
-    (mkIf cfg.showManual {
-      assertions = singleton {
-        assertion = cfgd.enable && cfgd.nixos.enable;
-        message   = "Can't enable `services.nixosManual.showManual` without `documentation.nixos.enable`";
-      };
-    })
-    (mkIf (cfg.showManual && cfgd.enable && cfgd.nixos.enable) {
-      console.extraTTYs = [ "tty${toString cfg.ttyNumber}" ];
-
-      systemd.services.nixos-manual = {
-        description = "NixOS Manual";
-        wantedBy = [ "multi-user.target" ];
-        serviceConfig = {
-          ExecStart = "${cfg.browser} ${config.system.build.manual.manualHTMLIndex}";
-          StandardInput = "tty";
-          StandardOutput = "tty";
-          TTYPath = "/dev/tty${toString cfg.ttyNumber}";
-          TTYReset = true;
-          TTYVTDisallocate = true;
-          Restart = "always";
-        };
-      };
-    })
-  ];
-
-}
diff --git a/nixpkgs/nixos/modules/services/misc/rogue.nix b/nixpkgs/nixos/modules/services/misc/rogue.nix
deleted file mode 100644
index d56d103b5f34..000000000000
--- a/nixpkgs/nixos/modules/services/misc/rogue.nix
+++ /dev/null
@@ -1,62 +0,0 @@
-# Execute the game `rogue' on tty 9.  Mostly used by the NixOS
-# installation CD.
-
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-
-  cfg = config.services.rogue;
-
-in
-
-{
-  ###### interface
-
-  options = {
-
-    services.rogue.enable = mkOption {
-      type = types.bool;
-      default = false;
-      description = ''
-        Whether to enable the Rogue game on one of the virtual
-        consoles.
-      '';
-    };
-
-    services.rogue.tty = mkOption {
-      type = types.str;
-      default = "tty9";
-      description = ''
-        Virtual console on which to run Rogue.
-      '';
-    };
-
-  };
-
-
-  ###### implementation
-
-  config = mkIf cfg.enable {
-
-    console.extraTTYs = [ cfg.tty ];
-
-    systemd.services.rogue =
-      { description = "Rogue dungeon crawling game";
-        wantedBy = [ "multi-user.target" ];
-        serviceConfig =
-          { ExecStart = "${pkgs.rogue}/bin/rogue";
-            StandardInput = "tty";
-            StandardOutput = "tty";
-            TTYPath = "/dev/${cfg.tty}";
-            TTYReset = true;
-            TTYVTDisallocate = true;
-            WorkingDirectory = "/tmp";
-            Restart = "always";
-          };
-      };
-
-  };
-
-}
diff --git a/nixpkgs/nixos/modules/services/monitoring/graphite.nix b/nixpkgs/nixos/modules/services/monitoring/graphite.nix
index dd147bb37930..64d9d61950da 100644
--- a/nixpkgs/nixos/modules/services/monitoring/graphite.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/graphite.nix
@@ -39,8 +39,6 @@ let
     GRAPHITE_URL = cfg.seyren.graphiteUrl;
   } // cfg.seyren.extraConfig;
 
-  pagerConfig = pkgs.writeText "alarms.yaml" cfg.pager.alerts;
-
   configDir = pkgs.buildEnv {
     name = "graphite-config";
     paths = lists.filter (el: el != null) [
@@ -61,12 +59,10 @@ let
 
   carbonEnv = {
     PYTHONPATH = let
-      cenv = pkgs.python.buildEnv.override {
-        extraLibs = [ pkgs.python27Packages.carbon ];
+      cenv = pkgs.python3.buildEnv.override {
+        extraLibs = [ pkgs.python3Packages.carbon ];
       };
-      cenvPack =  "${cenv}/${pkgs.python.sitePackages}";
-    # opt/graphite/lib contains twisted.plugins.carbon-cache
-    in "${cenvPack}/opt/graphite/lib:${cenvPack}";
+    in "${cenv}/${pkgs.python3.sitePackages}";
     GRAPHITE_ROOT = dataDir;
     GRAPHITE_CONF_DIR = configDir;
     GRAPHITE_STORAGE_DIR = dataDir;
@@ -74,6 +70,10 @@ let
 
 in {
 
+  imports = [
+    (mkRemovedOptionModule ["services" "graphite" "pager"] "")
+  ];
+
   ###### interface
 
   options.services.graphite = {
@@ -132,7 +132,7 @@ in {
       finders = mkOption {
         description = "List of finder plugins to load.";
         default = [];
-        example = literalExample "[ pkgs.python27Packages.influxgraph ]";
+        example = literalExample "[ pkgs.python3Packages.influxgraph ]";
         type = types.listOf types.package;
       };
 
@@ -159,8 +159,8 @@ in {
 
       package = mkOption {
         description = "Package to use for graphite api.";
-        default = pkgs.python27Packages.graphite_api;
-        defaultText = "pkgs.python27Packages.graphite_api";
+        default = pkgs.python3Packages.graphite_api;
+        defaultText = "pkgs.python3Packages.graphite_api";
         type = types.package;
       };
 
@@ -344,49 +344,6 @@ in {
       };
     };
 
-    pager = {
-      enable = mkOption {
-        description = ''
-          Whether to enable graphite-pager service. For more information visit
-          <link xlink:href="https://github.com/seatgeek/graphite-pager"/>
-        '';
-        default = false;
-        type = types.bool;
-      };
-
-      redisUrl = mkOption {
-        description = "Redis connection string.";
-        default = "redis://localhost:${toString config.services.redis.port}/";
-        type = types.str;
-      };
-
-      graphiteUrl = mkOption {
-        description = "URL to your graphite service.";
-        default = "http://${cfg.web.listenAddress}:${toString cfg.web.port}";
-        type = types.str;
-      };
-
-      alerts = mkOption {
-        description = "Alerts configuration for graphite-pager.";
-        default = ''
-          alerts:
-            - target: constantLine(100)
-              warning: 90
-              critical: 200
-              name: Test
-        '';
-        example = ''
-          pushbullet_key: pushbullet_api_key
-          alerts:
-            - target: stats.seatgeek.app.deal_quality.venue_info_cache.hit
-              warning: .5
-              critical: 1
-              name: Deal quality venue cache hits
-        '';
-        type = types.lines;
-      };
-    };
-
     beacon = {
       enable = mkEnableOption "graphite beacon";
 
@@ -409,7 +366,7 @@ in {
         environment = carbonEnv;
         serviceConfig = {
           RuntimeDirectory = name;
-          ExecStart = "${pkgs.pythonPackages.twisted}/bin/twistd ${carbonOpts name}";
+          ExecStart = "${pkgs.python3Packages.twisted}/bin/twistd ${carbonOpts name}";
           User = "graphite";
           Group = "graphite";
           PermissionsStartOnly = true;
@@ -431,7 +388,7 @@ in {
         environment = carbonEnv;
         serviceConfig = {
           RuntimeDirectory = name;
-          ExecStart = "${pkgs.pythonPackages.twisted}/bin/twistd ${carbonOpts name}";
+          ExecStart = "${pkgs.python3Packages.twisted}/bin/twistd ${carbonOpts name}";
           User = "graphite";
           Group = "graphite";
           PIDFile="/run/${name}/${name}.pid";
@@ -447,7 +404,7 @@ in {
         environment = carbonEnv;
         serviceConfig = {
           RuntimeDirectory = name;
-          ExecStart = "${pkgs.pythonPackages.twisted}/bin/twistd ${carbonOpts name}";
+          ExecStart = "${pkgs.python3Packages.twisted}/bin/twistd ${carbonOpts name}";
           User = "graphite";
           Group = "graphite";
           PIDFile="/run/${name}/${name}.pid";
@@ -457,19 +414,11 @@ in {
 
     (mkIf (cfg.carbon.enableCache || cfg.carbon.enableAggregator || cfg.carbon.enableRelay) {
       environment.systemPackages = [
-        pkgs.pythonPackages.carbon
+        pkgs.python3Packages.carbon
       ];
     })
 
-    (mkIf cfg.web.enable (let
-      python27' = pkgs.python27.override {
-        packageOverrides = self: super: {
-          django = self.django_1_8;
-          django_tagging = self.django_tagging_0_4_3;
-        };
-      };
-      pythonPackages = python27'.pkgs;
-    in {
+    (mkIf cfg.web.enable ({
       systemd.services.graphiteWeb = {
         description = "Graphite Web Interface";
         wantedBy = [ "multi-user.target" ];
@@ -477,28 +426,27 @@ in {
         path = [ pkgs.perl ];
         environment = {
           PYTHONPATH = let
-              penv = pkgs.python.buildEnv.override {
+              penv = pkgs.python3.buildEnv.override {
                 extraLibs = [
-                  pythonPackages.graphite-web
-                  pythonPackages.pysqlite
+                  pkgs.python3Packages.graphite-web
                 ];
               };
-              penvPack = "${penv}/${pkgs.python.sitePackages}";
+              penvPack = "${penv}/${pkgs.python3.sitePackages}";
             in concatStringsSep ":" [
                  "${graphiteLocalSettingsDir}"
-                 "${penvPack}/opt/graphite/webapp"
                  "${penvPack}"
                  # explicitly adding pycairo in path because it cannot be imported via buildEnv
-                 "${pkgs.pythonPackages.pycairo}/${pkgs.python.sitePackages}"
+                 "${pkgs.python3Packages.pycairo}/${pkgs.python3.sitePackages}"
                ];
           DJANGO_SETTINGS_MODULE = "graphite.settings";
+          GRAPHITE_SETTINGS_MODULE = "graphite_local_settings";
           GRAPHITE_CONF_DIR = configDir;
           GRAPHITE_STORAGE_DIR = dataDir;
           LD_LIBRARY_PATH = "${pkgs.cairo.out}/lib";
         };
         serviceConfig = {
           ExecStart = ''
-            ${pkgs.python27Packages.waitress-django}/bin/waitress-serve-django \
+            ${pkgs.python3Packages.waitress-django}/bin/waitress-serve-django \
               --host=${cfg.web.listenAddress} --port=${toString cfg.web.port}
           '';
           User = "graphite";
@@ -510,7 +458,7 @@ in {
             mkdir -p ${dataDir}/{whisper/,log/webapp/}
             chmod 0700 ${dataDir}/{whisper/,log/webapp/}
 
-            ${pkgs.pythonPackages.django_1_8}/bin/django-admin.py migrate --noinput
+            ${pkgs.python3Packages.django}/bin/django-admin.py migrate --noinput
 
             chown -R graphite:graphite ${dataDir}
 
@@ -518,16 +466,16 @@ in {
           fi
 
           # Only collect static files when graphite_web changes.
-          if ! [ "${dataDir}/current_graphite_web" -ef "${pythonPackages.graphite-web}" ]; then
+          if ! [ "${dataDir}/current_graphite_web" -ef "${pkgs.python3Packages.graphite-web}" ]; then
             mkdir -p ${staticDir}
-            ${pkgs.pythonPackages.django_1_8}/bin/django-admin.py collectstatic  --noinput --clear
+            ${pkgs.python3Packages.django}/bin/django-admin.py collectstatic  --noinput --clear
             chown -R graphite:graphite ${staticDir}
-            ln -sfT "${pythonPackages.graphite-web}" "${dataDir}/current_graphite_web"
+            ln -sfT "${pkgs.python3Packages.graphite-web}" "${dataDir}/current_graphite_web"
           fi
         '';
       };
 
-      environment.systemPackages = [ pythonPackages.graphite-web ];
+      environment.systemPackages = [ pkgs.python3Packages.graphite-web ];
     }))
 
     (mkIf cfg.api.enable {
@@ -537,16 +485,16 @@ in {
         after = [ "network.target" ];
         environment = {
           PYTHONPATH = let
-              aenv = pkgs.python.buildEnv.override {
-                extraLibs = [ cfg.api.package pkgs.cairo pkgs.pythonPackages.cffi ] ++ cfg.api.finders;
+              aenv = pkgs.python3.buildEnv.override {
+                extraLibs = [ cfg.api.package pkgs.cairo pkgs.python3Packages.cffi ] ++ cfg.api.finders;
               };
-            in "${aenv}/${pkgs.python.sitePackages}";
+            in "${aenv}/${pkgs.python3.sitePackages}";
           GRAPHITE_API_CONFIG = graphiteApiConfig;
           LD_LIBRARY_PATH = "${pkgs.cairo.out}/lib";
         };
         serviceConfig = {
           ExecStart = ''
-            ${pkgs.python27Packages.waitress}/bin/waitress-serve \
+            ${pkgs.python3Packages.waitress}/bin/waitress-serve \
             --host=${cfg.api.listenAddress} --port=${toString cfg.api.port} \
             graphite_api.app:app
           '';
@@ -591,34 +539,13 @@ in {
       services.mongodb.enable = mkDefault true;
     })
 
-    (mkIf cfg.pager.enable {
-      systemd.services.graphitePager = {
-        description = "Graphite Pager Alerting Daemon";
-        wantedBy = [ "multi-user.target" ];
-        after = [ "network.target" "redis.service" ];
-        environment = {
-          REDIS_URL = cfg.pager.redisUrl;
-          GRAPHITE_URL = cfg.pager.graphiteUrl;
-        };
-        serviceConfig = {
-          ExecStart = "${pkgs.pythonPackages.graphitepager}/bin/graphite-pager --config ${pagerConfig}";
-          User = "graphite";
-          Group = "graphite";
-        };
-      };
-
-      services.redis.enable = mkDefault true;
-
-      environment.systemPackages = [ pkgs.pythonPackages.graphitepager ];
-    })
-
     (mkIf cfg.beacon.enable {
       systemd.services.graphite-beacon = {
         description = "Grpahite Beacon Alerting Daemon";
         wantedBy = [ "multi-user.target" ];
         serviceConfig = {
           ExecStart = ''
-            ${pkgs.pythonPackages.graphite_beacon}/bin/graphite-beacon \
+            ${pkgs.python3Packages.graphite_beacon}/bin/graphite-beacon \
               --config=${pkgs.writeText "graphite-beacon.json" (builtins.toJSON cfg.beacon.config)}
           '';
           User = "graphite";
@@ -630,7 +557,7 @@ in {
     (mkIf (
       cfg.carbon.enableCache || cfg.carbon.enableAggregator || cfg.carbon.enableRelay ||
       cfg.web.enable || cfg.api.enable ||
-      cfg.seyren.enable || cfg.pager.enable || cfg.beacon.enable
+      cfg.seyren.enable || cfg.beacon.enable
      ) {
       users.users.graphite = {
         uid = config.ids.uids.graphite;
diff --git a/nixpkgs/nixos/modules/services/monitoring/netdata.nix b/nixpkgs/nixos/modules/services/monitoring/netdata.nix
index f8225af20428..e43241eea894 100644
--- a/nixpkgs/nixos/modules/services/monitoring/netdata.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/netdata.nix
@@ -9,10 +9,12 @@ let
     mkdir -p $out/libexec/netdata/plugins.d
     ln -s /run/wrappers/bin/apps.plugin $out/libexec/netdata/plugins.d/apps.plugin
     ln -s /run/wrappers/bin/freeipmi.plugin $out/libexec/netdata/plugins.d/freeipmi.plugin
+    ln -s /run/wrappers/bin/perf.plugin $out/libexec/netdata/plugins.d/perf.plugin
+    ln -s /run/wrappers/bin/slabinfo.plugin $out/libexec/netdata/plugins.d/slabinfo.plugin
   '';
 
   plugins = [
-    "${pkgs.netdata}/libexec/netdata/plugins.d"
+    "${cfg.package}/libexec/netdata/plugins.d"
     "${wrappedPlugins}/libexec/netdata/plugins.d"
   ] ++ cfg.extraPluginPaths;
 
@@ -35,6 +37,13 @@ in {
     services.netdata = {
       enable = mkEnableOption "netdata";
 
+      package = mkOption {
+        type = types.package;
+        default = pkgs.netdata;
+        defaultText = "pkgs.netdata";
+        description = "Netdata package to use.";
+      };
+
       user = mkOption {
         type = types.str;
         default = "netdata";
@@ -141,8 +150,8 @@ in {
       path = (with pkgs; [ curl gawk which ]) ++ lib.optional cfg.python.enable
         (pkgs.python3.withPackages cfg.python.extraPackages);
       serviceConfig = {
-        Environment="PYTHONPATH=${pkgs.netdata}/libexec/netdata/python.d/python_modules";
-        ExecStart = "${pkgs.netdata}/bin/netdata -P /run/netdata/netdata.pid -D -c ${configFile}";
+        Environment="PYTHONPATH=${cfg.package}/libexec/netdata/python.d/python_modules";
+        ExecStart = "${cfg.package}/bin/netdata -P /run/netdata/netdata.pid -D -c ${configFile}";
         ExecReload = "${pkgs.utillinux}/bin/kill -s HUP -s USR1 -s USR2 $MAINPID";
         TimeoutStopSec = 60;
         # User and group
@@ -159,7 +168,7 @@ in {
     systemd.enableCgroupAccounting = true;
 
     security.wrappers."apps.plugin" = {
-      source = "${pkgs.netdata}/libexec/netdata/plugins.d/apps.plugin.org";
+      source = "${cfg.package}/libexec/netdata/plugins.d/apps.plugin.org";
       capabilities = "cap_dac_read_search,cap_sys_ptrace+ep";
       owner = cfg.user;
       group = cfg.group;
@@ -167,13 +176,29 @@ in {
     };
 
     security.wrappers."freeipmi.plugin" = {
-      source = "${pkgs.netdata}/libexec/netdata/plugins.d/freeipmi.plugin.org";
+      source = "${cfg.package}/libexec/netdata/plugins.d/freeipmi.plugin.org";
       capabilities = "cap_dac_override,cap_fowner+ep";
       owner = cfg.user;
       group = cfg.group;
       permissions = "u+rx,g+rx,o-rwx";
     };
 
+    security.wrappers."perf.plugin" = {
+      source = "${cfg.package}/libexec/netdata/plugins.d/perf.plugin.org";
+      capabilities = "cap_sys_admin+ep";
+      owner = cfg.user;
+      group = cfg.group;
+      permissions = "u+rx,g+rx,o-rx";
+    };
+
+    security.wrappers."slabinfo.plugin" = {
+      source = "${cfg.package}/libexec/netdata/plugins.d/slabinfo.plugin.org";
+      capabilities = "cap_dac_override+ep";
+      owner = cfg.user;
+      group = cfg.group;
+      permissions = "u+rx,g+rx,o-rx";
+    };
+
     security.pam.loginLimits = [
       { domain = "netdata"; type = "soft"; item = "nofile"; value = "10000"; }
       { domain = "netdata"; type = "hard"; item = "nofile"; value = "30000"; }
diff --git a/nixpkgs/nixos/modules/services/networking/firewall.nix b/nixpkgs/nixos/modules/services/networking/firewall.nix
index b0045ff795e3..cdc3a172ea70 100644
--- a/nixpkgs/nixos/modules/services/networking/firewall.nix
+++ b/nixpkgs/nixos/modules/services/networking/firewall.nix
@@ -546,9 +546,13 @@ in
       options nf_conntrack nf_conntrack_helper=1
     '';
 
-    assertions = [ { assertion = cfg.checkReversePath -> kernelHasRPFilter;
-                     message = "This kernel does not support rpfilter"; }
-                 ];
+    assertions = [
+      # This is approximately "checkReversePath -> kernelHasRPFilter",
+      # but the checkReversePath option can include non-boolean
+      # values.
+      { assertion = cfg.checkReversePath == false || kernelHasRPFilter;
+        message = "This kernel does not support rpfilter"; }
+    ];
 
     systemd.services.firewall = {
       description = "Firewall";
diff --git a/nixpkgs/nixos/modules/services/networking/iodine.nix b/nixpkgs/nixos/modules/services/networking/iodine.nix
index f9ca26c27960..46051d7044b5 100644
--- a/nixpkgs/nixos/modules/services/networking/iodine.nix
+++ b/nixpkgs/nixos/modules/services/networking/iodine.nix
@@ -9,6 +9,8 @@ let
 
   iodinedUser = "iodined";
 
+  /* is this path made unreadable by ProtectHome = true ? */
+  isProtected = x: hasPrefix "/root" x || hasPrefix "/home" x;
 in
 {
   imports = [
@@ -35,45 +37,48 @@ in
           corresponding attribute name.
         '';
         example = literalExample ''
-        {
-          foo = {
-            server = "tunnel.mdomain.com";
-            relay = "8.8.8.8";
-            extraConfig = "-v";
+          {
+            foo = {
+              server = "tunnel.mdomain.com";
+              relay = "8.8.8.8";
+              extraConfig = "-v";
+            }
           }
-        }
         '';
-        type = types.attrsOf (types.submodule (
-        {
-          options = {
-            server = mkOption {
-              type = types.str;
-              default = "";
-              description = "Domain or Subdomain of server running iodined";
-              example = "tunnel.mydomain.com";
-            };
-
-            relay = mkOption {
-              type = types.str;
-              default = "";
-              description = "DNS server to use as a intermediate relay to the iodined server";
-              example = "8.8.8.8";
-            };
-
-            extraConfig = mkOption {
-              type = types.str;
-              default = "";
-              description = "Additional command line parameters";
-              example = "-l 192.168.1.10 -p 23";
-            };
-
-            passwordFile = mkOption {
-              type = types.str;
-              default = "";
-              description = "File that contains password";
-            };
-          };
-        }));
+        type = types.attrsOf (
+          types.submodule (
+            {
+              options = {
+                server = mkOption {
+                  type = types.str;
+                  default = "";
+                  description = "Hostname of server running iodined";
+                  example = "tunnel.mydomain.com";
+                };
+
+                relay = mkOption {
+                  type = types.str;
+                  default = "";
+                  description = "DNS server to use as an intermediate relay to the iodined server";
+                  example = "8.8.8.8";
+                };
+
+                extraConfig = mkOption {
+                  type = types.str;
+                  default = "";
+                  description = "Additional command line parameters";
+                  example = "-l 192.168.1.10 -p 23";
+                };
+
+                passwordFile = mkOption {
+                  type = types.str;
+                  default = "";
+                  description = "Path to a file containing the password.";
+                };
+              };
+            }
+          )
+        );
       };
 
       server = {
@@ -121,31 +126,67 @@ in
     boot.kernelModules = [ "tun" ];
 
     systemd.services =
-    let
-      createIodineClientService = name: cfg:
-      {
-        description = "iodine client - ${name}";
-        after = [ "network.target" ];
-        wantedBy = [ "multi-user.target" ];
-        script = "exec ${pkgs.iodine}/bin/iodine -f -u ${iodinedUser} ${cfg.extraConfig} ${optionalString (cfg.passwordFile != "") "< \"${cfg.passwordFile}\""} ${cfg.relay} ${cfg.server}";
-        serviceConfig = {
-          RestartSec = "30s";
-          Restart = "always";
+      let
+        createIodineClientService = name: cfg:
+          {
+            description = "iodine client - ${name}";
+            after = [ "network.target" ];
+            wantedBy = [ "multi-user.target" ];
+            script = "exec ${pkgs.iodine}/bin/iodine -f -u ${iodinedUser} ${cfg.extraConfig} ${optionalString (cfg.passwordFile != "") "< \"${builtins.toString cfg.passwordFile}\""} ${cfg.relay} ${cfg.server}";
+            serviceConfig = {
+              RestartSec = "30s";
+              Restart = "always";
+
+              # hardening :
+              # Filesystem access
+              ProtectSystem = "strict";
+              ProtectHome = if isProtected cfg.passwordFile then "read-only" else "true" ;
+              PrivateTmp = true;
+              ReadWritePaths = "/dev/net/tun";
+              PrivateDevices = false;
+              ProtectKernelTunables = true;
+              ProtectKernelModules = true;
+              ProtectControlGroups = true;
+              # Caps
+              NoNewPrivileges = true;
+              # Misc.
+              LockPersonality = true;
+              RestrictRealtime = true;
+              PrivateMounts = true;
+              MemoryDenyWriteExecute = true;
+            };
+          };
+      in
+        listToAttrs (
+          mapAttrsToList
+            (name: value: nameValuePair "iodine-${name}" (createIodineClientService name value))
+            cfg.clients
+        ) // {
+          iodined = mkIf (cfg.server.enable) {
+            description = "iodine, ip over dns server daemon";
+            after = [ "network.target" ];
+            wantedBy = [ "multi-user.target" ];
+            script = "exec ${pkgs.iodine}/bin/iodined -f -u ${iodinedUser} ${cfg.server.extraConfig} ${optionalString (cfg.server.passwordFile != "") "< \"${builtins.toString cfg.server.passwordFile}\""} ${cfg.server.ip} ${cfg.server.domain}";
+            serviceConfig = {
+              # Filesystem access
+              ProtectSystem = "strict";
+              ProtectHome = if isProtected cfg.server.passwordFile then "read-only" else "true" ;
+              PrivateTmp = true;
+              ReadWritePaths = "/dev/net/tun";
+              PrivateDevices = false;
+              ProtectKernelTunables = true;
+              ProtectKernelModules = true;
+              ProtectControlGroups = true;
+              # Caps
+              NoNewPrivileges = true;
+              # Misc.
+              LockPersonality = true;
+              RestrictRealtime = true;
+              PrivateMounts = true;
+              MemoryDenyWriteExecute = true;
+            };
+          };
         };
-      };
-    in
-    listToAttrs (
-      mapAttrsToList
-        (name: value: nameValuePair "iodine-${name}" (createIodineClientService name value))
-        cfg.clients
-    ) // {
-      iodined = mkIf (cfg.server.enable) {
-        description = "iodine, ip over dns server daemon";
-        after = [ "network.target" ];
-        wantedBy = [ "multi-user.target" ];
-        script = "exec ${pkgs.iodine}/bin/iodined -f -u ${iodinedUser} ${cfg.server.extraConfig} ${optionalString (cfg.server.passwordFile != "") "< \"${cfg.server.passwordFile}\""} ${cfg.server.ip} ${cfg.server.domain}";
-      };
-    };
 
     users.users.${iodinedUser} = {
       uid = config.ids.uids.iodined;
diff --git a/nixpkgs/nixos/modules/services/networking/resilio.nix b/nixpkgs/nixos/modules/services/networking/resilio.nix
index 9b25aa575837..e74e03fc0b07 100644
--- a/nixpkgs/nixos/modules/services/networking/resilio.nix
+++ b/nixpkgs/nixos/modules/services/networking/resilio.nix
@@ -244,7 +244,7 @@ in
       group           = "rslsync";
     };
 
-    users.groups = [ { name = "rslsync"; } ];
+    users.groups.rslsync = {};
 
     systemd.services.resilio = with pkgs; {
       description = "Resilio Sync Service";
diff --git a/nixpkgs/nixos/modules/services/networking/supplicant.nix b/nixpkgs/nixos/modules/services/networking/supplicant.nix
index 35c1e649e2e1..b5b9989ce186 100644
--- a/nixpkgs/nixos/modules/services/networking/supplicant.nix
+++ b/nixpkgs/nixos/modules/services/networking/supplicant.nix
@@ -39,8 +39,6 @@ let
         bindsTo = deps;
         after = deps;
         before = [ "network.target" ];
-        # Receive restart event after resume
-        partOf = [ "post-resume.target" ];
 
         path = [ pkgs.coreutils ];
 
diff --git a/nixpkgs/nixos/modules/services/networking/supybot.nix b/nixpkgs/nixos/modules/services/networking/supybot.nix
index d5b9a97a1c1a..dc9fb31ffd0b 100644
--- a/nixpkgs/nixos/modules/services/networking/supybot.nix
+++ b/nixpkgs/nixos/modules/services/networking/supybot.nix
@@ -3,32 +3,35 @@
 with lib;
 
 let
-
   cfg  = config.services.supybot;
-
+  isStateDirHome = hasPrefix "/home/" cfg.stateDir;
+  isStateDirVar = cfg.stateDir == "/var/lib/supybot";
+  pyEnv = pkgs.python3.withPackages (p: [ p.limnoria ] ++ (cfg.extraPackages p));
 in
-
 {
-
   options = {
 
     services.supybot = {
 
       enable = mkOption {
+        type = types.bool;
         default = false;
-        description = "Enable Supybot, an IRC bot";
+        description = "Enable Supybot, an IRC bot (also known as Limnoria).";
       };
 
       stateDir = mkOption {
-        # Setting this to /var/lib/supybot caused useradd to fail
-        default = "/home/supybot";
+        type = types.path;
+        default = if versionAtLeast config.system.stateVersion "20.09"
+          then "/var/lib/supybot"
+          else "/home/supybot";
+        defaultText = "/var/lib/supybot";
         description = "The root directory, logs and plugins are stored here";
       };
 
       configFile = mkOption {
         type = types.path;
         description = ''
-          Path to a supybot config file. This can be generated by
+          Path to initial supybot config file. This can be generated by
           running supybot-wizard.
 
           Note: all paths should include the full path to the stateDir
@@ -36,21 +39,54 @@ in
         '';
       };
 
+      plugins = mkOption {
+        type = types.attrsOf types.path;
+        default = {};
+        description = ''
+          Attribute set of additional plugins that will be symlinked to the
+          <filename>plugin</filename> subdirectory.
+
+          Please note that you still need to add the plugins to the config
+          file (or with <literal>!load</literal>) using their attribute name.
+        '';
+        example = literalExample ''
+          let
+            plugins = pkgs.fetchzip {
+              url = "https://github.com/ProgVal/Supybot-plugins/archive/57c2450c.zip";
+              sha256 = "077snf84ibnva3sbpzdfpfma6hcdw7dflwnhg6pw7mgnf0nd84qd";
+            };
+          in
+          {
+            Wikipedia = "''${plugins}/Wikipedia";
+            Decide = ./supy-decide;
+          }
+        '';
+      };
+
+      extraPackages = mkOption {
+        default = p: [];
+        description = ''
+          Extra Python packages available to supybot plugins. The
+          value must be a function which receives the attrset defined
+          in <varname>python3Packages</varname> as the sole argument.
+        '';
+        example = literalExample ''p: [ p.lxml p.requests ]'';
+      };
+
     };
 
   };
 
-
   config = mkIf cfg.enable {
 
-    environment.systemPackages = [ pkgs.pythonPackages.limnoria ];
+    environment.systemPackages = [ pkgs.python3Packages.limnoria ];
 
     users.users.supybot = {
       uid = config.ids.uids.supybot;
       group = "supybot";
       description = "Supybot IRC bot user";
       home = cfg.stateDir;
-      createHome = true;
+      isSystemUser = true;
     };
 
     users.groups.supybot = {
@@ -59,19 +95,16 @@ in
 
     systemd.services.supybot = {
       description = "Supybot, an IRC bot";
+      documentation = [ "https://limnoria.readthedocs.io/" ];
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
-      path = [ pkgs.pythonPackages.limnoria ];
       preStart = ''
-        cd ${cfg.stateDir}
-        mkdir -p backup conf data plugins logs/plugins tmp web
-        ln -sf ${cfg.configFile} supybot.cfg
         # This needs to be created afresh every time
-        rm -f supybot.cfg.bak
+        rm -f '${cfg.stateDir}/supybot.cfg.bak'
       '';
 
       serviceConfig = {
-        ExecStart = "${pkgs.pythonPackages.limnoria}/bin/supybot ${cfg.stateDir}/supybot.cfg";
+        ExecStart = "${pyEnv}/bin/supybot ${cfg.stateDir}/supybot.cfg";
         PIDFile = "/run/supybot.pid";
         User = "supybot";
         Group = "supybot";
@@ -79,8 +112,50 @@ in
         Restart = "on-abort";
         StartLimitInterval = "5m";
         StartLimitBurst = "1";
+
+        NoNewPrivileges = true;
+        PrivateDevices = true;
+        PrivateMounts = true;
+        PrivateTmp = true;
+        ProtectControlGroups = true;
+        ProtectKernelModules = true;
+        ProtectKernelTunables = true;
+        RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+        RestrictSUIDSGID = true;
+        SystemCallArchitectures = "native";
+        RestrictNamespaces = true;
+        RestrictRealtime = true;
+        LockPersonality = true;
+        MemoryDenyWriteExecute = true;
+        RemoveIPC = true;
+        ProtectHostname = true;
+        CapabilityBoundingSet = "";
+        ProtectSystem = "full";
+      }
+      // optionalAttrs isStateDirVar {
+        StateDirectory = "supybot";
+        ProtectSystem = "strict";
+      }
+      // optionalAttrs (!isStateDirHome) {
+        ProtectHome = true;
       };
     };
 
+    systemd.tmpfiles.rules = [
+      "d '${cfg.stateDir}'              0700 supybot supybot - -"
+      "d '${cfg.stateDir}/backup'       0750 supybot supybot - -"
+      "d '${cfg.stateDir}/conf'         0750 supybot supybot - -"
+      "d '${cfg.stateDir}/data'         0750 supybot supybot - -"
+      "d '${cfg.stateDir}/plugins'      0750 supybot supybot - -"
+      "d '${cfg.stateDir}/logs'         0750 supybot supybot - -"
+      "d '${cfg.stateDir}/logs/plugins' 0750 supybot supybot - -"
+      "d '${cfg.stateDir}/tmp'          0750 supybot supybot - -"
+      "d '${cfg.stateDir}/web'          0750 supybot supybot - -"
+      "L '${cfg.stateDir}/supybot.cfg'  -    -       -       - ${cfg.configFile}"
+    ]
+    ++ (flip mapAttrsToList cfg.plugins (name: dest:
+      "L+ '${cfg.stateDir}/plugins/${name}' - - - - ${dest}"
+    ));
+
   };
 }
diff --git a/nixpkgs/nixos/modules/services/networking/tailscale.nix b/nixpkgs/nixos/modules/services/networking/tailscale.nix
new file mode 100644
index 000000000000..513c42b40117
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/tailscale.nix
@@ -0,0 +1,46 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let cfg = config.services.tailscale;
+in {
+  meta.maintainers = with maintainers; [ danderson mbaillie ];
+
+  options.services.tailscale = {
+    enable = mkEnableOption "Tailscale client daemon";
+
+    port = mkOption {
+      type = types.port;
+      default = 41641;
+      description = "The port to listen on for tunnel traffic (0=autoselect).";
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.tailscale = {
+      description = "Tailscale client daemon";
+
+      after = [ "network-pre.target" ];
+      wants = [ "network-pre.target" ];
+      wantedBy = [ "multi-user.target" ];
+
+      unitConfig = {
+        StartLimitIntervalSec = 0;
+        StartLimitBurst = 0;
+      };
+
+      serviceConfig = {
+        ExecStart =
+          "${pkgs.tailscale}/bin/tailscaled --port ${toString cfg.port}";
+
+        RuntimeDirectory = "tailscale";
+        RuntimeDirectoryMode = 755;
+
+        StateDirectory = "tailscale";
+        StateDirectoryMode = 700;
+
+        Restart = "on-failure";
+      };
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/services/networking/zerotierone.nix b/nixpkgs/nixos/modules/services/networking/zerotierone.nix
index 042c4d5adddd..cf39ed065a76 100644
--- a/nixpkgs/nixos/modules/services/networking/zerotierone.nix
+++ b/nixpkgs/nixos/modules/services/networking/zerotierone.nix
@@ -69,13 +69,14 @@ in
     environment.systemPackages = [ cfg.package ];
 
     # Prevent systemd from potentially changing the MAC address
-    environment.etc."systemd/network/50-zerotier.link".text = ''
-      [Match]
-      OriginalName=zt*
-
-      [Link]
-      AutoNegotiation=false
-      MACAddressPolicy=none
-    '';
+    systemd.network.links."50-zerotier" = {
+      matchConfig = {
+        OriginalName = "zt*";
+      };
+      linkConfig = {
+        AutoNegotiation = false;
+        MACAddressPolicy = "none";
+      };
+    };
   };
 }
diff --git a/nixpkgs/nixos/modules/services/security/fail2ban.nix b/nixpkgs/nixos/modules/services/security/fail2ban.nix
index cb748c93d24e..3f84f9c2560c 100644
--- a/nixpkgs/nixos/modules/services/security/fail2ban.nix
+++ b/nixpkgs/nixos/modules/services/security/fail2ban.nix
@@ -216,6 +216,10 @@ in
 
   config = mkIf cfg.enable {
 
+    warnings = mkIf (config.networking.firewall.enable == false && config.networking.nftables.enable == false) [
+      "fail2ban can not be used without a firewall"
+    ];
+
     environment.systemPackages = [ cfg.package ];
 
     environment.etc = {
diff --git a/nixpkgs/nixos/modules/services/web-apps/gerrit.nix b/nixpkgs/nixos/modules/services/web-apps/gerrit.nix
new file mode 100644
index 000000000000..b184c0754d45
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/web-apps/gerrit.nix
@@ -0,0 +1,218 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+  cfg = config.services.gerrit;
+
+  # NixOS option type for git-like configs
+  gitIniType = with types;
+    let
+      primitiveType = either str (either bool int);
+      multipleType = either primitiveType (listOf primitiveType);
+      sectionType = lazyAttrsOf multipleType;
+      supersectionType = lazyAttrsOf (either multipleType sectionType);
+    in lazyAttrsOf supersectionType;
+
+  gerritConfig = pkgs.writeText "gerrit.conf" (
+    lib.generators.toGitINI cfg.settings
+  );
+
+  # Wrap the gerrit java with all the java options so it can be called
+  # like a normal CLI app
+  gerrit-cli = pkgs.writeShellScriptBin "gerrit" ''
+    set -euo pipefail
+    jvmOpts=(
+      ${lib.escapeShellArgs cfg.jvmOpts}
+      -Xmx${cfg.jvmHeapLimit}
+    )
+    exec ${cfg.jvmPackage}/bin/java \
+      "''${jvmOpts[@]}" \
+      -jar ${cfg.package}/webapps/${cfg.package.name}.war \
+      "$@"
+  '';
+
+  gerrit-plugins = pkgs.runCommand
+    "gerrit-plugins"
+    {
+      buildInputs = [ gerrit-cli ];
+    }
+    ''
+      shopt -s nullglob
+      mkdir $out
+
+      for name in ${toString cfg.builtinPlugins}; do
+        echo "Installing builtin plugin $name.jar"
+        gerrit cat plugins/$name.jar > $out/$name.jar
+      done
+
+      for file in ${toString cfg.plugins}; do
+        name=$(echo "$file" | cut -d - -f 2-)
+        echo "Installing plugin $name"
+        ln -sf "$file" $out/$name
+      done
+    '';
+in
+{
+  options = {
+    services.gerrit = {
+      enable = mkEnableOption "Gerrit service";
+
+      package = mkOption {
+        type = types.package;
+        default = pkgs.gerrit;
+        description = "Gerrit package to use";
+      };
+
+      jvmPackage = mkOption {
+        type = types.package;
+        default = pkgs.jre_headless;
+        defaultText = "pkgs.jre_headless";
+        description = "Java Runtime Environment package to use";
+      };
+
+      jvmOpts = mkOption {
+        type = types.listOf types.str;
+        default = [
+          "-Dflogger.backend_factory=com.google.common.flogger.backend.log4j.Log4jBackendFactory#getInstance"
+          "-Dflogger.logging_context=com.google.gerrit.server.logging.LoggingContext#getInstance"
+        ];
+        description = "A list of JVM options to start gerrit with.";
+      };
+
+      jvmHeapLimit = mkOption {
+        type = types.str;
+        default = "1024m";
+        description = ''
+          How much memory to allocate to the JVM heap
+        '';
+      };
+
+      listenAddress = mkOption {
+        type = types.str;
+        default = "[::]:8080";
+        description = ''
+          <literal>hostname:port</literal> to listen for HTTP traffic.
+
+          This is bound using the systemd socket activation.
+        '';
+      };
+
+      settings = mkOption {
+        type = gitIniType;
+        default = {};
+        description = ''
+          Gerrit configuration. This will be generated to the
+          <literal>etc/gerrit.config</literal> file.
+        '';
+      };
+
+      plugins = mkOption {
+        type = types.listOf types.package;
+        default = [];
+        description = ''
+          List of plugins to add to Gerrit. Each derivation is a jar file
+          itself where the name of the derivation is the name of plugin.
+        '';
+      };
+
+      builtinPlugins = mkOption {
+        type = types.listOf (types.enum cfg.package.passthru.plugins);
+        default = [];
+        description = ''
+          List of builtins plugins to install. Those are shipped in the
+          <literal>gerrit.war</literal> file.
+        '';
+      };
+
+      serverId = mkOption {
+        type = types.str;
+        description = ''
+          Set a UUID that uniquely identifies the server.
+
+          This can be generated with
+          <literal>nix-shell -p utillinux --run uuidgen</literal>.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    services.gerrit.settings = {
+      cache.directory = "/var/cache/gerrit";
+      container.heapLimit = cfg.jvmHeapLimit;
+      gerrit.basePath = lib.mkDefault "git";
+      gerrit.serverId = cfg.serverId;
+      httpd.inheritChannel = "true";
+      httpd.listenUrl = lib.mkDefault "http://${cfg.listenAddress}";
+      index.type = lib.mkDefault "lucene";
+    };
+
+    # Add the gerrit CLI to the system to run `gerrit init` and friends.
+    environment.systemPackages = [ gerrit-cli ];
+
+    systemd.sockets.gerrit = {
+      unitConfig.Description = "Gerrit HTTP socket";
+      wantedBy = [ "sockets.target" ];
+      listenStreams = [ cfg.listenAddress ];
+    };
+
+    systemd.services.gerrit = {
+      description = "Gerrit";
+
+      wantedBy = [ "multi-user.target" ];
+      requires = [ "gerrit.socket" ];
+      after = [ "gerrit.socket" "network.target" ];
+
+      path = [
+        gerrit-cli
+        pkgs.bash
+        pkgs.coreutils
+        pkgs.git
+        pkgs.openssh
+      ];
+
+      environment = {
+        GERRIT_HOME = "%S/gerrit";
+        GERRIT_TMP = "%T";
+        HOME = "%S/gerrit";
+        XDG_CONFIG_HOME = "%S/gerrit/.config";
+      };
+
+      preStart = ''
+        set -euo pipefail
+
+        # bootstrap if nothing exists
+        if [[ ! -d git ]]; then
+          gerrit init --batch --no-auto-start
+        fi
+
+        # install gerrit.war for the plugin manager
+        rm -rf bin
+        mkdir bin
+        ln -sfv ${cfg.package}/webapps/${cfg.package.name}.war bin/gerrit.war
+
+        # copy the config, keep it mutable because Gerrit
+        ln -sfv ${gerritConfig} etc/gerrit.config
+
+        # install the plugins
+        rm -rf plugins
+        ln -sv ${gerrit-plugins} plugins
+      ''
+      ;
+
+      serviceConfig = {
+        CacheDirectory = "gerrit";
+        DynamicUser = true;
+        ExecStart = "${gerrit-cli}/bin/gerrit daemon --console-log";
+        LimitNOFILE = 4096;
+        StandardInput = "socket";
+        StandardOutput = "journal";
+        StateDirectory = "gerrit";
+        WorkingDirectory = "%S/gerrit";
+      };
+    };
+  };
+
+  meta.maintainers = with lib.maintainers; [ edef zimbatm ];
+}
diff --git a/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix b/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix
index 912e05d6d400..087bd0e5df3e 100644
--- a/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix
@@ -30,7 +30,7 @@ let
 
   occ = pkgs.writeScriptBin "nextcloud-occ" ''
     #! ${pkgs.stdenv.shell}
-    cd ${pkgs.nextcloud}
+    cd ${cfg.package}
     sudo=exec
     if [[ "$USER" != nextcloud ]]; then
       sudo='exec /run/wrappers/bin/sudo -u nextcloud --preserve-env=NEXTCLOUD_CONFIG_DIR'
@@ -42,6 +42,8 @@ let
       occ $*
   '';
 
+  inherit (config.system) stateVersion;
+
 in {
   options.services.nextcloud = {
     enable = mkEnableOption "nextcloud";
@@ -64,6 +66,11 @@ in {
       default = false;
       description = "Use https for generated links.";
     };
+    package = mkOption {
+      type = types.package;
+      description = "Which package to use for the Nextcloud instance.";
+      relatedPackages = [ "nextcloud17" "nextcloud18" ];
+    };
 
     maxUploadSize = mkOption {
       default = "512M";
@@ -309,10 +316,31 @@ in {
         }
       ];
 
-      warnings = optional (cfg.poolConfig != null) ''
-        Using config.services.nextcloud.poolConfig is deprecated and will become unsupported in a future release.
-        Please migrate your configuration to config.services.nextcloud.poolSettings.
-      '';
+      warnings = []
+        ++ (optional (cfg.poolConfig != null) ''
+          Using config.services.nextcloud.poolConfig is deprecated and will become unsupported in a future release.
+          Please migrate your configuration to config.services.nextcloud.poolSettings.
+        '')
+        ++ (optional (versionOlder cfg.package.version "18") ''
+          You're currently deploying an older version of Nextcloud. This may be needed
+          since Nextcloud doesn't allow major version upgrades across multiple versions (i.e. an
+          upgrade from 16 is possible to 17, but not to 18).
+
+          Please deploy this to your server and wait until the migration is finished. After
+          that you can deploy to the latest Nextcloud version available.
+        '');
+
+      services.nextcloud.package = with pkgs;
+        mkDefault (
+          if pkgs ? nextcloud
+            then throw ''
+              The `pkgs.nextcloud`-attribute has been removed. If it's supposed to be the default
+              nextcloud defined in an overlay, please set `services.nextcloud.package` to
+              `pkgs.nextcloud`.
+            ''
+          else if versionOlder stateVersion "20.03" then nextcloud17
+          else nextcloud18
+        );
     }
 
     { systemd.timers.nextcloud-cron = {
@@ -407,7 +435,7 @@ in {
           path = [ occ ];
           script = ''
             chmod og+x ${cfg.home}
-            ln -sf ${pkgs.nextcloud}/apps ${cfg.home}/
+            ln -sf ${cfg.package}/apps ${cfg.home}/
             mkdir -p ${cfg.home}/config ${cfg.home}/data ${cfg.home}/store-apps
             ln -sf ${overrideConfig} ${cfg.home}/config/override.config.php
 
@@ -429,7 +457,7 @@ in {
           environment.NEXTCLOUD_CONFIG_DIR = "${cfg.home}/config";
           serviceConfig.Type = "oneshot";
           serviceConfig.User = "nextcloud";
-          serviceConfig.ExecStart = "${phpPackage}/bin/php -f ${pkgs.nextcloud}/cron.php";
+          serviceConfig.ExecStart = "${phpPackage}/bin/php -f ${cfg.package}/cron.php";
         };
         nextcloud-update-plugins = mkIf cfg.autoUpdateApps.enable {
           serviceConfig.Type = "oneshot";
@@ -471,7 +499,7 @@ in {
         enable = true;
         virtualHosts = {
           ${cfg.hostName} = {
-            root = pkgs.nextcloud;
+            root = cfg.package;
             locations = {
               "= /robots.txt" = {
                 priority = 100;
diff --git a/nixpkgs/nixos/modules/services/web-apps/nextcloud.xml b/nixpkgs/nixos/modules/services/web-apps/nextcloud.xml
index d66e0f0c2997..fc454f8ba254 100644
--- a/nixpkgs/nixos/modules/services/web-apps/nextcloud.xml
+++ b/nixpkgs/nixos/modules/services/web-apps/nextcloud.xml
@@ -113,5 +113,53 @@
    maintenance:install</literal>! This command tries to install the application
    and can cause unwanted side-effects!</para>
   </warning>
+
+  <para>
+   Nextcloud doesn't allow to move more than one major-version forward. If you're e.g. on
+   <literal>v16</literal>, you cannot upgrade to <literal>v18</literal>, you need to upgrade to
+   <literal>v17</literal> first. This is ensured automatically as long as the
+   <link linkend="opt-system.stateVersion">stateVersion</link> is declared properly. In that case
+   the oldest version available (one major behind the one from the previous NixOS
+   release) will be selected by default and the module will generate a warning that reminds
+   the user to upgrade to latest Nextcloud <emphasis>after</emphasis> that deploy.
+  </para>
+ </section>
+
+ <section xml:id="module-services-nextcloud-maintainer-info">
+  <title>Maintainer information</title>
+
+  <para>
+   As stated in the previous paragraph, we must provide a clean upgrade-path for Nextcloud
+   since it cannot move more than one major version forward on a single upgrade. This chapter
+   adds some notes how Nextcloud updates should be rolled out in the future.
+  </para>
+
+  <para>
+   While minor and patch-level updates are no problem and can be done directly in the
+   package-expression (and should be backported to supported stable branches after that),
+   major-releases should be added in a new attribute (e.g. Nextcloud <literal>v19.0.0</literal>
+   should be available in <literal>nixpkgs</literal> as <literal>pkgs.nextcloud19</literal>).
+   To provide simple upgrade paths it's generally useful to backport those as well to stable
+   branches. As long as the package-default isn't altered, this won't break existing setups.
+   After that, the versioning-warning in the <literal>nextcloud</literal>-module should be
+   updated to make sure that the
+   <link linkend="opt-services.nextcloud.package">package</link>-option selects the latest version
+   on fresh setups.
+  </para>
+
+  <para>
+   If major-releases will be abandoned by upstream, we should check first if those are needed
+   in NixOS for a safe upgrade-path before removing those. In that case we shold keep those
+   packages, but mark them as insecure in an expression like this (in
+   <literal>&lt;nixpkgs/pkgs/servers/nextcloud/default.nix&gt;</literal>):
+<programlisting>/* ... */
+{
+  nextcloud17 = generic {
+    version = "17.0.x";
+    sha256 = "0000000000000000000000000000000000000000000000000000";
+    insecure = true;
+  };
+}</programlisting>
+  </para>
  </section>
 </chapter>
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/kodi.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/kodi.nix
index 65a7b9c628e5..e997b9a11343 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/kodi.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/kodi.nix
@@ -20,7 +20,7 @@ in
     services.xserver.desktopManager.session = [{
       name = "kodi";
       start = ''
-        ${pkgs.kodi}/bin/kodi --lircdev /run/lirc/lircd --standalone &
+        LIRC_SOCKET_PATH=/run/lirc/lircd ${pkgs.kodi}/bin/kodi --standalone &
         waitPID=$!
       '';
     }];
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix
index 910a246d776c..f236c14fcf3e 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix
@@ -44,35 +44,35 @@ in
 
   config = mkIf cfg.enable {
 
-    services.xserver.desktopManager.session = singleton {
-      name = "mate";
-      bgSupport = true;
-      start = ''
-        export XDG_MENU_PREFIX=mate-
+    services.xserver.displayManager.sessionPackages = [
+      pkgs.mate.mate-session-manager
+    ];
 
-        # Let caja find extensions
-        export CAJA_EXTENSION_DIRS=$CAJA_EXTENSION_DIRS''${CAJA_EXTENSION_DIRS:+:}${config.system.path}/lib/caja/extensions-2.0
+    services.xserver.displayManager.sessionCommands = ''
+      if test "$XDG_CURRENT_DESKTOP" = "MATE"; then
+          export XDG_MENU_PREFIX=mate-
 
-        # Let caja extensions find gsettings schemas
-        ${concatMapStrings (p: ''
+          # Let caja find extensions
+          export CAJA_EXTENSION_DIRS=$CAJA_EXTENSION_DIRS''${CAJA_EXTENSION_DIRS:+:}${config.system.path}/lib/caja/extensions-2.0
+
+          # Let caja extensions find gsettings schemas
+          ${concatMapStrings (p: ''
           if [ -d "${p}/lib/caja/extensions-2.0" ]; then
-            ${addToXDGDirs p}
+              ${addToXDGDirs p}
           fi
-          '')
-          config.environment.systemPackages
-        }
+          '') config.environment.systemPackages}
 
-        # Let mate-panel find applets
-        export MATE_PANEL_APPLETS_DIR=$MATE_PANEL_APPLETS_DIR''${MATE_PANEL_APPLETS_DIR:+:}${config.system.path}/share/mate-panel/applets
-        export MATE_PANEL_EXTRA_MODULES=$MATE_PANEL_EXTRA_MODULES''${MATE_PANEL_EXTRA_MODULES:+:}${config.system.path}/lib/mate-panel/applets
+          # Add mate-control-center paths to some XDG variables because its schemas are needed by mate-settings-daemon, and mate-settings-daemon is a dependency for mate-control-center (that is, they are mutually recursive)
+          ${addToXDGDirs pkgs.mate.mate-control-center}
+      fi
+    '';
 
-        # Add mate-control-center paths to some XDG variables because its schemas are needed by mate-settings-daemon, and mate-settings-daemon is a dependency for mate-control-center (that is, they are mutually recursive)
-        ${addToXDGDirs pkgs.mate.mate-control-center}
+    # Let mate-panel find applets
+    environment.sessionVariables."MATE_PANEL_APPLETS_DIR" = "${config.system.path}/share/mate-panel/applets";
+    environment.sessionVariables."MATE_PANEL_EXTRA_MODULES" = "${config.system.path}/lib/mate-panel/applets";
 
-        ${pkgs.mate.mate-session-manager}/bin/mate-session ${optionalString cfg.debug "--debug"} &
-        waitPID=$!
-      '';
-    };
+    # Debugging
+    environment.sessionVariables.MATE_SESSION_DEBUG = mkIf cfg.debug "1";
 
     environment.systemPackages =
       pkgs.mate.basePackages ++
diff --git a/nixpkgs/nixos/modules/system/activation/top-level.nix b/nixpkgs/nixos/modules/system/activation/top-level.nix
index 14bd751ce324..49693b6f1be0 100644
--- a/nixpkgs/nixos/modules/system/activation/top-level.nix
+++ b/nixpkgs/nixos/modules/system/activation/top-level.nix
@@ -75,7 +75,7 @@ let
       echo -n "$configurationName" > $out/configuration-name
       echo -n "systemd ${toString config.systemd.package.interfaceVersion}" > $out/init-interface-version
       echo -n "$nixosLabel" > $out/nixos-version
-      echo -n "${pkgs.stdenv.hostPlatform.system}" > $out/system
+      echo -n "${config.boot.kernelPackages.stdenv.hostPlatform.system}" > $out/system
 
       mkdir $out/fine-tune
       childCount=0
diff --git a/nixpkgs/nixos/modules/system/boot/kernel.nix b/nixpkgs/nixos/modules/system/boot/kernel.nix
index c247f334c23d..43871f439f7f 100644
--- a/nixpkgs/nixos/modules/system/boot/kernel.nix
+++ b/nixpkgs/nixos/modules/system/boot/kernel.nix
@@ -192,139 +192,144 @@ in
 
   ###### implementation
 
-  config = mkIf (!config.boot.isContainer) {
-
-    system.build = { inherit kernel; };
-
-    system.modulesTree = [ kernel ] ++ config.boot.extraModulePackages;
-
-    # Implement consoleLogLevel both in early boot and using sysctl
-    # (so you don't need to reboot to have changes take effect).
-    boot.kernelParams =
-      [ "loglevel=${toString config.boot.consoleLogLevel}" ] ++
-      optionals config.boot.vesa [ "vga=0x317" "nomodeset" ];
-
-    boot.kernel.sysctl."kernel.printk" = mkDefault config.boot.consoleLogLevel;
-
-    boot.kernelModules = [ "loop" "atkbd" ];
-
-    boot.initrd.availableKernelModules =
-      [ # Note: most of these (especially the SATA/PATA modules)
-        # shouldn't be included by default since nixos-generate-config
-        # detects them, but I'm keeping them for now for backwards
-        # compatibility.
-
-        # Some SATA/PATA stuff.
-        "ahci"
-        "sata_nv"
-        "sata_via"
-        "sata_sis"
-        "sata_uli"
-        "ata_piix"
-        "pata_marvell"
-
-        # Standard SCSI stuff.
-        "sd_mod"
-        "sr_mod"
-
-        # SD cards and internal eMMC drives.
-        "mmc_block"
-
-        # Support USB keyboards, in case the boot fails and we only have
-        # a USB keyboard, or for LUKS passphrase prompt.
-        "uhci_hcd"
-        "ehci_hcd"
-        "ehci_pci"
-        "ohci_hcd"
-        "ohci_pci"
-        "xhci_hcd"
-        "xhci_pci"
-        "usbhid"
-        "hid_generic" "hid_lenovo" "hid_apple" "hid_roccat"
-        "hid_logitech_hidpp" "hid_logitech_dj"
-
-      ] ++ optionals (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) [
-        # Misc. x86 keyboard stuff.
-        "pcips2" "atkbd" "i8042"
-
-        # x86 RTC needed by the stage 2 init script.
-        "rtc_cmos"
-      ];
-
-    boot.initrd.kernelModules =
-      [ # For LVM.
-        "dm_mod"
-      ];
-
-    # The Linux kernel >= 2.6.27 provides firmware.
-    hardware.firmware = [ kernel ];
-
-    # Create /etc/modules-load.d/nixos.conf, which is read by
-    # systemd-modules-load.service to load required kernel modules.
-    environment.etc =
-      { "modules-load.d/nixos.conf".source = kernelModulesConf;
-      };
-
-    systemd.services.systemd-modules-load =
-      { wantedBy = [ "multi-user.target" ];
-        restartTriggers = [ kernelModulesConf ];
-        serviceConfig =
-          { # Ignore failed module loads.  Typically some of the
-            # modules in ‘boot.kernelModules’ are "nice to have but
-            # not required" (e.g. acpi-cpufreq), so we don't want to
-            # barf on those.
-            SuccessExitStatus = "0 1";
+  config = mkMerge
+    [ (mkIf config.boot.initrd.enable {
+        boot.initrd.availableKernelModules =
+          [ # Note: most of these (especially the SATA/PATA modules)
+            # shouldn't be included by default since nixos-generate-config
+            # detects them, but I'm keeping them for now for backwards
+            # compatibility.
+
+            # Some SATA/PATA stuff.
+            "ahci"
+            "sata_nv"
+            "sata_via"
+            "sata_sis"
+            "sata_uli"
+            "ata_piix"
+            "pata_marvell"
+
+            # Standard SCSI stuff.
+            "sd_mod"
+            "sr_mod"
+
+            # SD cards and internal eMMC drives.
+            "mmc_block"
+
+            # Support USB keyboards, in case the boot fails and we only have
+            # a USB keyboard, or for LUKS passphrase prompt.
+            "uhci_hcd"
+            "ehci_hcd"
+            "ehci_pci"
+            "ohci_hcd"
+            "ohci_pci"
+            "xhci_hcd"
+            "xhci_pci"
+            "usbhid"
+            "hid_generic" "hid_lenovo" "hid_apple" "hid_roccat"
+            "hid_logitech_hidpp" "hid_logitech_dj"
+
+          ] ++ optionals (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) [
+            # Misc. x86 keyboard stuff.
+            "pcips2" "atkbd" "i8042"
+
+            # x86 RTC needed by the stage 2 init script.
+            "rtc_cmos"
+          ];
+
+        boot.initrd.kernelModules =
+          [ # For LVM.
+            "dm_mod"
+          ];
+      })
+
+      (mkIf (!config.boot.isContainer) {
+        system.build = { inherit kernel; };
+
+        system.modulesTree = [ kernel ] ++ config.boot.extraModulePackages;
+
+        # Implement consoleLogLevel both in early boot and using sysctl
+        # (so you don't need to reboot to have changes take effect).
+        boot.kernelParams =
+          [ "loglevel=${toString config.boot.consoleLogLevel}" ] ++
+          optionals config.boot.vesa [ "vga=0x317" "nomodeset" ];
+
+        boot.kernel.sysctl."kernel.printk" = mkDefault config.boot.consoleLogLevel;
+
+        boot.kernelModules = [ "loop" "atkbd" ];
+
+        # The Linux kernel >= 2.6.27 provides firmware.
+        hardware.firmware = [ kernel ];
+
+        # Create /etc/modules-load.d/nixos.conf, which is read by
+        # systemd-modules-load.service to load required kernel modules.
+        environment.etc =
+          { "modules-load.d/nixos.conf".source = kernelModulesConf;
           };
-      };
-
-    lib.kernelConfig = {
-      isYes = option: {
-        assertion = config: config.isYes option;
-        message = "CONFIG_${option} is not yes!";
-        configLine = "CONFIG_${option}=y";
-      };
-
-      isNo = option: {
-        assertion = config: config.isNo option;
-        message = "CONFIG_${option} is not no!";
-        configLine = "CONFIG_${option}=n";
-      };
-
-      isModule = option: {
-        assertion = config: config.isModule option;
-        message = "CONFIG_${option} is not built as a module!";
-        configLine = "CONFIG_${option}=m";
-      };
-
-      ### Usually you will just want to use these two
-      # True if yes or module
-      isEnabled = option: {
-        assertion = config: config.isEnabled option;
-        message = "CONFIG_${option} is not enabled!";
-        configLine = "CONFIG_${option}=y";
-      };
-
-      # True if no or omitted
-      isDisabled = option: {
-        assertion = config: config.isDisabled option;
-        message = "CONFIG_${option} is not disabled!";
-        configLine = "CONFIG_${option}=n";
-      };
-    };
 
-    # The config options that all modules can depend upon
-    system.requiredKernelConfig = with config.lib.kernelConfig; [
-      # !!! Should this really be needed?
-      (isYes "MODULES")
-      (isYes "BINFMT_ELF")
-    ] ++ (optional (randstructSeed != "") (isYes "GCC_PLUGIN_RANDSTRUCT"));
+        systemd.services.systemd-modules-load =
+          { wantedBy = [ "multi-user.target" ];
+            restartTriggers = [ kernelModulesConf ];
+            serviceConfig =
+              { # Ignore failed module loads.  Typically some of the
+                # modules in ‘boot.kernelModules’ are "nice to have but
+                # not required" (e.g. acpi-cpufreq), so we don't want to
+                # barf on those.
+                SuccessExitStatus = "0 1";
+              };
+          };
 
-    # nixpkgs kernels are assumed to have all required features
-    assertions = if config.boot.kernelPackages.kernel ? features then [] else
-      let cfg = config.boot.kernelPackages.kernel.config; in map (attrs:
-        { assertion = attrs.assertion cfg; inherit (attrs) message; }
-      ) config.system.requiredKernelConfig;
+        lib.kernelConfig = {
+          isYes = option: {
+            assertion = config: config.isYes option;
+            message = "CONFIG_${option} is not yes!";
+            configLine = "CONFIG_${option}=y";
+          };
 
-  };
+          isNo = option: {
+            assertion = config: config.isNo option;
+            message = "CONFIG_${option} is not no!";
+            configLine = "CONFIG_${option}=n";
+          };
+
+          isModule = option: {
+            assertion = config: config.isModule option;
+            message = "CONFIG_${option} is not built as a module!";
+            configLine = "CONFIG_${option}=m";
+          };
+
+          ### Usually you will just want to use these two
+          # True if yes or module
+          isEnabled = option: {
+            assertion = config: config.isEnabled option;
+            message = "CONFIG_${option} is not enabled!";
+            configLine = "CONFIG_${option}=y";
+          };
+
+          # True if no or omitted
+          isDisabled = option: {
+            assertion = config: config.isDisabled option;
+            message = "CONFIG_${option} is not disabled!";
+            configLine = "CONFIG_${option}=n";
+          };
+        };
+
+        # The config options that all modules can depend upon
+        system.requiredKernelConfig = with config.lib.kernelConfig;
+          [
+            # !!! Should this really be needed?
+            (isYes "MODULES")
+            (isYes "BINFMT_ELF")
+          ] ++ (optional (randstructSeed != "") (isYes "GCC_PLUGIN_RANDSTRUCT"));
+
+        # nixpkgs kernels are assumed to have all required features
+        assertions = if config.boot.kernelPackages.kernel ? features then [] else
+          let cfg = config.boot.kernelPackages.kernel.config; in map (attrs:
+            { assertion = attrs.assertion cfg; inherit (attrs) message; }
+          ) config.system.requiredKernelConfig;
+
+      })
+
+    ];
 
 }
diff --git a/nixpkgs/nixos/modules/system/boot/networkd.nix b/nixpkgs/nixos/modules/system/boot/networkd.nix
index 6dfbe66fc647..3078f84f6e92 100644
--- a/nixpkgs/nixos/modules/system/boot/networkd.nix
+++ b/nixpkgs/nixos/modules/system/boot/networkd.nix
@@ -355,6 +355,14 @@ let
   };
 
   linkOptions = commonNetworkOptions // {
+    # overwrite enable option from above
+    enable = mkOption {
+      default = true;
+      type = types.bool;
+      description = ''
+        Whether to enable this .link unit. It's handled by udev no matter if <command>systemd-networkd</command> is enabled or not
+      '';
+    };
 
     linkConfig = mkOption {
       default = {};
@@ -1045,44 +1053,49 @@ in
 
   };
 
-  config = mkIf config.systemd.network.enable {
+  config = mkMerge [
+    # .link units are honored by udev, no matter if systemd-networkd is enabled or not.
+    {
+      systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.links;
+      environment.etc = unitFiles;
+    }
 
-    users.users.systemd-network.group = "systemd-network";
+    (mkIf config.systemd.network.enable {
 
-    systemd.additionalUpstreamSystemUnits = [
-      "systemd-networkd.service" "systemd-networkd-wait-online.service"
-    ];
+      users.users.systemd-network.group = "systemd-network";
 
-    systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.links
-      // mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.netdevs
-      // mapAttrs' (n: v: nameValuePair "${n}.network" (networkToUnit n v)) cfg.networks;
+      systemd.additionalUpstreamSystemUnits = [
+        "systemd-networkd.service" "systemd-networkd-wait-online.service"
+      ];
 
-    environment.etc = unitFiles;
+      systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.netdevs
+        // mapAttrs' (n: v: nameValuePair "${n}.network" (networkToUnit n v)) cfg.networks;
 
-    systemd.services.systemd-networkd = {
-      wantedBy = [ "multi-user.target" ];
-      restartTriggers = attrNames unitFiles;
-      # prevent race condition with interface renaming (#39069)
-      requires = [ "systemd-udev-settle.service" ];
-      after = [ "systemd-udev-settle.service" ];
-    };
+      systemd.services.systemd-networkd = {
+        wantedBy = [ "multi-user.target" ];
+        restartTriggers = attrNames unitFiles;
+        # prevent race condition with interface renaming (#39069)
+        requires = [ "systemd-udev-settle.service" ];
+        after = [ "systemd-udev-settle.service" ];
+      };
 
-    systemd.services.systemd-networkd-wait-online = {
-      wantedBy = [ "network-online.target" ];
-    };
+      systemd.services.systemd-networkd-wait-online = {
+        wantedBy = [ "network-online.target" ];
+      };
 
-    systemd.services."systemd-network-wait-online@" = {
-      description = "Wait for Network Interface %I to be Configured";
-      conflicts = [ "shutdown.target" ];
-      requisite = [ "systemd-networkd.service" ];
-      after = [ "systemd-networkd.service" ];
-      serviceConfig = {
-        Type = "oneshot";
-        RemainAfterExit = true;
-        ExecStart = "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online -i %I";
+      systemd.services."systemd-network-wait-online@" = {
+        description = "Wait for Network Interface %I to be Configured";
+        conflicts = [ "shutdown.target" ];
+        requisite = [ "systemd-networkd.service" ];
+        after = [ "systemd-networkd.service" ];
+        serviceConfig = {
+          Type = "oneshot";
+          RemainAfterExit = true;
+          ExecStart = "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online -i %I";
+        };
       };
-    };
 
-    services.resolved.enable = mkDefault true;
-  };
+      services.resolved.enable = mkDefault true;
+    })
+  ];
 }
diff --git a/nixpkgs/nixos/modules/system/boot/stage-1.nix b/nixpkgs/nixos/modules/system/boot/stage-1.nix
index 26117cffeda2..93cd801ef803 100644
--- a/nixpkgs/nixos/modules/system/boot/stage-1.nix
+++ b/nixpkgs/nixos/modules/system/boot/stage-1.nix
@@ -390,6 +390,17 @@ in
       '';
     };
 
+    boot.initrd.enable = mkOption {
+      type = types.bool;
+      default = !config.boot.isContainer;
+      defaultText = "!config.boot.isContainer";
+      description = ''
+        Whether to enable the NixOS initial RAM disk (initrd). This may be
+        needed to perform some initialisation tasks (like mounting
+        network/encrypted file systems) before continuing the boot process.
+      '';
+    };
+
     boot.initrd.prepend = mkOption {
       default = [ ];
       type = types.listOf types.str;
@@ -555,7 +566,7 @@ in
 
   };
 
-  config = mkIf (!config.boot.isContainer) {
+  config = mkIf config.boot.initrd.enable {
     assertions = [
       { assertion = any (fs: fs.mountPoint == "/") fileSystems;
         message = "The ‘fileSystems’ option does not specify your root file system.";
diff --git a/nixpkgs/nixos/release-small.nix b/nixpkgs/nixos/release-small.nix
index 7b86a91357ec..2a15073b6698 100644
--- a/nixpkgs/nixos/release-small.nix
+++ b/nixpkgs/nixos/release-small.nix
@@ -28,7 +28,7 @@ let
 in rec {
 
   nixos = {
-    inherit (nixos') channel manual iso_minimal dummy;
+    inherit (nixos') channel manual options iso_minimal dummy;
     tests = {
       inherit (nixos'.tests)
         containers-imperative
diff --git a/nixpkgs/nixos/tests/all-tests.nix b/nixpkgs/nixos/tests/all-tests.nix
index 7dd0f23df658..3501c551625d 100644
--- a/nixpkgs/nixos/tests/all-tests.nix
+++ b/nixpkgs/nixos/tests/all-tests.nix
@@ -97,6 +97,7 @@ in
   fontconfig-default-fonts = handleTest ./fontconfig-default-fonts.nix {};
   freeswitch = handleTest ./freeswitch.nix {};
   fsck = handleTest ./fsck.nix {};
+  gerrit = handleTest ./gerrit.nix {};
   gotify-server = handleTest ./gotify-server.nix {};
   grocy = handleTest ./grocy.nix {};
   gitdaemon = handleTest ./gitdaemon.nix {};
@@ -135,6 +136,7 @@ in
   initrd-network-ssh = handleTest ./initrd-network-ssh {};
   initrdNetwork = handleTest ./initrd-network.nix {};
   installer = handleTest ./installer.nix {};
+  iodine = handleTest ./iodine.nix {};
   ipv6 = handleTest ./ipv6.nix {};
   jackett = handleTest ./jackett.nix {};
   jellyfin = handleTest ./jellyfin.nix {};
diff --git a/nixpkgs/nixos/tests/fenics.nix b/nixpkgs/nixos/tests/fenics.nix
new file mode 100644
index 000000000000..7252d19e4e65
--- /dev/null
+++ b/nixpkgs/nixos/tests/fenics.nix
@@ -0,0 +1,50 @@
+import ./make-test-python.nix ({ pkgs, ... }:
+
+let
+  fenicsScript = pkgs.writeScript "poisson.py" ''
+    #!/usr/bin/env python
+    from dolfin import *
+
+    mesh = UnitSquareMesh(4, 4)
+    V = FunctionSpace(mesh, "Lagrange", 1)
+
+    def boundary(x):
+        return x[0] < DOLFIN_EPS or x[0] > 1.0 - DOLFIN_EPS
+
+    u0 = Constant(0.0)
+    bc = DirichletBC(V, u0, boundary)
+
+    u = TrialFunction(V)
+    v = TestFunction(V)
+    f = Expression("10*exp(-(pow(x[0] - 0.5, 2) + pow(x[1] - 0.5, 2)) / 0.02)", degree=2)
+    g = Expression("sin(5*x[0])", degree=2)
+    a = inner(grad(u), grad(v))*dx
+    L = f*v*dx + g*v*ds
+
+    u = Function(V)
+    solve(a == L, u, bc)
+    print(u)
+  '';
+in
+{
+  name = "fenics";
+  meta = {
+    maintainers = with pkgs.stdenv.lib.maintainers; [ knedlsepp ];
+  };
+
+  nodes = {
+    fenicsnode = { pkgs, ... }: {
+      environment.systemPackages = with pkgs; [
+        gcc
+        (python3.withPackages (ps: with ps; [ fenics ]))
+      ];
+      virtualisation.memorySize = 512;
+    };
+  };
+  testScript =
+    { nodes, ... }:
+    ''
+      start_all()
+      node1.succeed("${fenicsScript}")
+    '';
+})
diff --git a/nixpkgs/nixos/tests/gerrit.nix b/nixpkgs/nixos/tests/gerrit.nix
new file mode 100644
index 000000000000..e8b5cb4c4feb
--- /dev/null
+++ b/nixpkgs/nixos/tests/gerrit.nix
@@ -0,0 +1,56 @@
+import ./make-test-python.nix ({ pkgs, ... }:
+
+let
+  lfs = pkgs.fetchurl {
+    url = "https://gerrit-ci.gerritforge.com/job/plugin-lfs-bazel-master/90/artifact/bazel-bin/plugins/lfs/lfs.jar";
+    sha256 = "023b0kd8djm3cn1lf1xl67yv3j12yl8bxccn42lkfmwxjwjfqw6h";
+  };
+
+in {
+  name = "gerrit";
+
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ flokli zimbatm ];
+  };
+
+  nodes = {
+    server =
+      { config, pkgs, ... }: {
+        networking.firewall.allowedTCPPorts = [ 80 2222 ];
+
+        virtualisation.memorySize = 1024;
+
+        services.gerrit = {
+          enable = true;
+          serverId = "aa76c84b-50b0-4711-a0a0-1ee30e45bbd0";
+          listenAddress = "[::]:80";
+          jvmPackage = pkgs.jdk12_headless;
+          jvmHeapLimit = "1g";
+
+          plugins = [ lfs ];
+          builtinPlugins = [ "hooks" "webhooks" ];
+          settings = {
+            gerrit.canonicalWebUrl = "http://server";
+            lfs.plugin = "lfs";
+            plugins.allowRemoteAdmin = true;
+            sshd.listenAddress = "[::]:2222";
+            sshd.advertisedAddress = "[::]:2222";
+          };
+        };
+      };
+
+    client =
+      { ... }: {
+      };
+  };
+
+  testScript = ''
+    start_all()
+    server.wait_for_unit("gerrit.service")
+    server.wait_for_open_port(80)
+    client.succeed("curl http://server")
+
+    server.wait_for_open_port(2222)
+    client.succeed("nc -z server 2222")
+  '';
+})
diff --git a/nixpkgs/nixos/tests/graphite.nix b/nixpkgs/nixos/tests/graphite.nix
index ba3c73bb878d..71776a94cbd6 100644
--- a/nixpkgs/nixos/tests/graphite.nix
+++ b/nixpkgs/nixos/tests/graphite.nix
@@ -12,15 +12,19 @@ import ./make-test-python.nix ({ pkgs, ... } :
         virtualisation.memorySize = 1024;
         time.timeZone = "UTC";
         services.graphite = {
-          web.enable = true;
+          web = {
+            enable = true;
+            extraConfig = ''
+              SECRET_KEY = "abcd";
+            '';
+          };
           api = {
             enable = true;
             port = 8082;
-            finders = [ pkgs.python27Packages.influxgraph ];
+            finders = [ pkgs.python3Packages.influxgraph ];
           };
           carbon.enableCache = true;
-          seyren.enable = true;
-          pager.enable = true;
+          seyren.enable = false;  # Implicitely requires openssl-1.0.2u which is marked insecure
           beacon.enable = true;
         };
       };
@@ -31,16 +35,16 @@ import ./make-test-python.nix ({ pkgs, ... } :
     one.wait_for_unit("default.target")
     one.wait_for_unit("graphiteWeb.service")
     one.wait_for_unit("graphiteApi.service")
-    one.wait_for_unit("graphitePager.service")
     one.wait_for_unit("graphite-beacon.service")
     one.wait_for_unit("carbonCache.service")
-    one.wait_for_unit("seyren.service")
     # The services above are of type "simple". systemd considers them active immediately
     # even if they're still in preStart (which takes quite long for graphiteWeb).
     # Wait for ports to open so we're sure the services are up and listening.
     one.wait_for_open_port(8080)
     one.wait_for_open_port(2003)
     one.succeed('echo "foo 1 `date +%s`" | nc -N localhost 2003')
-    one.wait_until_succeeds("curl 'http://localhost:8080/metrics/find/?query=foo&format=treejson' --silent | grep foo >&2")
+    one.wait_until_succeeds(
+        "curl 'http://localhost:8080/metrics/find/?query=foo&format=treejson' --silent | grep foo >&2"
+    )
   '';
 })
diff --git a/nixpkgs/nixos/tests/installer.nix b/nixpkgs/nixos/tests/installer.nix
index 983861911e0d..babde4126c4c 100644
--- a/nixpkgs/nixos/tests/installer.nix
+++ b/nixpkgs/nixos/tests/installer.nix
@@ -104,7 +104,6 @@ let
 
       with subtest("Assert readiness of login prompt"):
           machine.succeed("echo hello")
-          machine.wait_for_unit("nixos-manual")
 
       with subtest("Wait for hard disks to appear in /dev"):
           machine.succeed("udevadm settle")
diff --git a/nixpkgs/nixos/tests/iodine.nix b/nixpkgs/nixos/tests/iodine.nix
new file mode 100644
index 000000000000..8bd9603a6d6c
--- /dev/null
+++ b/nixpkgs/nixos/tests/iodine.nix
@@ -0,0 +1,63 @@
+import ./make-test-python.nix (
+  { pkgs, ... }: let
+    domain = "whatever.example.com";
+  in
+    {
+      name = "iodine";
+      nodes = {
+        server =
+          { ... }:
+
+            {
+              networking.firewall = {
+                allowedUDPPorts = [ 53 ];
+                trustedInterfaces = [ "dns0" ];
+              };
+              boot.kernel.sysctl = {
+                "net.ipv4.ip_forward" = 1;
+                "net.ipv6.ip_forward" = 1;
+              };
+
+              services.iodine.server = {
+                enable = true;
+                ip = "10.53.53.1/24";
+                passwordFile = "${builtins.toFile "password" "foo"}";
+                inherit domain;
+              };
+
+              # test resource: accessible only via tunnel
+              services.openssh = {
+                enable = true;
+                openFirewall = false;
+              };
+            };
+
+        client =
+          { ... }: {
+            services.iodine.clients.testClient = {
+              # test that ProtectHome is "read-only"
+              passwordFile = "/root/pw";
+              relay = "server";
+              server = domain;
+            };
+            systemd.tmpfiles.rules = [
+              "f /root/pw 0666 root root - foo"
+            ];
+            environment.systemPackages = [
+              pkgs.nagiosPluginsOfficial
+            ];
+          };
+
+      };
+
+      testScript = ''
+        start_all()
+
+        server.wait_for_unit("sshd")
+        server.wait_for_unit("iodined")
+        client.wait_for_unit("iodine-testClient")
+
+        client.succeed("check_ssh -H 10.53.53.1")
+      '';
+    }
+)
diff --git a/nixpkgs/nixos/tests/mongodb.nix b/nixpkgs/nixos/tests/mongodb.nix
index 9ebf84eed232..ee7fc50f7ecc 100644
--- a/nixpkgs/nixos/tests/mongodb.nix
+++ b/nixpkgs/nixos/tests/mongodb.nix
@@ -1,42 +1,52 @@
 # This test start mongodb, runs a query using mongo shell
 
-import ./make-test-python.nix ({ pkgs, ...} : let
-  testQuery = pkgs.writeScript "nixtest.js" ''
-    db.greetings.insert({ "greeting": "hello" });
-    print(db.greetings.findOne().greeting);
-  '';
-in {
-  name = "mongodb";
-  meta = with pkgs.stdenv.lib.maintainers; {
-    maintainers = [ bluescreen303 offline cstrahan rvl phile314 ];
-  };
+import ./make-test-python.nix ({ pkgs, ... }:
+  let
+    testQuery = pkgs.writeScript "nixtest.js" ''
+      db.greetings.insert({ "greeting": "hello" });
+      print(db.greetings.findOne().greeting);
+    '';
 
-  nodes = {
-    one =
-      { ... }:
-        {
-          services = {
-           mongodb.enable = true;
-           mongodb.enableAuth = true;
-           mongodb.initialRootPassword = "root";
-           mongodb.initialScript = pkgs.writeText "mongodb_initial.js" ''
-             db = db.getSiblingDB("nixtest");
-             db.createUser({user:"nixtest",pwd:"nixtest",roles:[{role:"readWrite",db:"nixtest"}]});
-           '';
-           mongodb.extraConfig = ''
-             # Allow starting engine with only a small virtual disk
-             storage.journal.enabled: false
-             storage.mmapv1.smallFiles: true
-           '';
-          };
-        };
+    runMongoDBTest = pkg: ''
+      node.execute("(rm -rf data || true) && mkdir data")
+      node.execute(
+          "${pkg}/bin/mongod --fork --logpath logs --dbpath data"
+      )
+      node.wait_for_open_port(27017)
+
+      assert "hello" in node.succeed(
+          "mongo ${testQuery}"
+      )
+
+      node.execute(
+          "${pkg}/bin/mongod --shutdown --dbpath data"
+      )
+      node.wait_for_closed_port(27017)
+    '';
+
+  in {
+    name = "mongodb";
+    meta = with pkgs.stdenv.lib.maintainers; {
+      maintainers = [ bluescreen303 offline cstrahan rvl phile314 ];
+    };
+
+    nodes = {
+      node = {...}: {
+        environment.systemPackages = with pkgs; [
+#          mongodb-3_4
+          mongodb-3_6
+          mongodb-4_0
+        ];
+      };
     };
 
-  testScript = ''
-    start_all()
-    one.wait_for_unit("mongodb.service")
-    one.succeed(
-        "mongo -u nixtest -p nixtest nixtest ${testQuery} | grep -q hello"
-    )
-  '';
-})
+    testScript = ''
+      node.start()
+    ''
+#      + runMongoDBTest pkgs.mongodb-3_4
+      + runMongoDBTest pkgs.mongodb-3_6 
+      + runMongoDBTest pkgs.mongodb-4_0
+      + ''
+        node.shutdown()
+      '';
+  })
diff --git a/nixpkgs/nixos/tests/mysql.nix b/nixpkgs/nixos/tests/mysql.nix
index 924bac84e26c..84673181e1a4 100644
--- a/nixpkgs/nixos/tests/mysql.nix
+++ b/nixpkgs/nixos/tests/mysql.nix
@@ -22,6 +22,27 @@ import ./make-test-python.nix ({ pkgs, ...} : {
         services.mysql.package = pkgs.mysql57;
       };
 
+    mysql80 =
+      { pkgs, ... }:
+
+      {
+        # prevent oom:
+        # Kernel panic - not syncing: Out of memory: compulsory panic_on_oom is enabled
+        virtualisation.memorySize = 1024;
+
+        services.mysql.enable = true;
+        services.mysql.initialDatabases = [
+          { name = "testdb"; schema = ./testdb.sql; }
+          { name = "empty_testdb"; }
+        ];
+        # note that using pkgs.writeText here is generally not a good idea,
+        # as it will store the password in world-readable /nix/store ;)
+        services.mysql.initialScript = pkgs.writeText "mysql-init.sql" ''
+          CREATE USER 'passworduser'@'localhost' IDENTIFIED BY 'password123';
+        '';
+        services.mysql.package = pkgs.mysql80;
+      };
+
     mariadb =
       { pkgs, ... }:
 
@@ -61,6 +82,12 @@ import ./make-test-python.nix ({ pkgs, ...} : {
     # ';' acts as no-op, just check whether login succeeds with the user created from the initialScript
     mysql.succeed("echo ';' | mysql -u passworduser --password=password123")
 
+    mysql80.wait_for_unit("mysql")
+    mysql80.succeed("echo 'use empty_testdb;' | mysql -u root")
+    mysql80.succeed("echo 'use testdb; select * from tests;' | mysql -u root -N | grep 4")
+    # ';' acts as no-op, just check whether login succeeds with the user created from the initialScript
+    mysql80.succeed("echo ';' | mysql -u passworduser --password=password123")
+
     mariadb.wait_for_unit("mysql")
     mariadb.succeed(
         "echo 'use testdb; create table tests (test_id INT, PRIMARY KEY (test_id));' | sudo -u testuser mysql -u testuser"
diff --git a/nixpkgs/nixos/tests/networking.nix b/nixpkgs/nixos/tests/networking.nix
index 933a4451af92..0a6507d2dc88 100644
--- a/nixpkgs/nixos/tests/networking.nix
+++ b/nixpkgs/nixos/tests/networking.nix
@@ -655,6 +655,31 @@ let
             ), "The IPv6 routing table has not been properly cleaned:\n{}".format(ipv6Residue)
       '';
     };
+    # even with disabled networkd, systemd.network.links should work
+    # (as it's handled by udev, not networkd)
+    link = {
+      name = "Link";
+      nodes.client = { pkgs, ... }: {
+        virtualisation.vlans = [ 1 ];
+        networking = {
+          useNetworkd = networkd;
+          useDHCP = false;
+        };
+        systemd.network.links."50-foo" = {
+          matchConfig = {
+            Name = "foo";
+            Driver = "dummy";
+          };
+          linkConfig.MTUBytes = "1442";
+        };
+      };
+      testScript = ''
+        print(client.succeed("ip l add name foo type dummy"))
+        print(client.succeed("stat /etc/systemd/network/50-foo.link"))
+        client.succeed("udevadm settle")
+        assert "mtu 1442" in client.succeed("ip l show dummy0")
+      '';
+    };
   };
 
 in mapAttrs (const (attrs: makeTest (attrs // {