about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/configuration/customizing-packages.xml27
-rw-r--r--nixos/doc/manual/development/option-declarations.xml88
-rw-r--r--nixos/doc/manual/development/option-types.xml116
-rw-r--r--nixos/doc/manual/installation/obtaining.xml2
-rw-r--r--nixos/doc/manual/release-notes/rl-1703.xml5
-rw-r--r--nixos/modules/config/debug-info.nix6
-rw-r--r--nixos/modules/config/shells-environment.nix2
-rw-r--r--nixos/modules/config/system-environment.nix2
-rw-r--r--nixos/modules/config/system-path.nix1
-rw-r--r--nixos/modules/hardware/opengl.nix6
-rw-r--r--nixos/modules/hardware/video/amdgpu-pro.nix2
-rw-r--r--nixos/modules/installer/tools/nixos-option.sh2
-rw-r--r--nixos/modules/installer/virtualbox-demo.nix2
-rw-r--r--nixos/modules/misc/ids.nix4
-rw-r--r--nixos/modules/module-list.nix3
-rw-r--r--nixos/modules/programs/adb.nix30
-rw-r--r--nixos/modules/security/grsecurity.nix6
-rw-r--r--nixos/modules/services/cluster/fleet.nix2
-rw-r--r--nixos/modules/services/cluster/kubernetes.nix2
-rw-r--r--nixos/modules/services/cluster/panamax.nix2
-rw-r--r--nixos/modules/services/editors/emacs.xml6
-rw-r--r--nixos/modules/services/games/ghost-one.nix3
-rw-r--r--nixos/modules/services/logging/logcheck.nix4
-rw-r--r--nixos/modules/services/mail/opensmtpd.nix2
-rw-r--r--nixos/modules/services/misc/dictd.nix10
-rw-r--r--nixos/modules/services/misc/errbot.nix4
-rw-r--r--nixos/modules/services/misc/leaps.nix62
-rw-r--r--nixos/modules/services/misc/matrix-synapse.nix30
-rw-r--r--nixos/modules/services/misc/nix-daemon.nix4
-rw-r--r--nixos/modules/services/misc/parsoid.nix3
-rw-r--r--nixos/modules/services/misc/taskserver/default.nix4
-rw-r--r--nixos/modules/services/network-filesystems/ipfs.nix111
-rw-r--r--nixos/modules/services/network-filesystems/tahoe.nix52
-rw-r--r--nixos/modules/services/network-filesystems/yandex-disk.nix13
-rw-r--r--nixos/modules/services/networking/bitlbee.nix7
-rw-r--r--nixos/modules/services/networking/cjdns.nix7
-rw-r--r--nixos/modules/services/networking/dnscrypt-proxy.nix122
-rw-r--r--nixos/modules/services/networking/i2pd.nix230
-rw-r--r--nixos/modules/services/networking/nsd.nix4
-rw-r--r--nixos/modules/services/networking/quassel.nix11
-rw-r--r--nixos/modules/services/networking/skydns.nix2
-rw-r--r--nixos/modules/services/networking/smokeping.nix4
-rw-r--r--nixos/modules/services/networking/tinc.nix2
-rw-r--r--nixos/modules/services/networking/vsftpd.nix11
-rw-r--r--nixos/modules/services/networking/znc.nix3
-rw-r--r--nixos/modules/services/search/hound.nix2
-rw-r--r--nixos/modules/services/security/clamav.nix2
-rw-r--r--nixos/modules/services/web-servers/fcgiwrap.nix2
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/default.nix3
-rw-r--r--nixos/modules/services/x11/desktop-managers/lumina.nix52
-rw-r--r--nixos/modules/services/x11/desktop-managers/lxqt.nix1
-rw-r--r--nixos/modules/system/boot/loader/grub/grub.nix3
-rw-r--r--nixos/modules/tasks/network-interfaces.nix2
-rw-r--r--nixos/modules/virtualisation/libvirtd.nix2
-rw-r--r--nixos/release.nix1
-rw-r--r--nixos/tests/chromium.nix2
-rw-r--r--nixos/tests/cjdns.nix2
-rw-r--r--nixos/tests/dnscrypt-proxy.nix2
-rw-r--r--nixos/tests/hibernate.nix4
-rw-r--r--nixos/tests/leaps.nix29
-rw-r--r--nixos/tests/mpich.nix41
-rwxr-xr-xnixos/tests/test-config-examples.sh14
-rw-r--r--nixos/tests/virtualbox.nix12
64 files changed, 964 insertions, 235 deletions
diff --git a/nixos/doc/manual/configuration/customizing-packages.xml b/nixos/doc/manual/configuration/customizing-packages.xml
index 6ee7a95dc6fa..8aa01fb57a09 100644
--- a/nixos/doc/manual/configuration/customizing-packages.xml
+++ b/nixos/doc/manual/configuration/customizing-packages.xml
@@ -42,29 +42,30 @@ construction, so without them,
 elements.)</para>
 
 <para>Even greater customisation is possible using the function
-<varname>overrideDerivation</varname>.  While the
+<varname>overrideAttrs</varname>.  While the
 <varname>override</varname> mechanism above overrides the arguments of
-a package function, <varname>overrideDerivation</varname> allows
-changing the <emphasis>result</emphasis> of the function.  This
-permits changing any aspect of the package, such as the source code.
+a package function, <varname>overrideAttrs</varname> allows
+changing the <emphasis>attributes</emphasis> passed to <literal>mkDerivation</literal>.
+This permits changing any aspect of the package, such as the source code.
 For instance, if you want to override the source code of Emacs, you
 can say:
 
 <programlisting>
-environment.systemPackages =
-  [ (pkgs.lib.overrideDerivation pkgs.emacs (attrs: {
-      name = "emacs-25.0-pre";
-      src = /path/to/my/emacs/tree;
-    }))
-  ];
+environment.systemPackages = [
+  (pkgs.emacs.overrideAttrs (oldAttrs: {
+    name = "emacs-25.0-pre";
+    src = /path/to/my/emacs/tree;
+  }))
+];
 </programlisting>
 
-Here, <varname>overrideDerivation</varname> takes the Nix derivation
+Here, <varname>overrideAttrs</varname> takes the Nix derivation
 specified by <varname>pkgs.emacs</varname> and produces a new
 derivation in which the original’s <literal>name</literal> and
 <literal>src</literal> attribute have been replaced by the given
-values.  The original attributes are accessible via
-<varname>attrs</varname>.</para>
+values by re-calling <literal>stdenv.mkDerivation</literal>.
+The original attributes are accessible via the function argument,
+which is conventionally named <varname>oldAttrs</varname>.</para>
 
 <para>The overrides shown above are not global.  They do not affect
 the original package; other packages in Nixpkgs continue to depend on
diff --git a/nixos/doc/manual/development/option-declarations.xml b/nixos/doc/manual/development/option-declarations.xml
index 7be5e9d51d46..ce432a7fa6ca 100644
--- a/nixos/doc/manual/development/option-declarations.xml
+++ b/nixos/doc/manual/development/option-declarations.xml
@@ -65,4 +65,92 @@ options = {
 
 </para>
 
+<section xml:id="sec-option-declarations-eot"><title>Extensible Option 
+    Types</title>
+
+  <para>Extensible option types is a feature that allow to extend certain types 
+    declaration through multiple module files.
+    This feature only work with a restricted set of types, namely 
+    <literal>enum</literal> and <literal>submodules</literal> and any composed
+    forms of them.</para>
+
+  <para>Extensible option types can be used for <literal>enum</literal> options 
+    that affects multiple modules, or as an alternative to related 
+    <literal>enable</literal> options.</para>
+
+  <para>As an example, we will take the case of display managers. There is a
+    central display manager module for generic display manager options and a
+    module file per display manager backend (slim, kdm, gdm ...).
+  </para>
+
+  <para>There are two approach to this module structure:
+
+  <itemizedlist>
+    <listitem><para>Managing the display managers independently by adding an
+        enable option to every display manager module backend. (NixOS)</para>
+    </listitem>
+    <listitem><para>Managing the display managers in the central module by
+        adding an option to select which display manager backend to use.</para>
+    </listitem>
+  </itemizedlist>
+  </para>
+
+  <para>Both approachs have problems.</para>
+    
+  <para>Making backends independent can quickly become hard to manage. For
+    display managers, there can be only one enabled at a time, but the type
+    system can not enforce this restriction as there is no relation between
+    each backend <literal>enable</literal> option. As a result, this restriction
+    has to be done explicitely by adding assertions in each display manager
+    backend module.</para>
+
+  <para>On the other hand, managing the display managers backends in the
+    central module will require to change the central module option every time
+    a new backend is added or removed.</para>
+
+  <para>By using extensible option types, it is possible to create a placeholder 
+    option in the central module (<xref linkend='ex-option-declaration-eot-service' 
+      />), and to extend it in each backend module (<xref 
+      linkend='ex-option-declaration-eot-backend-slim' />, <xref 
+      linkend='ex-option-declaration-eot-backend-kdm' />).</para>
+ 
+  <para>As a result, <literal>displayManager.enable</literal> option values can
+  be added without changing the main service module file and the type system
+  automatically enforce that there can only be a single display manager
+  enabled.</para>
+
+<example xml:id='ex-option-declaration-eot-service'><title>Extensible type 
+    placeholder in the service module</title>
+<screen>
+services.xserver.displayManager.enable = mkOption {
+  description = "Display manager to use";
+  type = with types; nullOr (enum [ ]);
+};</screen></example>
+
+<example xml:id='ex-option-declaration-eot-backend-slim'><title>Extending 
+    <literal>services.xserver.displayManager.enable</literal> in the 
+    <literal>slim</literal> module</title>
+<screen>
+services.xserver.displayManager.enable = mkOption {
+  type = with types; nullOr (enum [ "slim" ]);
+};</screen></example>
+
+<example xml:id='ex-option-declaration-eot-backend-kdm'><title>Extending 
+    <literal>services.foo.backend</literal> in the <literal>kdm</literal> 
+    module</title>
+<screen>
+services.xserver.displayManager.enable = mkOption {
+  type = with types; nullOr (enum [ "kdm" ]);
+};</screen></example>
+
+<para>The placeholder declaration is a standard <literal>mkOption</literal> 
+  declaration, but it is important that extensible option declarations only use 
+  the <literal>type</literal> argument.</para>
+
+<para>Extensible option types work with any of the composed variants of 
+  <literal>enum</literal> such as 
+  <literal>with types; nullOr (enum [ "foo" "bar" ])</literal> 
+  or <literal>with types; listOf (enum [ "foo" "bar" ])</literal>.</para>
+
+</section>
 </section>
diff --git a/nixos/doc/manual/development/option-types.xml b/nixos/doc/manual/development/option-types.xml
index 8871b02cebf1..8e6ac53ad480 100644
--- a/nixos/doc/manual/development/option-types.xml
+++ b/nixos/doc/manual/development/option-types.xml
@@ -62,23 +62,45 @@
     <listitem><para>A string. Multiple definitions are concatenated with a 
         collon <literal>":"</literal>.</para></listitem>
   </varlistentry>
+</variablelist>
+
+ </section>
+
+ <section><title>Value Types</title>
+
+   <para>Value types are type that take a value parameter. The only value type 
+     in the library is <literal>enum</literal>.</para>
+
+<variablelist>
   <varlistentry>
-    <term><varname>types.separatedString</varname> 
+    <term><varname>types.enum</varname> <replaceable>l</replaceable></term>
+    <listitem><para>One element of the list <replaceable>l</replaceable>, e.g. 
+        <literal>types.enum [ "left" "right" ]</literal>. Multiple definitions 
+        cannot be merged.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>types.separatedString</varname>
       <replaceable>sep</replaceable></term>
-    <listitem><para>A string with a custom separator 
-        <replaceable>sep</replaceable>, e.g. <literal>types.separatedString 
+    <listitem><para>A string with a custom separator
+        <replaceable>sep</replaceable>, e.g. <literal>types.separatedString
           "|"</literal>.</para></listitem>
   </varlistentry>
+  <varlistentry>
+    <term><varname>types.submodule</varname> <replaceable>o</replaceable></term>
+    <listitem><para>A set of sub options <replaceable>o</replaceable>.
+        <replaceable>o</replaceable> can be an attribute set or a function
+        returning an attribute set. Submodules are used in composed types to
+        create modular options. Submodule are detailed in <xref
+          linkend='section-option-types-submodule' />.</para></listitem>
+  </varlistentry>
 </variablelist>
-
  </section>
 
  <section><title>Composed Types</title>
 
-   <para>Composed types allow to create complex types by taking another type(s) 
-     or value(s) as parameter(s).
-     It is possible to compose types multiple times, e.g. <literal>with types; 
-       nullOr (enum [ "left" "right" ])</literal>.</para>
+   <para>Composed types are types that take a type as parameter. <literal>listOf 
+       int</literal> and <literal>either int str</literal> are examples of 
+     composed types.</para>
 
 <variablelist>
   <varlistentry>
@@ -100,12 +122,6 @@
         value.</para></listitem>
   </varlistentry>
   <varlistentry>
-    <term><varname>types.loeOf</varname> <replaceable>t</replaceable></term>
-    <listitem><para>A list or an element of <replaceable>t</replaceable> type. 
-        Multiple definitions are merged according to the 
-        values.</para></listitem>
-  </varlistentry>
-  <varlistentry>
     <term><varname>types.nullOr</varname> <replaceable>t</replaceable></term>
     <listitem><para><literal>null</literal> or type 
         <replaceable>t</replaceable>. Multiple definitions are merged according 
@@ -118,12 +134,6 @@
         once.</para></listitem>
   </varlistentry>
   <varlistentry>
-    <term><varname>types.enum</varname> <replaceable>l</replaceable></term>
-    <listitem><para>One element of the list <replaceable>l</replaceable>, e.g. 
-        <literal>types.enum [ "left" "right" ]</literal>. Multiple definitions 
-        cannot be merged</para></listitem>
-  </varlistentry>
-  <varlistentry>
     <term><varname>types.either</varname> <replaceable>t1</replaceable> 
       <replaceable>t2</replaceable></term>
     <listitem><para>Type <replaceable>t1</replaceable> or type 
@@ -131,14 +141,6 @@
           str</literal>. Multiple definitions cannot be 
         merged.</para></listitem>
   </varlistentry>
-  <varlistentry>
-    <term><varname>types.submodule</varname> <replaceable>o</replaceable></term>
-    <listitem><para>A set of sub options <replaceable>o</replaceable>. 
-        <replaceable>o</replaceable> can be an attribute set or a function 
-        returning an attribute set. Submodules are used in composed types to 
-        create modular options. Submodule are detailed in <xref 
-          linkend='section-option-types-submodule' />.</para></listitem>
-  </varlistentry>
 </variablelist>
 
 </section>
@@ -197,7 +199,6 @@ options.mod = mkOption {
   type = with types; listOf (submodule modOptions);
 };</screen></example>
 
-
 <section><title>Composed with <literal>listOf</literal></title>
 
   <para>When composed with <literal>listOf</literal>, submodule allows multiple 
@@ -323,9 +324,13 @@ code before creating a new type.</para>
 <variablelist>
   <varlistentry>
     <term><varname>name</varname></term>
-    <listitem><para>A string representation of the type function name, name 
-        usually changes accordingly parameters passed to 
-        types.</para></listitem>
+    <listitem><para>A string representation of the type function 
+        name.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>definition</varname></term>
+    <listitem><para>Description of the type used in documentation. Give 
+        information of the type and any of its arguments.</para></listitem>
   </varlistentry>
   <varlistentry>
     <term><varname>check</varname></term>
@@ -388,6 +393,53 @@ code before creating a new type.</para>
         type parameter, this function should be defined as <literal>m: 
           composedType (elemType.substSubModules m)</literal>.</para></listitem>
   </varlistentry>
+  <varlistentry>
+    <term><varname>typeMerge</varname></term>
+    <listitem><para>A function to merge multiple type declarations. Takes the 
+        type to merge <literal>functor</literal> as parameter. A 
+        <literal>null</literal> return value means that type cannot be 
+        merged.</para>
+      <variablelist>
+        <varlistentry>
+          <term><replaceable>f</replaceable></term>
+          <listitem><para>The type to merge  
+              <literal>functor</literal>.</para></listitem>
+        </varlistentry>
+      </variablelist>
+      <para>Note: There is a generic <literal>defaultTypeMerge</literal> that 
+        work with most of value and composed types.</para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term><varname>functor</varname></term>
+    <listitem><para>An attribute set representing the type. It is used for type 
+        operations and has the following keys:</para>
+      <variablelist>
+        <varlistentry>
+          <term><varname>type</varname></term>
+          <listitem><para>The type function.</para></listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><varname>wrapped</varname></term>
+          <listitem><para>Holds the type parameter for composed types.</para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><varname>payload</varname></term>
+          <listitem><para>Holds the value parameter for value types. 
+              The types that have a <literal>payload</literal> are the
+              <literal>enum</literal>, <literal>separatedString</literal> and
+              <literal>submodule</literal> types.</para></listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><varname>binOp</varname></term>
+          <listitem><para>A binary operation that can merge the payloads of two 
+              same types. Defined as a function that take two payloads as 
+              parameters and return the payloads merged.</para></listitem>
+        </varlistentry>
+      </variablelist>
+    </listitem>
+  </varlistentry>
 </variablelist>
 
 </section>
diff --git a/nixos/doc/manual/installation/obtaining.xml b/nixos/doc/manual/installation/obtaining.xml
index f6e8b218e2b3..20a4838be880 100644
--- a/nixos/doc/manual/installation/obtaining.xml
+++ b/nixos/doc/manual/installation/obtaining.xml
@@ -32,7 +32,7 @@ running NixOS system through several other means:
   <listitem>
     <para>Using AMIs for Amazon’s EC2.  To find one for your region
     and instance type, please refer to the <link
-    xlink:href="https://github.com/NixOS/nixops/blob/master/nix/ec2-amis.nix">list
+    xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/ec2-amis.nix">list
     of most recent AMIs</link>.</para>
   </listitem>
   <listitem>
diff --git a/nixos/doc/manual/release-notes/rl-1703.xml b/nixos/doc/manual/release-notes/rl-1703.xml
index efff8b895a1a..743f3dce2302 100644
--- a/nixos/doc/manual/release-notes/rl-1703.xml
+++ b/nixos/doc/manual/release-notes/rl-1703.xml
@@ -75,7 +75,10 @@ following incompatible changes:</para>
 
 <itemizedlist>
   <listitem>
-    <para></para>
+    <para>Module type system have a new extensible option types feature that
+      allow to extend certain types, such as enum, through multiple option
+      declarations of the same option across multiple modules.
+    </para>
   </listitem>
 </itemizedlist>
 
diff --git a/nixos/modules/config/debug-info.nix b/nixos/modules/config/debug-info.nix
index 671a59f52f6d..49991d22a933 100644
--- a/nixos/modules/config/debug-info.nix
+++ b/nixos/modules/config/debug-info.nix
@@ -17,12 +17,10 @@ with lib;
         where tools such as <command>gdb</command> can find them.
         If you need debug symbols for a package that doesn't
         provide them by default, you can enable them as follows:
-        <!-- FIXME: ugly, see #10721 -->
         <programlisting>
         nixpkgs.config.packageOverrides = pkgs: {
-          hello = pkgs.lib.overrideDerivation pkgs.hello (attrs: {
-            outputs = attrs.outputs or ["out"] ++ ["debug"];
-            buildInputs = attrs.buildInputs ++ [&lt;nixpkgs/pkgs/build-support/setup-hooks/separate-debug-info.sh>];
+          hello = pkgs.hello.overrideAttrs (oldAttrs: {
+            separateDebugInfo = true;
           });
         };
         </programlisting>
diff --git a/nixos/modules/config/shells-environment.nix b/nixos/modules/config/shells-environment.nix
index f458bc39adaa..8147fed39d09 100644
--- a/nixos/modules/config/shells-environment.nix
+++ b/nixos/modules/config/shells-environment.nix
@@ -41,7 +41,7 @@ in
         strings.  The latter is concatenated, interspersed with colon
         characters.
       '';
-      type = types.attrsOf (types.loeOf types.str);
+      type = with types; attrsOf (either str (listOf str));
       apply = mapAttrs (n: v: if isList v then concatStringsSep ":" v else v);
     };
 
diff --git a/nixos/modules/config/system-environment.nix b/nixos/modules/config/system-environment.nix
index 3362400326d2..6011e354ece4 100644
--- a/nixos/modules/config/system-environment.nix
+++ b/nixos/modules/config/system-environment.nix
@@ -23,7 +23,7 @@ in
         strings.  The latter is concatenated, interspersed with colon
         characters.
       '';
-      type = types.attrsOf (types.loeOf types.str);
+      type = with types; attrsOf (either str (listOf str));
       apply = mapAttrs (n: v: if isList v then concatStringsSep ":" v else v);
     };
 
diff --git a/nixos/modules/config/system-path.nix b/nixos/modules/config/system-path.nix
index 775d0c39c4fa..3ac5f634c7a6 100644
--- a/nixos/modules/config/system-path.nix
+++ b/nixos/modules/config/system-path.nix
@@ -118,6 +118,7 @@ in
         "/share/terminfo"
         "/share/themes"
         "/share/vim-plugins"
+        "/share/vulkan"
       ];
 
     system.path = pkgs.buildEnv {
diff --git a/nixos/modules/hardware/opengl.nix b/nixos/modules/hardware/opengl.nix
index bef500e30c0b..c4fad9a66725 100644
--- a/nixos/modules/hardware/opengl.nix
+++ b/nixos/modules/hardware/opengl.nix
@@ -135,6 +135,12 @@ in
     environment.sessionVariables.LD_LIBRARY_PATH =
       [ "/run/opengl-driver/lib" "/run/opengl-driver-32/lib" ];
 
+    environment.extraInit = ''
+      export XDG_DATA_DIRS=$XDG_DATA_DIRS:/run/opengl-driver/share
+    '' + optionalString cfg.driSupport32Bit ''
+      export XDG_DATA_DIRS=$XDG_DATA_DIRS:/run/opengl-driver-32/share
+    '';
+
     hardware.opengl.package = mkDefault (makePackage pkgs);
     hardware.opengl.package32 = mkDefault (makePackage pkgs_i686);
 
diff --git a/nixos/modules/hardware/video/amdgpu-pro.nix b/nixos/modules/hardware/video/amdgpu-pro.nix
index 3723d7690dc6..979810abf90a 100644
--- a/nixos/modules/hardware/video/amdgpu-pro.nix
+++ b/nixos/modules/hardware/video/amdgpu-pro.nix
@@ -45,10 +45,8 @@ in
       "amd/amdapfxx.blb".source = package + "/etc/amd/amdapfxx.blb";
       "gbm/gbm.conf".source = package + "/etc/gbm/gbm.conf";
       "OpenCL/vendors/amdocl64.icd".source = package + "/etc/OpenCL/vendors/amdocl64.icd";
-      "vulkan/icd.d/amd_icd64.json".source = package + "/etc/vulkan/icd.d/amd_icd64.json";
     } // optionalAttrs opengl.driSupport32Bit {
       "OpenCL/vendors/amdocl32.icd".source = package32 + "/etc/OpenCL/vendors/amdocl32.icd";
-      "vulkan/icd.d/amd_icd32.json".source = package32 + "/etc/vulkan/icd.d/amd_icd32.json";
     };
 
   };
diff --git a/nixos/modules/installer/tools/nixos-option.sh b/nixos/modules/installer/tools/nixos-option.sh
index 17c17d05e288..27eacda48a87 100644
--- a/nixos/modules/installer/tools/nixos-option.sh
+++ b/nixos/modules/installer/tools/nixos-option.sh
@@ -256,7 +256,7 @@ if isOption opt then
   // optionalAttrs (opt ? default) { inherit (opt) default; }
   // optionalAttrs (opt ? example) { inherit (opt) example; }
   // optionalAttrs (opt ? description) { inherit (opt) description; }
-  // optionalAttrs (opt ? type) { typename = opt.type.name; }
+  // optionalAttrs (opt ? type) { typename = opt.type.description; }
   // optionalAttrs (opt ? options) { inherit (opt) options; }
   // {
     # to disambiguate the xml output.
diff --git a/nixos/modules/installer/virtualbox-demo.nix b/nixos/modules/installer/virtualbox-demo.nix
index 49ec08996104..5316cfce906b 100644
--- a/nixos/modules/installer/virtualbox-demo.nix
+++ b/nixos/modules/installer/virtualbox-demo.nix
@@ -18,5 +18,5 @@ with lib;
 
   # Add some more video drivers to give X11 a shot at working in
   # VMware and QEMU.
-  services.xserver.videoDrivers = mkOverride 40 [ "virtualbox" "vmware" "cirrus" "vesa" ];
+  services.xserver.videoDrivers = mkOverride 40 [ "virtualbox" "vmware" "cirrus" "vesa" "modesetting" ];
 }
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index 8c0f0c2624b1..80a9a520e24e 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -277,6 +277,8 @@
       gitlab-runner = 257;
       postgrey = 258;
       hound = 259;
+      leaps = 260;
+      ipfs  = 261;
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
@@ -524,6 +526,8 @@
       gitlab-runner = 257;
       postgrey = 258;
       hound = 259;
+      leaps = 260;
+      ipfs = 261;
 
       # When adding a gid, make sure it doesn't match an existing
       # uid. Users and groups with the same name should have equal
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 61596265124a..8254ada3ddf7 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -61,6 +61,7 @@
   ./misc/nixpkgs.nix
   ./misc/passthru.nix
   ./misc/version.nix
+  ./programs/adb.nix
   ./programs/atop.nix
   ./programs/bash/bash.nix
   ./programs/blcr.nix
@@ -250,6 +251,7 @@
   ./services/misc/gitolite.nix
   ./services/misc/gpsd.nix
   ./services/misc/ihaskell.nix
+  ./services/misc/leaps.nix
   ./services/misc/mantisbt.nix
   ./services/misc/mathics.nix
   ./services/misc/matrix-synapse.nix
@@ -316,6 +318,7 @@
   ./services/monitoring/zabbix-server.nix
   ./services/network-filesystems/cachefilesd.nix
   ./services/network-filesystems/drbd.nix
+  ./services/network-filesystems/ipfs.nix
   ./services/network-filesystems/netatalk.nix
   ./services/network-filesystems/nfsd.nix
   ./services/network-filesystems/openafs-client/default.nix
diff --git a/nixos/modules/programs/adb.nix b/nixos/modules/programs/adb.nix
new file mode 100644
index 000000000000..9ba81899e588
--- /dev/null
+++ b/nixos/modules/programs/adb.nix
@@ -0,0 +1,30 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+  meta.maintainers = [ maintainers.mic92 ];
+
+  ###### interface
+  options = {
+    programs.adb = {
+      enable = mkOption {
+        default = false;
+        example = true;
+        type = types.bool;
+        description = ''
+          Whether to configure system to use Android Debug Bridge (adb).
+          To grant access to a user, it must be part of adbusers group:
+          <code>users.extraUsers.alice.extraGroups = ["adbusers"];</code>
+        '';
+      };
+    };
+  };
+
+  ###### implementation
+  config = mkIf config.programs.adb.enable {
+    services.udev.packages = [ pkgs.android-udev-rules ];
+    environment.systemPackages = [ pkgs.androidenv.platformTools ];
+    users.extraGroups.adbusers = {};
+  };
+}
diff --git a/nixos/modules/security/grsecurity.nix b/nixos/modules/security/grsecurity.nix
index 7ba25f866f24..53c2ace784ef 100644
--- a/nixos/modules/security/grsecurity.nix
+++ b/nixos/modules/security/grsecurity.nix
@@ -67,9 +67,9 @@ in
     system.requiredKernelConfig = with config.lib.kernelConfig;
       [ (isEnabled "GRKERNSEC")
         (isEnabled "PAX")
-        (isYES "GRKERNSEC_SYSCTL")
-        (isYES "GRKERNSEC_SYSCTL_DISTRO")
-        (isNO "GRKERNSEC_NO_RBAC")
+        (isYes "GRKERNSEC_SYSCTL")
+        (isYes "GRKERNSEC_SYSCTL_DISTRO")
+        (isNo "GRKERNSEC_NO_RBAC")
       ];
 
     nixpkgs.config.grsecurity = true;
diff --git a/nixos/modules/services/cluster/fleet.nix b/nixos/modules/services/cluster/fleet.nix
index 78d4ea93c491..ec03be395948 100644
--- a/nixos/modules/services/cluster/fleet.nix
+++ b/nixos/modules/services/cluster/fleet.nix
@@ -28,7 +28,7 @@ in {
 
     etcdServers = mkOption {
       type = types.listOf types.str;
-      default = [ "http://127.0.0.1:4001" ];
+      default = [ "http://127.0.0.1:2379" ];
       description = ''
         Fleet list of etcd endpoints to use.
       '';
diff --git a/nixos/modules/services/cluster/kubernetes.nix b/nixos/modules/services/cluster/kubernetes.nix
index 4bdd7f95f774..19303e97a706 100644
--- a/nixos/modules/services/cluster/kubernetes.nix
+++ b/nixos/modules/services/cluster/kubernetes.nix
@@ -23,7 +23,7 @@ in {
 
     etcdServers = mkOption {
       description = "Kubernetes list of etcd servers to watch.";
-      default = [ "127.0.0.1:4001" ];
+      default = [ "127.0.0.1:2379" ];
       type = types.listOf types.str;
     };
 
diff --git a/nixos/modules/services/cluster/panamax.nix b/nixos/modules/services/cluster/panamax.nix
index b47ff744fc27..4475e8d8c24b 100644
--- a/nixos/modules/services/cluster/panamax.nix
+++ b/nixos/modules/services/cluster/panamax.nix
@@ -46,7 +46,7 @@ in {
 
     fleetctlEndpoint = mkOption {
       type = types.str;
-      default = "http://127.0.0.1:4001";
+      default = "http://127.0.0.1:2379";
       description = ''
         Panamax fleetctl endpoint.
       '';
diff --git a/nixos/modules/services/editors/emacs.xml b/nixos/modules/services/editors/emacs.xml
index bcaa8b8df3d8..e03f6046de8e 100644
--- a/nixos/modules/services/editors/emacs.xml
+++ b/nixos/modules/services/editors/emacs.xml
@@ -356,14 +356,14 @@ https://nixos.org/nixpkgs/manual/#sec-modify-via-packageOverrides
         <programlisting><![CDATA[
 { pkgs ? import <nixpkgs> {} }:
 let
-  myEmacs = pkgs.lib.overrideDerivation (pkgs.emacs.override {
+  myEmacs = (pkgs.emacs.override {
     # Use gtk3 instead of the default gtk2
     withGTK3 = true;
     withGTK2 = false;
-  }) (attrs: {
+  }).overrideAttrs (attrs: {
     # I don't want emacs.desktop file because I only use
     # emacsclient.
-    postInstall = attrs.postInstall + ''
+    postInstall = (attrs.postInstall or "") + ''
       rm $out/share/applications/emacs.desktop
     '';
   });
diff --git a/nixos/modules/services/games/ghost-one.nix b/nixos/modules/services/games/ghost-one.nix
index 5762148df2bb..71ff6bb2f3f0 100644
--- a/nixos/modules/services/games/ghost-one.nix
+++ b/nixos/modules/services/games/ghost-one.nix
@@ -21,8 +21,7 @@ in
 
       language = mkOption {
         default = "English";
-        type = types.addCheck types.str
-          (lang: elem lang [ "English" "Spanish" "Russian" "Serbian" "Turkish" ]);
+        type = types.enum [ "English" "Spanish" "Russian" "Serbian" "Turkish" ];
         description = "The language of bot messages: English, Spanish, Russian, Serbian or Turkish.";
       };
 
diff --git a/nixos/modules/services/logging/logcheck.nix b/nixos/modules/services/logging/logcheck.nix
index a8a214b21550..27ed5374f561 100644
--- a/nixos/modules/services/logging/logcheck.nix
+++ b/nixos/modules/services/logging/logcheck.nix
@@ -55,9 +55,9 @@ let
 
   levelOption = mkOption {
     default = "server";
-    type = types.str;
+    type = types.enum [ "workstation" "server" "paranoid" ];
     description = ''
-      Set the logcheck level. Either "workstation", "server", or "paranoid".
+      Set the logcheck level.
     '';
   };
 
diff --git a/nixos/modules/services/mail/opensmtpd.nix b/nixos/modules/services/mail/opensmtpd.nix
index 5856b4697553..53acdba42457 100644
--- a/nixos/modules/services/mail/opensmtpd.nix
+++ b/nixos/modules/services/mail/opensmtpd.nix
@@ -115,7 +115,7 @@ in {
         chown smtpq.root /var/spool/smtpd/purge
         chmod 700 /var/spool/smtpd/purge
       '';
-      serviceConfig.ExecStart = "${opensmtpd}/sbin/smtpd -d -f ${conf} ${args}";
+      serviceConfig.ExecStart = "${pkgs.opensmtpd}/sbin/smtpd -d -f ${conf} ${args}";
       environment.OPENSMTPD_PROC_PATH = "${procEnv}/libexec/opensmtpd";
     };
 
diff --git a/nixos/modules/services/misc/dictd.nix b/nixos/modules/services/misc/dictd.nix
index ef744439c3d6..24dca15dd913 100644
--- a/nixos/modules/services/misc/dictd.nix
+++ b/nixos/modules/services/misc/dictd.nix
@@ -2,6 +2,10 @@
 
 with lib;
 
+let
+  cfg = config.services.dictd;
+in
+
 {
 
   ###### interface
@@ -20,7 +24,7 @@ with lib;
 
       DBs = mkOption {
         type = types.listOf types.package;
-        default = [];
+        default = with pkgs.dictdDBs; [ wiktionary wordnet ];
         example = [ pkgs.dictdDBs.nld2eng ];
         description = ''List of databases to make available.'';
       };
@@ -34,8 +38,8 @@ with lib;
 
   config = let dictdb = pkgs.dictDBCollector { dictlist = map (x: {
                name = x.name;
-               filename = x; } ) config.services.dictd.DBs; };
-  in mkIf config.services.dictd.enable {
+               filename = x; } ) cfg.DBs; };
+  in mkIf cfg.enable {
 
     # get the command line client on system path to make some use of the service
     environment.systemPackages = [ pkgs.dict ];
diff --git a/nixos/modules/services/misc/errbot.nix b/nixos/modules/services/misc/errbot.nix
index f573be69925c..427cb7c546d0 100644
--- a/nixos/modules/services/misc/errbot.nix
+++ b/nixos/modules/services/misc/errbot.nix
@@ -8,7 +8,7 @@ let
     name = "errbot-plugins";
     paths = plugins;
   };
-  mkConfigFile = instanceCfg: dataDir: pkgs.writeText "errbot-config.py" ''
+  mkConfigDir = instanceCfg: dataDir: pkgs.writeTextDir "config.py" ''
     import logging
     BACKEND = '${instanceCfg.backend}'
     BOT_DATA_DIR = '${dataDir}'
@@ -93,7 +93,7 @@ in {
       serviceConfig = {
         User = "errbot";
         Restart = "on-failure";
-        ExecStart = "${pkgs.errbot}/bin/errbot -c ${mkConfigFile instanceCfg dataDir}";
+        ExecStart = "${pkgs.errbot}/bin/errbot -c ${mkConfigDir instanceCfg dataDir}/config.py";
         PermissionsStartOnly = true;
       };
     })) cfg.instances;
diff --git a/nixos/modules/services/misc/leaps.nix b/nixos/modules/services/misc/leaps.nix
new file mode 100644
index 000000000000..b92cf27f58dc
--- /dev/null
+++ b/nixos/modules/services/misc/leaps.nix
@@ -0,0 +1,62 @@
+{ config, pkgs, lib, ... } @ args:
+
+with lib;
+
+let
+  cfg = config.services.leaps;
+  stateDir = "/var/lib/leaps/";
+in
+{
+  options = {
+    services.leaps = {
+      enable = mkEnableOption "leaps";
+      port = mkOption {
+        type = types.int;
+        default = 8080;
+        description = "A port where leaps listens for incoming http requests";
+      };
+      address = mkOption {
+        default = "";
+        type = types.str;
+        example = "127.0.0.1";
+        description = "Hostname or IP-address to listen to. By default it will listen on all interfaces.";
+      };
+      path = mkOption {
+        default = "/";
+        type = types.path;
+        description = "Subdirectory used for reverse proxy setups";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    users = {
+      users.leaps = {
+        uid             = config.ids.uids.leaps;
+        description     = "Leaps server user";
+        group           = "leaps";
+        home            = stateDir;
+        createHome      = true;
+      };
+
+      groups.leaps = {
+        gid = config.ids.gids.leaps;
+      };
+    };
+
+    systemd.services.leaps = {
+      description   = "leaps service";
+      wantedBy      = [ "multi-user.target" ];
+      after         = [ "network.target" ];
+
+      serviceConfig = {
+        User = "leaps";
+        Group = "leaps";
+        Restart = "on-failure";
+        WorkingDirectory = stateDir;
+        PrivateTmp = true;
+        ExecStart = "${pkgs.leaps.bin}/bin/leaps -path ${toString cfg.path} -address ${cfg.address}:${toString cfg.port}";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/misc/matrix-synapse.nix b/nixos/modules/services/misc/matrix-synapse.nix
index 4145f8fa957a..277fc9a39022 100644
--- a/nixos/modules/services/misc/matrix-synapse.nix
+++ b/nixos/modules/services/misc/matrix-synapse.nix
@@ -9,11 +9,15 @@ let
   mkListener = l: ''{port: ${toString l.port}, bind_address: "${l.bind_address}", type: ${l.type}, tls: ${fromBool l.tls}, x_forwarded: ${fromBool l.x_forwarded}, resources: [${concatStringsSep "," (map mkResource l.resources)}]}'';
   fromBool = x: if x then "true" else "false";
   configFile = pkgs.writeText "homeserver.yaml" ''
+${optionalString (cfg.tls_certificate_path != null) ''
 tls_certificate_path: "${cfg.tls_certificate_path}"
+''}
 ${optionalString (cfg.tls_private_key_path != null) ''
 tls_private_key_path: "${cfg.tls_private_key_path}"
 ''}
+${optionalString (cfg.tls_dh_params_path != null) ''
 tls_dh_params_path: "${cfg.tls_dh_params_path}"
+''}
 no_tls: ${fromBool cfg.no_tls}
 ${optionalString (cfg.bind_port != null) ''
 bind_port: ${toString cfg.bind_port}
@@ -146,8 +150,9 @@ in {
         '';
       };
       tls_certificate_path = mkOption {
-        type = types.str;
-        default = "/var/lib/matrix-synapse/homeserver.tls.crt";
+        type = types.nullOr types.str;
+        default = null;
+        example = "/var/lib/matrix-synapse/homeserver.tls.crt";
         description = ''
           PEM encoded X509 certificate for TLS.
           You can replace the self-signed certificate that synapse
@@ -158,16 +163,17 @@ in {
       };
       tls_private_key_path = mkOption {
         type = types.nullOr types.str;
-        default = "/var/lib/matrix-synapse/homeserver.tls.key";
-        example = null;
+        default = null;
+        example = "/var/lib/matrix-synapse/homeserver.tls.key";
         description = ''
           PEM encoded private key for TLS. Specify null if synapse is not
           speaking TLS directly.
         '';
       };
       tls_dh_params_path = mkOption {
-        type = types.str;
-        default = "/var/lib/matrix-synapse/homeserver.tls.dh";
+        type = types.nullOr types.str;
+        default = null;
+        example = "/var/lib/matrix-synapse/homeserver.tls.dh";
         description = ''
           PEM dh parameters for ephemeral keys
         '';
@@ -557,12 +563,10 @@ in {
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
       preStart = ''
-        if ! test -e /var/lib/matrix-synapse; then
-          mkdir -p /var/lib/matrix-synapse
-          chmod 700 /var/lib/matrix-synapse
-          chown -R matrix-synapse:matrix-synapse /var/lib/matrix-synapse
-          ${cfg.package}/bin/homeserver --config-path ${configFile} --keys-directory /var/lib/matrix-synapse/ --generate-keys
-        fi
+        ${cfg.package}/bin/homeserver \
+          --config-path ${configFile} \
+          --keys-directory /var/lib/matrix-synapse \
+          --generate-keys
       '';
       serviceConfig = {
         Type = "simple";
@@ -570,7 +574,7 @@ in {
         Group = "matrix-synapse";
         WorkingDirectory = "/var/lib/matrix-synapse";
         PermissionsStartOnly = true;
-        ExecStart = "${cfg.package}/bin/homeserver --config-path ${configFile}";
+        ExecStart = "${cfg.package}/bin/homeserver --config-path ${configFile} --keys-directory /var/lib/matrix-synapse";
       };
     };
   };
diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix
index 333782d15bcb..e2bbd4b01aa1 100644
--- a/nixos/modules/services/misc/nix-daemon.nix
+++ b/nixos/modules/services/misc/nix-daemon.nix
@@ -172,8 +172,8 @@ in
             sshKey = "/root/.ssh/id_buildfarm";
             system = "x86_64-linux";
             maxJobs = 2;
-            supportedFeatures = "kvm";
-            mandatoryFeatures = "perf";
+            supportedFeatures = [ "kvm" ];
+            mandatoryFeatures = [ "perf" ];
           }
         ];
         description = ''
diff --git a/nixos/modules/services/misc/parsoid.nix b/nixos/modules/services/misc/parsoid.nix
index 0844190a5490..ab1b54068772 100644
--- a/nixos/modules/services/misc/parsoid.nix
+++ b/nixos/modules/services/misc/parsoid.nix
@@ -91,7 +91,8 @@ in
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" ];
       serviceConfig = {
-        ExecStart = "${pkgs.nodePackages.parsoid}/lib/node_modules/parsoid/api/server.js -c ${confFile} -n ${toString cfg.workers}";
+        User = "nobody";
+        ExecStart = "${pkgs.nodePackages.parsoid}/lib/node_modules/parsoid/bin/server.js -c ${confFile} -n ${toString cfg.workers}";
       };
     };
 
diff --git a/nixos/modules/services/misc/taskserver/default.nix b/nixos/modules/services/misc/taskserver/default.nix
index 233c47684b7d..ca82a733f6fc 100644
--- a/nixos/modules/services/misc/taskserver/default.nix
+++ b/nixos/modules/services/misc/taskserver/default.nix
@@ -292,7 +292,7 @@ in {
       };
 
       allowedClientIDs = mkOption {
-        type = with types; loeOf (either (enum ["all" "none"]) str);
+        type = with types; either str (listOf str);
         default = [];
         example = [ "[Tt]ask [2-9]+" ];
         description = ''
@@ -306,7 +306,7 @@ in {
       };
 
       disallowedClientIDs = mkOption {
-        type = with types; loeOf (either (enum ["all" "none"]) str);
+        type = with types; either str (listOf str);
         default = [];
         example = [ "[Tt]ask [2-9]+" ];
         description = ''
diff --git a/nixos/modules/services/network-filesystems/ipfs.nix b/nixos/modules/services/network-filesystems/ipfs.nix
new file mode 100644
index 000000000000..c26a70737033
--- /dev/null
+++ b/nixos/modules/services/network-filesystems/ipfs.nix
@@ -0,0 +1,111 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  inherit (pkgs) ipfs;
+
+  cfg = config.services.ipfs;
+
+  ipfsFlags = ''${if cfg.autoMigrate then "--migrate" else ""} ${if cfg.enableGC then "--enable-gc" else ""} ${toString cfg.extraFlags}'';
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.ipfs = {
+
+      enable = mkEnableOption "Interplanetary File System";
+
+      user = mkOption {
+        type = types.str;
+        default = "ipfs";
+        description = "User under which the IPFS daemon runs";
+      };
+
+      group = mkOption {
+        type = types.str;
+        default = "ipfs";
+        description = "Group under which the IPFS daemon runs";
+      };
+
+      dataDir = mkOption {
+        type = types.str;
+        default = "/var/lib/ipfs";
+        description = "The data dir for IPFS";
+      };
+
+      autoMigrate = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether IPFS should try to migrate the file system automatically.
+        '';
+      };
+
+      enableGC = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable automatic garbage collection.
+        '';
+      };
+
+      extraFlags = mkOption {
+        type = types.listOf types.str;
+        description = "Extra flags passed to the IPFS daemon";
+        default = [];
+      };
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.ipfs ];
+
+    users.extraUsers = mkIf (cfg.user == "ipfs") {
+      ipfs = {
+        group = cfg.group;
+        home = cfg.dataDir;
+        createHome = false;
+        uid = config.ids.uids.ipfs;
+        description = "IPFS daemon user";
+      };
+    };
+
+    users.extraGroups = mkIf (cfg.group == "ipfs") {
+      ipfs = {
+        gid = config.ids.gids.ipfs;
+      };
+    };
+
+    systemd.services.ipfs = {
+      description = "IPFS Daemon";
+
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" "local-fs.target" ];
+      path  = [ pkgs.ipfs pkgs.su pkgs.bash ];
+
+      preStart =
+        ''
+          install -m 0755 -o ${cfg.user} -g ${cfg.group} -d ${cfg.dataDir}
+          if [[ ! -d ${cfg.dataDir}/.ipfs ]]; then
+            cd ${cfg.dataDir}
+            ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c "${ipfs}/bin/ipfs init"
+          fi
+        '';
+
+      serviceConfig = {
+        ExecStart = "${ipfs}/bin/ipfs daemon ${ipfsFlags}";
+        User = cfg.user;
+        Group = cfg.group;
+        PermissionsStartOnly = true;
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/network-filesystems/tahoe.nix b/nixos/modules/services/network-filesystems/tahoe.nix
index f1846b963252..f91827c379de 100644
--- a/nixos/modules/services/network-filesystems/tahoe.nix
+++ b/nixos/modules/services/network-filesystems/tahoe.nix
@@ -138,6 +138,45 @@ in
               '';
             };
             helper.enable = mkEnableOption "helper service";
+            sftpd.enable = mkEnableOption "SFTP service";
+            sftpd.port = mkOption {
+              default = null;
+              type = types.nullOr types.int;
+              description = ''
+                The port on which the SFTP server will listen.
+
+                This is the correct setting to tweak if you want Tahoe's SFTP
+                daemon to listen on a different port.
+              '';
+            };
+            sftpd.hostPublicKeyFile = mkOption {
+              default = null;
+              type = types.nullOr types.path;
+              description = ''
+                Path to the SSH host public key.
+              '';
+            };
+            sftpd.hostPrivateKeyFile = mkOption {
+              default = null;
+              type = types.nullOr types.path;
+              description = ''
+                Path to the SSH host private key.
+              '';
+            };
+            sftpd.accounts.file = mkOption {
+              default = null;
+              type = types.nullOr types.path;
+              description = ''
+                Path to the accounts file.
+              '';
+            };
+            sftpd.accounts.url = mkOption {
+              default = null;
+              type = types.nullOr types.str;
+              description = ''
+                URL of the accounts server.
+              '';
+            };
             package = mkOption {
               default = pkgs.tahoelafs;
               defaultText = "pkgs.tahoelafs";
@@ -256,6 +295,19 @@ in
 
                 [helper]
                 enabled = ${if settings.helper.enable then "true" else "false"}
+
+                [sftpd]
+                enabled = ${if settings.sftpd.enable then "true" else "false"}
+                ${optionalString (settings.sftpd.port != null)
+                  "port = ${toString settings.sftpd.port}"}
+                ${optionalString (settings.sftpd.hostPublicKeyFile != null)
+                  "host_pubkey_file = ${settings.sftpd.hostPublicKeyFile}"}
+                ${optionalString (settings.sftpd.hostPrivateKeyFile != null)
+                  "host_privkey_file = ${settings.sftpd.hostPrivateKeyFile}"}
+                ${optionalString (settings.sftpd.accounts.file != null)
+                  "accounts.file = ${settings.sftpd.accounts.file}"}
+                ${optionalString (settings.sftpd.accounts.url != null)
+                  "accounts.url = ${settings.sftpd.accounts.url}"}
               '';
             });
           # Actually require Tahoe, so that we will have it installed.
diff --git a/nixos/modules/services/network-filesystems/yandex-disk.nix b/nixos/modules/services/network-filesystems/yandex-disk.nix
index 982b6ca5ea7b..4de206641331 100644
--- a/nixos/modules/services/network-filesystems/yandex-disk.nix
+++ b/nixos/modules/services/network-filesystems/yandex-disk.nix
@@ -55,6 +55,15 @@ in
         description = "The directory to use for Yandex.Disk storage";
       };
 
+      excludes = mkOption {
+        default = "";
+        type = types.string;
+        example = "data,backup";
+        description = ''
+          Comma-separated list of directories which are excluded from synchronization.
+        '';
+      };
+
     };
 
   };
@@ -86,7 +95,7 @@ in
         chown ${u} ${dir}
 
         if ! test -d "${cfg.directory}" ; then
-          mkdir -p -m 755 ${cfg.directory} ||
+          (mkdir -p -m 755 ${cfg.directory} && chown ${u} ${cfg.directory}) ||
             exit 1
         fi
 
@@ -94,7 +103,7 @@ in
           -c '${pkgs.yandex-disk}/bin/yandex-disk token -p ${cfg.password} ${cfg.username} ${dir}/token'
 
         ${pkgs.su}/bin/su -s ${pkgs.stdenv.shell} ${u} \
-          -c '${pkgs.yandex-disk}/bin/yandex-disk start --no-daemon -a ${dir}/token -d ${cfg.directory}'
+          -c '${pkgs.yandex-disk}/bin/yandex-disk start --no-daemon -a ${dir}/token -d ${cfg.directory} --exclude-dirs=${cfg.excludes}'
       '';
 
     };
diff --git a/nixos/modules/services/networking/bitlbee.nix b/nixos/modules/services/networking/bitlbee.nix
index 5e6847097a94..e72ea20cccee 100644
--- a/nixos/modules/services/networking/bitlbee.nix
+++ b/nixos/modules/services/networking/bitlbee.nix
@@ -7,11 +7,6 @@ let
   cfg = config.services.bitlbee;
   bitlbeeUid = config.ids.uids.bitlbee;
 
-  authModeCheck = v:
-    v == "Open" ||
-    v == "Closed" ||
-    v == "Registered";
-
   bitlbeeConfig = pkgs.writeText "bitlbee.conf"
     ''
     [settings]
@@ -67,7 +62,7 @@ in
 
       authMode = mkOption {
         default = "Open";
-        type = types.addCheck types.str authModeCheck;
+        type = types.enum [ "Open" "Closed" "Registered" ];
         description = ''
           The following authentication modes are available:
             Open -- Accept connections from anyone, use NickServ for user authentication.
diff --git a/nixos/modules/services/networking/cjdns.nix b/nixos/modules/services/networking/cjdns.nix
index 5e15e40ea0c1..7e981183353d 100644
--- a/nixos/modules/services/networking/cjdns.nix
+++ b/nixos/modules/services/networking/cjdns.nix
@@ -36,7 +36,7 @@ let
       echo \'\'
       ${concatStringsSep "\n" (mapAttrsToList (k: v:
           optionalString (v.hostname != "")
-            "echo $(${pkgs.cjdns}/bin/publictoip6 ${x.key}) ${x.host}")
+            "echo $(${pkgs.cjdns}/bin/publictoip6 ${v.publicKey}) ${v.hostname}")
           (cfg.ETHInterface.connectTo // cfg.UDPInterface.connectTo))}
       echo \'\'
     '');
@@ -245,7 +245,10 @@ in
       serviceConfig = {
         Type = "forking";
         Restart = "on-failure";
-
+        CapabilityBoundingSet = "CAP_NET_ADMIN CAP_NET_RAW";
+        AmbientCapabilities = "CAP_NET_ADMIN CAP_NET_RAW";
+        ProtectSystem = "full";
+        MemoryDenyWriteExecute = true;
         ProtectHome = true;
         PrivateTmp = true;
       };
diff --git a/nixos/modules/services/networking/dnscrypt-proxy.nix b/nixos/modules/services/networking/dnscrypt-proxy.nix
index 5a24db8ccba0..82bf178f4cb7 100644
--- a/nixos/modules/services/networking/dnscrypt-proxy.nix
+++ b/nixos/modules/services/networking/dnscrypt-proxy.nix
@@ -5,15 +5,25 @@ let
   apparmorEnabled = config.security.apparmor.enable;
   dnscrypt-proxy = pkgs.dnscrypt-proxy;
   cfg = config.services.dnscrypt-proxy;
+  stateDirectory = "/var/lib/dnscrypt-proxy";
 
   localAddress = "${cfg.localAddress}:${toString cfg.localPort}";
 
-  daemonArgs =
-    [ "--local-address=${localAddress}"
-      (optionalString cfg.tcpOnly "--tcp-only")
-      (optionalString cfg.ephemeralKeys "-E")
-    ]
-    ++ resolverArgs;
+  # The minisign public key used to sign the upstream resolver list.
+  # This is somewhat more flexible than preloading the key as an
+  # embedded string.
+  upstreamResolverListPubKey = pkgs.fetchurl {
+    url = https://raw.githubusercontent.com/jedisct1/dnscrypt-proxy/master/minisign.pub;
+    sha256 = "18lnp8qr6ghfc2sd46nn1rhcpr324fqlvgsp4zaigw396cd7vnnh";
+  };
+
+  # Internal flag indicating whether the upstream resolver list is used
+  useUpstreamResolverList = cfg.resolverList == null && cfg.customResolver == null;
+
+  resolverList =
+    if (cfg.resolverList != null)
+      then cfg.resolverList
+      else "${stateDirectory}/dnscrypt-resolvers.csv";
 
   resolverArgs = if (cfg.customResolver != null)
     then
@@ -22,9 +32,16 @@ let
         "--provider-key=${cfg.customResolver.key}"
       ]
     else
-      [ "--resolvers-list=${cfg.resolverList}"
-        "--resolver-name=${toString cfg.resolverName}"
+      [ "--resolvers-list=${resolverList}"
+        "--resolver-name=${cfg.resolverName}"
       ];
+
+  # The final command line arguments passed to the daemon
+  daemonArgs =
+    [ "--local-address=${localAddress}" ]
+    ++ optional cfg.tcpOnly "--tcp-only"
+    ++ optional cfg.ephemeralKeys "-E"
+    ++ resolverArgs;
 in
 
 {
@@ -66,24 +83,20 @@ in
         default = "dnscrypt.eu-nl";
         type = types.nullOr types.str;
         description = ''
-          The name of the upstream DNSCrypt resolver to use, taken from the
-          list named in the <literal>resolverList</literal> option.
-          The default resolver is located in Holland, supports DNS security
-          extensions, and claims to not keep logs.
+          The name of the upstream DNSCrypt resolver to use, taken from
+          <filename>${resolverList}</filename>.  The default resolver is
+          located in Holland, supports DNS security extensions, and
+          <emphasis>claims</emphasis> to not keep logs.
         '';
       };
 
       resolverList = mkOption {
+        default = null;
+        type = types.nullOr types.path;
         description = ''
-          The list of upstream DNSCrypt resolvers. By default, we use the most
-          recent list published by upstream.
+          List of DNSCrypt resolvers.  The default is to use the list of
+          public resolvers provided by upstream.
         '';
-        example = literalExample "${pkgs.dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv";
-        default = pkgs.fetchurl {
-          url = https://raw.githubusercontent.com/jedisct1/dnscrypt-proxy/master/dnscrypt-resolvers.csv;
-          sha256 = "1i9wzw4zl052h5nyp28bwl8d66cgj0awvjhw5wgwz0warkjl1g8g";
-        };
-        defaultText = "pkgs.fetchurl { url = ...; sha256 = ...; }";
       };
 
       customResolver = mkOption {
@@ -150,7 +163,7 @@ in
       }
     ];
 
-    security.apparmor.profiles = mkIf apparmorEnabled (singleton (pkgs.writeText "apparmor-dnscrypt-proxy" ''
+    security.apparmor.profiles = optional apparmorEnabled (pkgs.writeText "apparmor-dnscrypt-proxy" ''
       ${dnscrypt-proxy}/bin/dnscrypt-proxy {
         /dev/null rw,
         /dev/urandom r,
@@ -177,9 +190,9 @@ in
         ${getLib pkgs.lz4}/lib/liblz4.so.* mr,
         ${getLib pkgs.attr}/lib/libattr.so.* mr,
 
-        ${cfg.resolverList} r,
+        ${resolverList} r,
       }
-    ''));
+    '');
 
     users.users.dnscrypt-proxy = {
       description = "dnscrypt-proxy daemon user";
@@ -188,11 +201,61 @@ in
     };
     users.groups.dnscrypt-proxy = {};
 
+    systemd.services.init-dnscrypt-proxy-statedir = optionalAttrs useUpstreamResolverList {
+      description = "Initialize dnscrypt-proxy state directory";
+      script = ''
+        mkdir -pv ${stateDirectory}
+        chown -c dnscrypt-proxy:dnscrypt-proxy ${stateDirectory}
+        cp --preserve=timestamps -uv \
+          ${pkgs.dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv \
+          ${stateDirectory}
+      '';
+      serviceConfig = {
+        Type = "oneshot";
+        RemainAfterExit = true;
+      };
+    };
+
+    systemd.services.update-dnscrypt-resolvers = optionalAttrs useUpstreamResolverList {
+      description = "Update list of DNSCrypt resolvers";
+
+      requires = [ "init-dnscrypt-proxy-statedir.service" ];
+      after = [ "init-dnscrypt-proxy-statedir.service" ];
+
+      path = with pkgs; [ curl minisign ];
+      script = ''
+        cd ${stateDirectory}
+        curl -fSsL -o dnscrypt-resolvers.csv.tmp \
+          https://download.dnscrypt.org/dnscrypt-proxy/dnscrypt-resolvers.csv
+        curl -fSsL -o dnscrypt-resolvers.csv.minisig.tmp \
+          https://download.dnscrypt.org/dnscrypt-proxy/dnscrypt-resolvers.csv.minisig
+        mv dnscrypt-resolvers.csv.minisig{.tmp,}
+        minisign -q -V -p ${upstreamResolverListPubKey} \
+          -m dnscrypt-resolvers.csv.tmp -x dnscrypt-resolvers.csv.minisig
+        mv dnscrypt-resolvers.csv{.tmp,}
+      '';
+
+      serviceConfig = {
+        PrivateTmp = true;
+        PrivateDevices = true;
+        ProtectHome = true;
+        ProtectSystem = true;
+      };
+    };
+
+    systemd.timers.update-dnscrypt-resolvers = optionalAttrs useUpstreamResolverList {
+      timerConfig = {
+        OnBootSec = "5min";
+        OnUnitActiveSec = "6h";
+      };
+      wantedBy = [ "timers.target" ];
+    };
+
     systemd.sockets.dnscrypt-proxy = {
       description = "dnscrypt-proxy listening socket";
       socketConfig = {
-        ListenStream = "${localAddress}";
-        ListenDatagram = "${localAddress}";
+        ListenStream = localAddress;
+        ListenDatagram = localAddress;
       };
       wantedBy = [ "sockets.target" ];
     };
@@ -200,8 +263,13 @@ in
     systemd.services.dnscrypt-proxy = {
       description = "dnscrypt-proxy daemon";
 
-      after = [ "network.target" ] ++ optional apparmorEnabled "apparmor.service";
-      requires = [ "dnscrypt-proxy.socket "] ++ optional apparmorEnabled "apparmor.service";
+      after = [ "network.target" ]
+        ++ optional apparmorEnabled "apparmor.service"
+        ++ optional useUpstreamResolverList "init-dnscrypt-proxy-statedir.service";
+
+      requires = [ "dnscrypt-proxy.socket "]
+        ++ optional apparmorEnabled "apparmor.service"
+        ++ optional useUpstreamResolverList "init-dnscrypt-proxy-statedir.service";
 
       serviceConfig = {
         Type = "simple";
diff --git a/nixos/modules/services/networking/i2pd.nix b/nixos/modules/services/networking/i2pd.nix
index 926857a0ff4e..578376764eba 100644
--- a/nixos/modules/services/networking/i2pd.nix
+++ b/nixos/modules/services/networking/i2pd.nix
@@ -10,7 +10,7 @@ let
 
   extip = "EXTIP=\$(${pkgs.curl.bin}/bin/curl -sf \"http://jsonip.com\" | ${pkgs.gawk}/bin/awk -F'\"' '{print $4}')";
 
-  toYesNo = b: if b then "yes" else "no";
+  toYesNo = b: if b then "true" else "false";
 
   mkEndpointOpt = name: addr: port: {
     enable = mkEnableOption name;
@@ -31,6 +31,17 @@ let
     };
   };
 
+  mkKeyedEndpointOpt = name: addr: port: keyFile:
+  (mkEndpointOpt name addr port) // {
+    keys = mkOption {
+      type = types.str;
+      default = "";
+      description = ''
+        File to persist ${lib.toUpper name} keys.
+      '';
+    };
+  };
+
   commonTunOpts = let
     i2cpOpts = {
       length = mkOption {
@@ -63,19 +74,49 @@ let
     };
   } // mkEndpointOpt name "127.0.0.1" 0;
 
-  i2pdConf = pkgs.writeText "i2pd.conf" ''
-      ipv6 = ${toYesNo cfg.enableIPv6}
-      notransit = ${toYesNo cfg.notransit}
-      floodfill = ${toYesNo cfg.floodfill}
-      ${if isNull cfg.port then "" else "port = ${toString cfg.port}"}
-      ${flip concatMapStrings
-        (collect (proto: proto ? port && proto ? address && proto ? name) cfg.proto)
-        (proto: let portStr = toString proto.port; in ''
-      [${proto.name}]
-      address = ${proto.address}
-      port = ${toString proto.port}
-      enabled = ${toYesNo proto.enable}
-      '')
+  i2pdConf = pkgs.writeText "i2pd.conf"
+  ''
+  ipv4 = ${toYesNo cfg.enableIPv4}
+  ipv6 = ${toYesNo cfg.enableIPv6}
+  notransit = ${toYesNo cfg.notransit}
+  floodfill = ${toYesNo cfg.floodfill}
+  netid = ${toString cfg.netid}
+  ${if isNull cfg.bandwidth then "" else "bandwidth = ${toString cfg.bandwidth}" }
+  ${if isNull cfg.port then "" else "port = ${toString cfg.port}"}
+
+  [limits]
+  transittunnels = ${toString cfg.limits.transittunnels}
+
+  [upnp]
+  enabled = ${toYesNo cfg.upnp.enable}
+  name = ${cfg.upnp.name}
+
+  [precomputation]
+  elgamal = ${toYesNo cfg.precomputation.elgamal}
+
+  [reseed]
+  verify = ${toYesNo cfg.reseed.verify}
+  file = ${cfg.reseed.file}
+  urls = ${builtins.concatStringsSep "," cfg.reseed.urls}
+
+  [addressbook]
+  defaulturl = ${cfg.addressbook.defaulturl}
+  subscriptions = ${builtins.concatStringsSep "," cfg.addressbook.subscriptions}
+  ${flip concatMapStrings
+      (collect (proto: proto ? port && proto ? address && proto ? name) cfg.proto)
+      (proto: let portStr = toString proto.port; in
+        ''
+          [${proto.name}]
+          enabled = ${toYesNo proto.enable}
+          address = ${proto.address}
+          port = ${toString proto.port}
+          ${if proto ? keys then "keys = ${proto.keys}" else ""}
+          ${if proto ? auth then "auth = ${toYesNo proto.auth}" else ""}
+          ${if proto ? user then "user = ${proto.user}" else ""}
+          ${if proto ? pass then "pass = ${proto.pass}" else ""}
+          ${if proto ? outproxy then "outproxy = ${proto.outproxy}" else ""}
+          ${if proto ? outproxyPort then "outproxyport = ${toString proto.outproxyPort}" else ""}
+        '')
       }
   '';
 
@@ -114,7 +155,7 @@ let
   i2pdSh = pkgs.writeScriptBin "i2pd" ''
     #!/bin/sh
     ${if isNull cfg.extIp then extip else ""}
-    ${pkgs.i2pd}/bin/i2pd --log=1 \
+    ${pkgs.i2pd}/bin/i2pd \
       --host=${if isNull cfg.extIp then "$EXTIP" else cfg.extIp} \
       --conf=${i2pdConf} \
       --tunconf=${i2pdTunnelConf}
@@ -135,6 +176,8 @@ in
         default = false;
         description = ''
           Enables I2Pd as a running service upon activation.
+          Please read http://i2pd.readthedocs.io/en/latest/ for further
+          configuration help.
         '';
       };
 
@@ -162,6 +205,22 @@ in
         '';
       };
 
+      netid = mkOption {
+        type = types.int;
+        default = 2;
+        description = ''
+          I2P overlay netid.
+        '';
+      };
+
+      bandwidth = mkOption {
+        type = with types; nullOr int;
+        default = null;
+        description = ''
+           Set a router bandwidth limit integer in kbps or letters: L (32), O (256), P (2048), X (>9000)
+        '';
+      };
+
       port = mkOption {
         type = with types; nullOr int;
         default = null;
@@ -170,6 +229,14 @@ in
         '';
       };
 
+      enableIPv4 = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Enables IPv4 connectivity. Enabled by default.
+        '';
+      };
+
       enableIPv6 = mkOption {
         type = types.bool;
         default = false;
@@ -178,16 +245,141 @@ in
         '';
       };
 
-      proto.http = mkEndpointOpt "http" "127.0.0.1" 7070;
+      upnp = {
+        enable = mkOption {
+          type = types.bool;
+          default = false;
+          description = ''
+            Enables UPnP.
+          '';
+        };
+
+        name = mkOption {
+          type = types.str;
+          default = "I2Pd";
+          description = ''
+            Name i2pd appears in UPnP forwardings list.
+          '';
+        };
+      };
+
+      precomputation.elgamal = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Use ElGamal precomputated tables.
+        '';
+      };
+
+      reseed = {
+        verify = mkOption {
+          type = types.bool;
+          default = false;
+          description = ''
+            Request SU3 signature verification
+          '';
+        };
+
+        file = mkOption {
+          type = types.str;
+          default = "";
+          description = ''
+            Full path to SU3 file to reseed from
+          '';
+        };
+
+        urls = mkOption {
+          type = with types; listOf str;
+          default = [
+            "https://reseed.i2p-project.de/"
+            "https://i2p.mooo.com/netDb/"
+            "https://netdb.i2p2.no/"
+            "https://us.reseed.i2p2.no:444/"
+            "https://uk.reseed.i2p2.no:444/"
+            "https://i2p.manas.ca:8443/"
+          ];
+          description = ''
+            Reseed URLs
+          '';
+        };
+      };
+
+      addressbook = {
+       defaulturl = mkOption {
+          type = types.str;
+          default = "http://joajgazyztfssty4w2on5oaqksz6tqoxbduy553y34mf4byv6gpq.b32.i2p/export/alive-hosts.txt";
+          description = ''
+            AddressBook subscription URL for initial setup
+          '';
+        };
+       subscriptions = mkOption {
+          type = with types; listOf str;
+          default = [
+            "http://inr.i2p/export/alive-hosts.txt"
+            "http://i2p-projekt.i2p/hosts.txt"
+            "http://stats.i2p/cgi-bin/newhosts.txt"
+          ];
+          description = ''
+            AddressBook subscription URLs
+          '';
+        };
+      };
+
+      limits.transittunnels = mkOption {
+        type = types.int;
+        default = 2500;
+        description = ''
+          Maximum number of active transit sessions
+        '';
+      };
+
+      proto.http = (mkEndpointOpt "http" "127.0.0.1" 7070) // {
+        auth = mkOption {
+          type = types.bool;
+          default = false;
+          description = ''
+            Enable authentication for webconsole.
+          '';
+        };
+        user = mkOption {
+          type = types.str;
+          default = "i2pd";
+          description = ''
+            Username for webconsole access
+          '';
+        };
+        pass = mkOption {
+          type = types.str;
+          default = "i2pd";
+          description = ''
+            Password for webconsole access.
+          '';
+        };
+      };
+
+      proto.httpProxy = mkKeyedEndpointOpt "httpproxy" "127.0.0.1" 4446 "";
+      proto.socksProxy = (mkKeyedEndpointOpt "socksproxy" "127.0.0.1" 4447 "")
+      // {
+        outproxy = mkOption {
+          type = types.str;
+          default = "127.0.0.1";
+          description = "Upstream outproxy bind address.";
+        };
+        outproxyPort = mkOption {
+          type = types.int;
+          default = 4444;
+          description = "Upstream outproxy bind port.";
+        };
+      };
+
       proto.sam = mkEndpointOpt "sam" "127.0.0.1" 7656;
       proto.bob = mkEndpointOpt "bob" "127.0.0.1" 2827;
+      proto.i2cp = mkEndpointOpt "i2cp" "127.0.0.1" 7654;
       proto.i2pControl = mkEndpointOpt "i2pcontrol" "127.0.0.1" 7650;
-      proto.httpProxy = mkEndpointOpt "httpproxy" "127.0.0.1" 4446;
-      proto.socksProxy = mkEndpointOpt "socksproxy" "127.0.0.1" 4447;
 
       outTunnels = mkOption {
         default = {};
-        type = with types; loaOf (submodule ( 
+        type = with types; loaOf (submodule (
           { name, config, ... }: {
             options = commonTunOpts name;
             config = {
diff --git a/nixos/modules/services/networking/nsd.nix b/nixos/modules/services/networking/nsd.nix
index 6af1dd736431..ccfd219620cf 100644
--- a/nixos/modules/services/networking/nsd.nix
+++ b/nixos/modules/services/networking/nsd.nix
@@ -118,8 +118,8 @@ let
   '';
 
   yesOrNo = b: if b then "yes" else "no";
-  maybeString = prefix: x: if x == null then "" else ''${prefix} "${s}"'';
-  maybeToString = prefix: x: if x == null then "" else ''${prefix} ${toString s}'';
+  maybeString = prefix: x: if x == null then "" else ''${prefix} "${x}"'';
+  maybeToString = prefix: x: if x == null then "" else ''${prefix} ${toString x}'';
   forEach = pre: l: concatMapStrings (x: pre + x + "\n") l;
 
 
diff --git a/nixos/modules/services/networking/quassel.nix b/nixos/modules/services/networking/quassel.nix
index 99269c49e8f1..3f0906fdb80d 100644
--- a/nixos/modules/services/networking/quassel.nix
+++ b/nixos/modules/services/networking/quassel.nix
@@ -3,8 +3,8 @@
 with lib;
 
 let
-  quassel = pkgs.kde4.quasselDaemon;
   cfg = config.services.quassel;
+  quassel = cfg.package;
   user = if cfg.user != null then cfg.user else "quassel";
 in
 
@@ -23,6 +23,15 @@ in
         '';
       };
 
+      package = mkOption {
+        type = types.package;
+        default = pkgs.kde4.quasselDaemon;
+        description = ''
+          The package of the quassel daemon.
+        '';
+        example = pkgs.quasselDaemon;
+      };
+
       interfaces = mkOption {
         default = [ "127.0.0.1" ];
         description = ''
diff --git a/nixos/modules/services/networking/skydns.nix b/nixos/modules/services/networking/skydns.nix
index ba913482e3cb..6ad18bb22403 100644
--- a/nixos/modules/services/networking/skydns.nix
+++ b/nixos/modules/services/networking/skydns.nix
@@ -11,7 +11,7 @@ in {
 
     etcd = {
       machines = mkOption {
-        default = [ "http://localhost:4001" ];
+        default = [ "http://127.0.0.1:2379" ];
         type = types.listOf types.str;
         description = "Skydns list of etcd endpoints to connect to.";
       };
diff --git a/nixos/modules/services/networking/smokeping.nix b/nixos/modules/services/networking/smokeping.nix
index 0c1f8d8cdb91..005655f111a1 100644
--- a/nixos/modules/services/networking/smokeping.nix
+++ b/nixos/modules/services/networking/smokeping.nix
@@ -221,7 +221,7 @@ in
         type = types.string;
         default = ''
           + FPing
-          binary = ${pkgs.fping}/bin/fping
+          binary = ${config.security.wrapperDir}/fping
         '';
         description = "Probe configuration";
       };
@@ -284,10 +284,10 @@ in
         mkdir -m 0755 -p ${smokepingHome}/cache ${smokepingHome}/data
         rm -f ${smokepingHome}/cropper
         ln -s ${cfg.package}/htdocs/cropper ${smokepingHome}/cropper
-        chown -R ${cfg.user} ${smokepingHome}
         cp ${cgiHome} ${smokepingHome}/smokeping.fcgi
         ${cfg.package}/bin/smokeping --check --config=${configPath}
         ${cfg.package}/bin/smokeping --static --config=${configPath}
+        chown -R ${cfg.user} ${smokepingHome}
       '';
       script = ''${cfg.package}/bin/smokeping --config=${configPath} --nodaemon'';
     };
diff --git a/nixos/modules/services/networking/tinc.nix b/nixos/modules/services/networking/tinc.nix
index b26d30597b1f..f8e68fda7fc2 100644
--- a/nixos/modules/services/networking/tinc.nix
+++ b/nixos/modules/services/networking/tinc.nix
@@ -68,7 +68,7 @@ in
 
             interfaceType = mkOption {
               default = "tun";
-              type = types.addCheck types.str (n: n == "tun" || n == "tap");
+              type = types.enum [ "tun" "tap" ];
               description = ''
                 The type of virtual interface used for the network connection
               '';
diff --git a/nixos/modules/services/networking/vsftpd.nix b/nixos/modules/services/networking/vsftpd.nix
index 7ec484941ede..deff645d9bfd 100644
--- a/nixos/modules/services/networking/vsftpd.nix
+++ b/nixos/modules/services/networking/vsftpd.nix
@@ -100,6 +100,10 @@ let
         seccomp_sandbox=NO
       ''}
       anon_umask=${cfg.anonymousUmask}
+      ${optionalString cfg.anonymousUser ''
+        anon_root=${cfg.anonymousUserHome}
+      ''}
+      ${cfg.extraConfig}
     '';
 
 in
@@ -163,6 +167,13 @@ in
         description = "Anonymous write umask.";
       };
 
+      extraConfig = mkOption {
+        type = types.lines;
+        default = "";
+        example = "ftpd_banner=Hello";
+        description = "Extra configuration to add at the bottom of the generated configuration file.";
+      };
+
     } // (listToAttrs (catAttrs "nixosOption" optionDescription));
 
   };
diff --git a/nixos/modules/services/networking/znc.nix b/nixos/modules/services/networking/znc.nix
index 676e82aa8937..76ba78ff366f 100644
--- a/nixos/modules/services/networking/znc.nix
+++ b/nixos/modules/services/networking/znc.nix
@@ -208,11 +208,10 @@ in
 
         networks = mkOption {
           default = { };
-          type = types.loaOf types.optionSet;
+          type = with types; loaOf (submodule networkOpts);
           description = ''
             IRC networks to connect the user to.
           '';
-          options = [ networkOpts ];
           example = {
             "freenode" = {
               server = "chat.freenode.net";
diff --git a/nixos/modules/services/search/hound.nix b/nixos/modules/services/search/hound.nix
index 708f57a5eb7c..1226cba682ec 100644
--- a/nixos/modules/services/search/hound.nix
+++ b/nixos/modules/services/search/hound.nix
@@ -116,7 +116,7 @@ in {
                     " -conf ${pkgs.writeText "hound.json" cfg.config}";
 
       };
-      path = [ pkgs.git ];
+      path = [ pkgs.git pkgs.mercurial pkgs.openssh ];
     };
   };
 
diff --git a/nixos/modules/services/security/clamav.nix b/nixos/modules/services/security/clamav.nix
index e4e5c1253b77..89ac1c01f521 100644
--- a/nixos/modules/services/security/clamav.nix
+++ b/nixos/modules/services/security/clamav.nix
@@ -16,7 +16,7 @@ let
 
     ${cfg.daemon.extraConfig}
   '';
-  pkg = pkgs.clamav.override { freshclamConf = cfg.updater.config; };
+  pkg = pkgs.clamav;
 in
 {
   options = {
diff --git a/nixos/modules/services/web-servers/fcgiwrap.nix b/nixos/modules/services/web-servers/fcgiwrap.nix
index 2c5e433003c8..a64a187255a4 100644
--- a/nixos/modules/services/web-servers/fcgiwrap.nix
+++ b/nixos/modules/services/web-servers/fcgiwrap.nix
@@ -21,7 +21,7 @@ in {
       };
 
       socketType = mkOption {
-        type = types.addCheck types.str (t: t == "unix" || t == "tcp" || t == "tcp6");
+        type = types.enum [ "unix" "tcp" "tcp6" ];
         default = "unix";
         description = "Socket type: 'unix', 'tcp' or 'tcp6'.";
       };
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index 166e5a6b2cea..698d37133d74 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -138,7 +138,7 @@ let
             server_name ${serverName} ${concatStringsSep " " vhost.serverAliases};
             ${acmeLocation}
             location / {
-              return 301 https://$host${optionalString (port != 443) ":${port}"}$request_uri;
+              return 301 https://$host${optionalString (port != 443) ":${toString port}"}$request_uri;
             }
           }
         ''}
diff --git a/nixos/modules/services/x11/desktop-managers/default.nix b/nixos/modules/services/x11/desktop-managers/default.nix
index 31412ae70142..144e4aada277 100644
--- a/nixos/modules/services/x11/desktop-managers/default.nix
+++ b/nixos/modules/services/x11/desktop-managers/default.nix
@@ -19,7 +19,8 @@ in
   # E.g., if KDE is enabled, it supersedes xterm.
   imports = [
     ./none.nix ./xterm.nix ./xfce.nix ./kde4.nix ./kde5.nix
-    ./lxqt.nix ./enlightenment.nix ./gnome3.nix ./kodi.nix
+    ./lumina.nix ./lxqt.nix ./enlightenment.nix ./gnome3.nix
+    ./kodi.nix
   ];
 
   options = {
diff --git a/nixos/modules/services/x11/desktop-managers/lumina.nix b/nixos/modules/services/x11/desktop-managers/lumina.nix
new file mode 100644
index 000000000000..f0b31a2acb01
--- /dev/null
+++ b/nixos/modules/services/x11/desktop-managers/lumina.nix
@@ -0,0 +1,52 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  xcfg = config.services.xserver;
+  cfg = xcfg.desktopManager.lumina;
+
+in
+
+{
+  options = {
+
+    services.xserver.desktopManager.lumina.enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = "Enable the Lumina desktop manager";
+    };
+
+  };
+
+
+  config = mkIf (xcfg.enable && cfg.enable) {
+
+    services.xserver.desktopManager.session = singleton {
+      name = "lumina";
+      start = ''
+        exec ${pkgs.lumina}/bin/start-lumina-desktop
+      '';
+    };
+
+    environment.systemPackages = [
+      pkgs.fluxbox
+      pkgs.kde5.kwindowsystem
+      pkgs.kde5.oxygen-icons5
+      pkgs.lumina
+      pkgs.numlockx
+      pkgs.qt5.qtsvg
+      pkgs.xscreensaver
+    ];
+
+    # Link some extra directories in /run/current-system/software/share
+    environment.pathsToLink = [
+      "/share/desktop-directories"
+      "/share/icons"
+      "/share/lumina"
+      "/share"
+    ];
+
+  };
+}
diff --git a/nixos/modules/services/x11/desktop-managers/lxqt.nix b/nixos/modules/services/x11/desktop-managers/lxqt.nix
index d13b7352c95e..c385e74dbb2f 100644
--- a/nixos/modules/services/x11/desktop-managers/lxqt.nix
+++ b/nixos/modules/services/x11/desktop-managers/lxqt.nix
@@ -25,6 +25,7 @@ in
 
     services.xserver.desktopManager.session = singleton {
       name = "lxqt";
+      bgSupport = true;
       start = ''
         exec ${pkgs.lxqt.lxqt-common}/bin/startlxqt
       '';
diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix
index c3be7407d592..17c842ddc533 100644
--- a/nixos/modules/system/boot/loader/grub/grub.nix
+++ b/nixos/modules/system/boot/loader/grub/grub.nix
@@ -324,8 +324,7 @@ in
 
       fsIdentifier = mkOption {
         default = "uuid";
-        type = types.addCheck types.str
-          (type: type == "uuid" || type == "label" || type == "provided");
+        type = types.enum [ "uuid" "label" "provided" ];
         description = ''
           Determines how GRUB will identify devices when generating the
           configuration file. A value of uuid / label signifies that grub
diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix
index aae4dc5fdadf..1faa8abd5f7f 100644
--- a/nixos/modules/tasks/network-interfaces.nix
+++ b/nixos/modules/tasks/network-interfaces.nix
@@ -245,7 +245,7 @@ let
 
       virtualType = mkOption {
         default = null;
-        type = types.nullOr (types.addCheck types.str (v: v == "tun" || v == "tap"));
+        type = with types; nullOr (enum [ "tun" "tap" ]);
         description = ''
           The explicit type of interface to create. Accepts tun or tap strings.
           Also accepts null to implicitly detect the type of device.
diff --git a/nixos/modules/virtualisation/libvirtd.nix b/nixos/modules/virtualisation/libvirtd.nix
index ea503a9526f8..5f669dee7545 100644
--- a/nixos/modules/virtualisation/libvirtd.nix
+++ b/nixos/modules/virtualisation/libvirtd.nix
@@ -123,7 +123,7 @@ in {
         # config file. But this path can unfortunately be garbage collected
         # while still being used by the virtual machine. So update the
         # emulator path on each startup to something valid (re-scan $PATH).
-        for file in /etc/libvirt/qemu/*.xml /etc/libvirt/lxc/*.xml; do
+        for file in /var/lib/libvirt/qemu/*.xml /var/lib/libvirt/lxc/*.xml; do
             test -f "$file" || continue
             # get (old) emulator path from config file
             emulator=$(grep "^[[:space:]]*<emulator>" "$file" | sed 's,^[[:space:]]*<emulator>\(.*\)</emulator>.*,\1,')
diff --git a/nixos/release.nix b/nixos/release.nix
index fbd3efd16ff0..639ee45b38d6 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -275,6 +275,7 @@ in rec {
   tests.networkingProxy = callTest tests/networking-proxy.nix {};
   tests.nfs3 = callTest tests/nfs.nix { version = 3; };
   tests.nfs4 = callTest tests/nfs.nix { version = 4; };
+  tests.leaps = callTest tests/leaps.nix { };
   tests.nsd = callTest tests/nsd.nix {};
   tests.openssh = callTest tests/openssh.nix {};
   #tests.panamax = hydraJob (import tests/panamax.nix { system = "x86_64-linux"; });
diff --git a/nixos/tests/chromium.nix b/nixos/tests/chromium.nix
index 9a6414f81c39..55b1fb5a7222 100644
--- a/nixos/tests/chromium.nix
+++ b/nixos/tests/chromium.nix
@@ -118,7 +118,7 @@ mapAttrs (channel: chromiumPkg: makeTest rec {
       "ulimit -c unlimited; ".
       "chromium $args \"$url\" & disown"
     );
-    $machine->waitForText(qr/Type to search or enter a URL to navigate/);
+    $machine->waitForText(qr/startup done/);
     $machine->waitUntilSucceeds("${xdo "check-startup" ''
       search --sync --onlyvisible --name "startup done"
       # close first start help popup
diff --git a/nixos/tests/cjdns.nix b/nixos/tests/cjdns.nix
index f61c82b916ad..f32ec52dfc26 100644
--- a/nixos/tests/cjdns.nix
+++ b/nixos/tests/cjdns.nix
@@ -54,7 +54,7 @@ import ./make-test.nix ({ pkgs, ...} : {
           services.cjdns =
             { UDPInterface =
                 { bind = "0.0.0.0:1024";
-                  connectTo."192.168.0.1:1024}" =
+                  connectTo."192.168.0.1:1024" =
                     { password = carolPassword;
                       publicKey = carolPubKey;
                     };
diff --git a/nixos/tests/dnscrypt-proxy.nix b/nixos/tests/dnscrypt-proxy.nix
index b686e9582a7d..26409949ec62 100644
--- a/nixos/tests/dnscrypt-proxy.nix
+++ b/nixos/tests/dnscrypt-proxy.nix
@@ -22,8 +22,6 @@ import ./make-test.nix ({ pkgs, ... }: {
   };
 
   testScript = ''
-    $client->start;
-    $client->waitForUnit("sockets.target");
     $client->waitForUnit("dnsmasq");
 
     # The daemon is socket activated; sending a single ping should activate it.
diff --git a/nixos/tests/hibernate.nix b/nixos/tests/hibernate.nix
index 787929f8904d..7616a75b0214 100644
--- a/nixos/tests/hibernate.nix
+++ b/nixos/tests/hibernate.nix
@@ -13,7 +13,7 @@ import ./make-test.nix (pkgs: {
 
       networking.firewall.allowedTCPPorts = [ 4444 ];
 
-      systemd.services.listener.serviceConfig.ExecStart = "${pkgs.netcat}/bin/nc -l -p 4444";
+      systemd.services.listener.serviceConfig.ExecStart = "${pkgs.netcat}/bin/nc -l 4444";
     };
 
     probe = { config, lib, pkgs, ...}: {
@@ -36,7 +36,7 @@ import ./make-test.nix (pkgs: {
       $machine->waitForShutdown;
       $machine->start;
       $probe->waitForUnit("network.target");
-      $probe->waitUntilSucceeds("echo test | nc -c machine 4444");
+      $probe->waitUntilSucceeds("echo test | nc machine 4444");
     '';
 
 })
diff --git a/nixos/tests/leaps.nix b/nixos/tests/leaps.nix
new file mode 100644
index 000000000000..3c390e1a1691
--- /dev/null
+++ b/nixos/tests/leaps.nix
@@ -0,0 +1,29 @@
+import ./make-test.nix ({ pkgs,  ... }:
+
+{
+  name = "leaps";
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ qknight ];
+  };
+
+  nodes =
+    { 
+      client = { };
+
+      server =
+        { services.leaps = {
+            enable = true;
+            port = 6666;
+            path = "/leaps/";
+          };
+          networking.firewall.enable = false;
+        };
+    };
+
+  testScript =
+    ''
+      startAll;
+      $server->waitForOpenPort(6666);
+      $client->succeed("curl http://server:6666/leaps/ | grep -i 'leaps'"); 
+    '';
+})
diff --git a/nixos/tests/mpich.nix b/nixos/tests/mpich.nix
deleted file mode 100644
index a28e41deb31e..000000000000
--- a/nixos/tests/mpich.nix
+++ /dev/null
@@ -1,41 +0,0 @@
-# Simple example to showcase distributed tests using NixOS VMs.
-
-import ./make-test.nix ({ pkgs, ...} : {
-  name = "mpich";
-  meta = with pkgs.stdenv.lib.maintainers; {
-    maintainers = [ eelco chaoflow ];
-  };
-
-  nodes = {
-    master =
-      { config, pkgs, ... }: {
-        environment.systemPackages = [ gcc mpich2 ];
-        #boot.kernelPackages = pkgs.kernelPackages_2_6_29;
-      };
-
-    slave =
-      { config, pkgs, ... }: {
-        environment.systemPackages = [ gcc mpich2 ];
-      };
-  };
-
-  # Start master/slave MPI daemons and compile/run a program that uses both
-  # nodes.
-  testScript =
-    ''
-       startAll;
-
-       $master->succeed("echo 'MPD_SECRETWORD=secret' > /etc/mpd.conf");
-       $master->succeed("chmod 600 /etc/mpd.conf");
-       $master->succeed("mpd --daemon --ifhn=master --listenport=4444");
-
-       $slave->succeed("echo 'MPD_SECRETWORD=secret' > /etc/mpd.conf");
-       $slave->succeed("chmod 600 /etc/mpd.conf");
-       $slave->succeed("mpd --daemon --host=master --port=4444");
-
-       $master->succeed("mpicc -o example -Wall ${./mpich-example.c}");
-       $slave->succeed("mpicc -o example -Wall ${./mpich-example.c}");
-
-       $master->succeed("mpiexec -n 2 ./example >&2");
-    '';
-})
diff --git a/nixos/tests/test-config-examples.sh b/nixos/tests/test-config-examples.sh
deleted file mode 100755
index 1ba2f841c41d..000000000000
--- a/nixos/tests/test-config-examples.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/sh
-
-# This script try to evaluate all configurations which are stored in
-# doc/config-examples.  This script is useful to ensure that examples are
-# working with the current system.
-
-pwd=$(pwd)
-set -xe
-for i in ../doc/config-examples/*.nix; do
-  NIXOS_CONFIG="$pwd/$i" nix-instantiate \
-      --eval-only --xml --strict > /dev/null 2>&1 \
-      ../default.nix -A system
-done
-set +xe
diff --git a/nixos/tests/virtualbox.nix b/nixos/tests/virtualbox.nix
index 02a8fc680280..376c4f21dc04 100644
--- a/nixos/tests/virtualbox.nix
+++ b/nixos/tests/virtualbox.nix
@@ -299,9 +299,9 @@ let
       -pf /run/dhclient.pid \
       -v eth0 eth1
 
-    otherIP="$(${pkgs.netcat}/bin/netcat -clp 1234 || :)"
+    otherIP="$(${pkgs.netcat}/bin/nc -l 1234 || :)"
     ${pkgs.iputils}/bin/ping -I eth1 -c1 "$otherIP"
-    echo "$otherIP reachable" | ${pkgs.netcat}/bin/netcat -clp 5678 || :
+    echo "$otherIP reachable" | ${pkgs.netcat}/bin/nc -l 5678 || :
   '';
 
   sysdDetectVirt = pkgs: ''
@@ -461,11 +461,11 @@ in mapAttrs mkVBoxTest {
     my $test1IP = waitForIP_test1 1;
     my $test2IP = waitForIP_test2 1;
 
-    $machine->succeed("echo '$test2IP' | netcat -c '$test1IP' 1234");
-    $machine->succeed("echo '$test1IP' | netcat -c '$test2IP' 1234");
+    $machine->succeed("echo '$test2IP' | nc '$test1IP' 1234");
+    $machine->succeed("echo '$test1IP' | nc '$test2IP' 1234");
 
-    $machine->waitUntilSucceeds("netcat -c '$test1IP' 5678 >&2");
-    $machine->waitUntilSucceeds("netcat -c '$test2IP' 5678 >&2");
+    $machine->waitUntilSucceeds("nc '$test1IP' 5678 >&2");
+    $machine->waitUntilSucceeds("nc '$test2IP' 5678 >&2");
 
     shutdownVM_test1;
     shutdownVM_test2;