about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorTuomas Tynkkynen <tuomas@tuxera.com>2016-05-03 23:12:48 +0300
committerTuomas Tynkkynen <tuomas@tuxera.com>2016-05-03 23:12:48 +0300
commitaadaa913792b0fdeb68b02425e4f03d2f8286a1f (patch)
treeea582b078a00e6ba27e2c887a9df5a792c37fb0e /nixos
parent2362891dc815160e343e52458f25db22508ac487 (diff)
parente7d3166656af0d98da9f59c78e2213cec842d743 (diff)
downloadnixlib-aadaa913792b0fdeb68b02425e4f03d2f8286a1f.tar
nixlib-aadaa913792b0fdeb68b02425e4f03d2f8286a1f.tar.gz
nixlib-aadaa913792b0fdeb68b02425e4f03d2f8286a1f.tar.bz2
nixlib-aadaa913792b0fdeb68b02425e4f03d2f8286a1f.tar.lz
nixlib-aadaa913792b0fdeb68b02425e4f03d2f8286a1f.tar.xz
nixlib-aadaa913792b0fdeb68b02425e4f03d2f8286a1f.tar.zst
nixlib-aadaa913792b0fdeb68b02425e4f03d2f8286a1f.zip
Merge remote-tracking branch 'upstream/master' into staging
Conflicts:
	pkgs/applications/networking/browsers/vivaldi/default.nix
	pkgs/misc/emulators/wine/base.nix
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/configuration/config-file.xml10
-rw-r--r--nixos/doc/manual/default.nix75
-rw-r--r--nixos/doc/manual/installation/installing-pxe.xml48
-rw-r--r--nixos/doc/manual/installation/installing.xml1
-rw-r--r--nixos/doc/manual/release-notes/release-notes.xml1
-rw-r--r--nixos/doc/manual/release-notes/rl-1609.xml48
-rw-r--r--nixos/modules/installer/netboot/netboot-base.nix20
-rw-r--r--nixos/modules/installer/netboot/netboot-minimal.nix10
-rw-r--r--nixos/modules/installer/netboot/netboot.nix91
-rw-r--r--nixos/modules/misc/ids.nix1
-rw-r--r--nixos/modules/module-list.nix1
-rw-r--r--nixos/modules/security/grsecurity.nix3
-rw-r--r--nixos/modules/services/hardware/sane_extra_backends/brscan4.nix116
-rw-r--r--nixos/modules/services/hardware/sane_extra_backends/brscan4_etc_files.nix71
-rw-r--r--nixos/modules/services/logging/graylog.nix161
-rw-r--r--nixos/modules/services/mail/rmilter.nix67
-rw-r--r--nixos/modules/services/mail/rspamd.nix59
-rw-r--r--nixos/modules/services/misc/taskserver/default.nix4
-rw-r--r--nixos/modules/services/networking/copy-com.nix54
-rw-r--r--nixos/modules/services/search/elasticsearch.nix1
-rw-r--r--nixos/modules/services/security/fail2ban.nix28
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome3.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/xfce.nix5
-rw-r--r--nixos/modules/services/x11/display-managers/default.nix8
-rw-r--r--nixos/modules/services/x11/xserver.nix9
-rw-r--r--nixos/modules/virtualisation/ec2-amis.nix72
-rw-r--r--nixos/release.nix13
-rw-r--r--nixos/tests/boot.nix43
28 files changed, 878 insertions, 144 deletions
diff --git a/nixos/doc/manual/configuration/config-file.xml b/nixos/doc/manual/configuration/config-file.xml
index 9b240979273d..3d1cdaf4c4ab 100644
--- a/nixos/doc/manual/configuration/config-file.xml
+++ b/nixos/doc/manual/configuration/config-file.xml
@@ -106,11 +106,15 @@ networking.extraHosts =
   '';
 </programlisting>
 
-      The main difference is that preceding whitespace is
-      automatically stripped from each line, and that characters like
+      The main difference is that it strips from each line
+      a number of spaces equal to the minimal indentation of
+      the string as a whole (disregarding the indentation of
+      empty lines), and that characters like
       <literal>"</literal> and <literal>\</literal> are not special
       (making it more convenient for including things like shell
-      code).</para>
+      code).
+      See more info about this in the Nix manual <link
+      xlink:href="https://nixos.org/nix/manual/#ssec-values">here</link>.</para>
     </listitem>
   </varlistentry>
 
diff --git a/nixos/doc/manual/default.nix b/nixos/doc/manual/default.nix
index 86a39322ba51..50b1bb9c7354 100644
--- a/nixos/doc/manual/default.nix
+++ b/nixos/doc/manual/default.nix
@@ -74,6 +74,63 @@ let
       </toc>
     '';
 
+  manualXsltprocOptions = toString [
+    "--param section.autolabel 1"
+    "--param section.label.includes.component.label 1"
+    "--stringparam html.stylesheet style.css"
+    "--param xref.with.number.and.title 1"
+    "--param toc.section.depth 3"
+    "--stringparam admon.style ''"
+    "--stringparam callout.graphics.extension .gif"
+    "--stringparam current.docid manual"
+    "--param chunk.section.depth 0"
+    "--param chunk.first.sections 1"
+    "--param use.id.as.filename 1"
+    "--stringparam generate.toc 'book toc appendix toc'"
+    "--stringparam chunk.toc ${toc}"
+  ];
+
+  olinkDB = stdenv.mkDerivation {
+    name = "manual-olinkdb";
+
+    inherit sources;
+
+    buildInputs = [ libxml2 libxslt ];
+
+    buildCommand = ''
+      ${copySources}
+
+      xsltproc \
+        ${manualXsltprocOptions} \
+        --stringparam collect.xref.targets only \
+        --stringparam targets.filename "$out/manual.db" \
+        --nonet --xinclude \
+        ${docbook5_xsl}/xml/xsl/docbook/xhtml/chunktoc.xsl \
+        ./manual.xml
+
+      # Check the validity of the man pages sources.
+      xmllint --noout --nonet --xinclude --noxincludenode \
+        --relaxng ${docbook5}/xml/rng/docbook/docbook.rng \
+        ./man-pages.xml
+
+      cat > "$out/olinkdb.xml" <<EOF
+      <?xml version="1.0" encoding="utf-8"?>
+      <!DOCTYPE targetset SYSTEM
+        "file://${docbook5_xsl}/xml/xsl/docbook/common/targetdatabase.dtd" [
+        <!ENTITY manualtargets SYSTEM "file://$out/manual.db">
+      ]>
+      <targetset>
+        <targetsetinfo>
+            Allows for cross-referencing olinks between the manpages
+            and the HTML/PDF manuals.
+        </targetsetinfo>
+
+        <document targetdoc="manual">&manualtargets;</document>
+      </targetset>
+      EOF
+    '';
+  };
+
 in rec {
 
   # The NixOS options in JSON format.
@@ -116,18 +173,8 @@ in rec {
       dst=$out/share/doc/nixos
       mkdir -p $dst
       xsltproc \
-        --param section.autolabel 1 \
-        --param section.label.includes.component.label 1 \
-        --stringparam html.stylesheet style.css \
-        --param xref.with.number.and.title 1 \
-        --param toc.section.depth 3 \
-        --stringparam admon.style "" \
-        --stringparam callout.graphics.extension .gif \
-        --param chunk.section.depth 0 \
-        --param chunk.first.sections 1 \
-        --param use.id.as.filename 1 \
-        --stringparam generate.toc "book toc appendix toc" \
-        --stringparam chunk.toc ${toc} \
+        ${manualXsltprocOptions} \
+        --stringparam target.database.document "${olinkDB}/olinkdb.xml" \
         --nonet --xinclude --output $dst/ \
         ${docbook5_xsl}/xml/xsl/docbook/xhtml/chunktoc.xsl ./manual.xml
 
@@ -159,6 +206,7 @@ in rec {
       dst=$out/share/doc/nixos
       mkdir -p $dst
       xmllint --xinclude manual.xml | dblatex -o $dst/manual.pdf - \
+        -P target.database.document="${olinkDB}/olinkdb.xml" \
         -P doc.collab.show=0 \
         -P latex.output.revhistory=0
 
@@ -178,7 +226,7 @@ in rec {
     buildCommand = ''
       ${copySources}
 
-      # Check the validity of the manual sources.
+      # Check the validity of the man pages sources.
       xmllint --noout --nonet --xinclude --noxincludenode \
         --relaxng ${docbook5}/xml/rng/docbook/docbook.rng \
         ./man-pages.xml
@@ -190,6 +238,7 @@ in rec {
         --param man.output.base.dir "'$out/share/man/'" \
         --param man.endnotes.are.numbered 0 \
         --param man.break.after.slash 1 \
+        --stringparam target.database.document "${olinkDB}/olinkdb.xml" \
         ${docbook5_xsl}/xml/xsl/docbook/manpages/docbook.xsl \
         ./man-pages.xml
     '';
diff --git a/nixos/doc/manual/installation/installing-pxe.xml b/nixos/doc/manual/installation/installing-pxe.xml
new file mode 100644
index 000000000000..7b7597c91626
--- /dev/null
+++ b/nixos/doc/manual/installation/installing-pxe.xml
@@ -0,0 +1,48 @@
+<section xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="sec-booting-from-pxe">
+
+<title>Booting from the <quote>netboot</quote> media (PXE)</title>
+<para>
+  Advanced users may wish to install NixOS using an existing PXE or
+  iPXE setup.
+</para>
+<para>
+  These instructions assume that you have an existing PXE or iPXE
+  infrastructure and simply want to add the NixOS installer as another
+  option. To build the necessary files from a recent version of
+  nixpkgs, you can run:
+</para>
+<programlisting>
+nix-build -A netboot nixos/release.nix
+</programlisting>
+<para>
+  This will create a <literal>result</literal> directory containing: *
+  <literal>bzImage</literal> – the Linux kernel *
+  <literal>initrd</literal> – the initrd file *
+  <literal>netboot.ipxe</literal> – an example ipxe script
+  demonstrating the appropriate kernel command line arguments for this
+  image
+</para>
+<para>
+  If you’re using plain PXE, configure your boot loader to use the
+  <literal>bzImage</literal> and <literal>initrd</literal> files and
+  have it provide the same kernel command line arguments found in
+  <literal>netboot.ipxe</literal>.
+</para>
+<para>
+  If you’re using iPXE, depending on how your HTTP/FTP/etc. server is
+  configured you may be able to use <literal>netboot.ipxe</literal>
+  unmodified, or you may need to update the paths to the files to
+  match your server’s directory layout
+</para>
+<para>
+  In the future we may begin making these files available as build
+  products from hydra at which point we will update this documentation
+  with instructions on how to obtain them either for placing on a
+  dedicated TFTP server or to boot them directly over the internet.
+</para>
+
+</section>
diff --git a/nixos/doc/manual/installation/installing.xml b/nixos/doc/manual/installation/installing.xml
index 4a0b3fee7c18..3e53062c3e84 100644
--- a/nixos/doc/manual/installation/installing.xml
+++ b/nixos/doc/manual/installation/installing.xml
@@ -270,5 +270,6 @@ $ reboot</screen>
 
 <xi:include href="installing-uefi.xml" />
 <xi:include href="installing-usb.xml" />
+<xi:include href="installing-pxe.xml" />
 
 </chapter>
diff --git a/nixos/doc/manual/release-notes/release-notes.xml b/nixos/doc/manual/release-notes/release-notes.xml
index 2beaab00800d..31a7ae04a4f5 100644
--- a/nixos/doc/manual/release-notes/release-notes.xml
+++ b/nixos/doc/manual/release-notes/release-notes.xml
@@ -9,6 +9,7 @@
 <para>This section lists the release notes for each stable version of NixOS
 and current unstable revision.</para>
 
+<xi:include href="rl-1609.xml" />
 <xi:include href="rl-1603.xml" />
 <xi:include href="rl-1509.xml" />
 <xi:include href="rl-1412.xml" />
diff --git a/nixos/doc/manual/release-notes/rl-1609.xml b/nixos/doc/manual/release-notes/rl-1609.xml
new file mode 100644
index 000000000000..22dea8029242
--- /dev/null
+++ b/nixos/doc/manual/release-notes/rl-1609.xml
@@ -0,0 +1,48 @@
+<section xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="sec-release-16.09">
+
+<title>Release 16.09 (“Flounder”, 2016/09/??)</title>
+
+<para>In addition to numerous new and upgraded packages, this release
+has the following highlights: </para>
+
+<itemizedlist>
+
+  <listitem>
+    <para>PXE "netboot" media has landed in <link xlink:href="https://github.com/NixOS/nixpkgs/pull/14740" />.
+    See <xref linkend="sec-booting-from-pxe" /> for documentation.</para>
+  </listitem>
+
+</itemizedlist>
+
+<para>The following new services were added since the last release:</para>
+
+  <itemizedlist>
+    <listitem><para><literal>(this will get automatically generated at release time)</literal></para></listitem>
+  </itemizedlist>
+
+
+<para>When upgrading from a previous release, please be aware of the
+following incompatible changes:</para>
+
+<itemizedlist>
+  <listitem>
+    <para>todo</para>
+  </listitem>
+</itemizedlist>
+
+
+<para>Other notable improvements:</para>
+
+<itemizedlist>
+  <listitem>
+    <para>todo</para>
+  </listitem>
+
+</itemizedlist>
+
+
+</section>
diff --git a/nixos/modules/installer/netboot/netboot-base.nix b/nixos/modules/installer/netboot/netboot-base.nix
new file mode 100644
index 000000000000..b12eaccf8707
--- /dev/null
+++ b/nixos/modules/installer/netboot/netboot-base.nix
@@ -0,0 +1,20 @@
+# This module contains the basic configuration for building netboot
+# images
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+  imports =
+    [ ./netboot.nix
+
+      # Profiles of this basic netboot media
+      ../../profiles/all-hardware.nix
+      ../../profiles/base.nix
+      ../../profiles/installation-device.nix
+    ];
+
+  # Allow the user to log in as root without a password.
+  users.extraUsers.root.initialHashedPassword = "";
+}
diff --git a/nixos/modules/installer/netboot/netboot-minimal.nix b/nixos/modules/installer/netboot/netboot-minimal.nix
new file mode 100644
index 000000000000..8ad6234edc77
--- /dev/null
+++ b/nixos/modules/installer/netboot/netboot-minimal.nix
@@ -0,0 +1,10 @@
+# This module defines a small netboot environment.
+
+{ config, lib, ... }:
+
+{
+  imports =
+    [ ./netboot-base.nix
+      ../../profiles/minimal.nix
+    ];
+}
diff --git a/nixos/modules/installer/netboot/netboot.nix b/nixos/modules/installer/netboot/netboot.nix
new file mode 100644
index 000000000000..366591a81148
--- /dev/null
+++ b/nixos/modules/installer/netboot/netboot.nix
@@ -0,0 +1,91 @@
+# This module creates netboot media containing the given NixOS
+# configuration.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+  options = {
+
+    netboot.storeContents = mkOption {
+      example = literalExample "[ pkgs.stdenv ]";
+      description = ''
+        This option lists additional derivations to be included in the
+        Nix store in the generated netboot image.
+      '';
+    };
+
+  };
+
+  config = {
+
+    boot.loader.grub.version = 2;
+
+    # Don't build the GRUB menu builder script, since we don't need it
+    # here and it causes a cyclic dependency.
+    boot.loader.grub.enable = false;
+
+    boot.initrd.postMountCommands = ''
+      mkdir -p /mnt-root/nix/store
+      mount -t squashfs /nix-store.squashfs /mnt-root/nix/store
+    '';
+
+    # !!! Hack - attributes expected by other modules.
+    system.boot.loader.kernelFile = "bzImage";
+    environment.systemPackages = [ pkgs.grub2 pkgs.grub2_efi pkgs.syslinux ];
+
+    boot.consoleLogLevel = mkDefault 7;
+
+    fileSystems."/" =
+      { fsType = "tmpfs";
+        options = [ "mode=0755" ];
+      };
+
+    boot.initrd.availableKernelModules = [ "squashfs" ];
+
+    boot.initrd.kernelModules = [ "loop" ];
+
+    # Closures to be copied to the Nix store, namely the init
+    # script and the top-level system configuration directory.
+   netboot.storeContents =
+      [ config.system.build.toplevel ];
+
+    # Create the squashfs image that contains the Nix store.
+    system.build.squashfsStore = import ../../../lib/make-squashfs.nix {
+      inherit (pkgs) stdenv squashfsTools perl pathsFromGraph;
+      storeContents = config.netboot.storeContents;
+    };
+
+
+    # Create the initrd
+    system.build.netbootRamdisk = pkgs.makeInitrd {
+      inherit (config.boot.initrd) compressor;
+      prepend = [ "${config.system.build.initialRamdisk}/initrd" ];
+
+      contents =
+        [ { object = config.system.build.squashfsStore;
+            symlink = "/nix-store.squashfs";
+          }
+        ];
+    };
+
+    system.build.netbootIpxeScript = pkgs.writeTextDir "netboot.ipxe" "#!ipxe\nkernel bzImage init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}\ninitrd initrd\nboot";
+
+    boot.loader.timeout = 10;
+
+    boot.postBootCommands =
+      ''
+        # After booting, register the contents of the Nix store
+        # in the Nix database in the tmpfs.
+        ${config.nix.package}/bin/nix-store --load-db < /nix/store/nix-path-registration
+
+        # nixos-rebuild also requires a "system" profile and an
+        # /etc/NIXOS tag.
+        touch /etc/NIXOS
+        ${config.nix.package}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
+      '';
+
+  };
+
+}
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index 684ca132bc74..7e40c1366677 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -264,6 +264,7 @@
       taskd = 240;
       factorio = 241;
       emby = 242;
+      graylog = 243;
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index ec14fd2e3631..b92361f628be 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -183,6 +183,7 @@
   ./services/hardware/thermald.nix
   ./services/logging/awstats.nix
   ./services/logging/fluentd.nix
+  ./services/logging/graylog.nix
   ./services/logging/klogd.nix
   ./services/logging/logcheck.nix
   ./services/logging/logrotate.nix
diff --git a/nixos/modules/security/grsecurity.nix b/nixos/modules/security/grsecurity.nix
index 236206026c3f..11668162808f 100644
--- a/nixos/modules/security/grsecurity.nix
+++ b/nixos/modules/security/grsecurity.nix
@@ -234,7 +234,8 @@ in
 
     systemd.services.grsec-lock = mkIf cfg.config.sysctl {
       description     = "grsecurity sysctl-lock Service";
-      requires        = [ "systemd-sysctl.service" ];
+      wants           = [ "systemd-sysctl.service" ];
+      after           = [ "systemd-sysctl.service" ];
       wantedBy        = [ "multi-user.target" ];
       serviceConfig.Type = "oneshot";
       serviceConfig.RemainAfterExit = "yes";
diff --git a/nixos/modules/services/hardware/sane_extra_backends/brscan4.nix b/nixos/modules/services/hardware/sane_extra_backends/brscan4.nix
new file mode 100644
index 000000000000..3ec74458cd29
--- /dev/null
+++ b/nixos/modules/services/hardware/sane_extra_backends/brscan4.nix
@@ -0,0 +1,116 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.hardware.sane.brscan4;
+
+  netDeviceList = attrValues cfg.netDevices;
+
+  etcFiles = pkgs.callPackage ./brscan4_etc_files.nix { netDevices = netDeviceList; };
+
+  netDeviceOpts = { name, config, ... }: {
+
+    options = {
+
+      name = mkOption {
+        type = types.str;
+        description = ''
+          The friendly name you give to the network device. If undefined,
+          the name of attribute will be used.
+        '';
+
+        example = literalExample "office1";
+      };
+
+      model = mkOption {
+        type = types.str;
+        description = ''
+          The model of the network device.
+        '';
+
+        example = literalExample "MFC-7860DW";
+      };
+
+      ip = mkOption {
+        type = with types; nullOr str;
+        default = null;
+        description = ''
+          The ip address of the device. If undefined, you will have to
+          provide a nodename.
+        '';
+
+        example = literalExample "192.168.1.2";
+      };
+
+      nodename = mkOption {
+        type = with types; nullOr str;
+        default = null;
+        description = ''
+          The node name of the device. If undefined, you will have to
+          provide an ip.
+        '';
+
+        example = literalExample "BRW0080927AFBCE";
+      };
+
+    };
+
+
+    config =
+      { name = mkDefault name;
+      };
+  };
+
+in
+
+{
+  options = {
+
+    hardware.sane.brscan4.enable = 
+      mkEnableOption "Brother's brscan4 scan backend" // {
+      description = ''
+        When enabled, will automatically register the "brscan4" sane
+        backend and bring configuration files to their expected location. 
+      '';
+    };
+
+    hardware.sane.brscan4.netDevices = mkOption {
+      default = {};
+      example =
+        { office1 = { model = "MFC-7860DW"; ip = "192.168.1.2"; };
+          office2 = { model = "MFC-7860DW"; nodename = "BRW0080927AFBCE"; };
+        };
+      type = types.loaOf types.optionSet;
+      description = ''
+        The list of network devices that will be registered against the brscan4
+        sane backend.
+      '';
+      options = [ netDeviceOpts ];
+    };
+  };
+
+  config = mkIf (config.hardware.sane.enable && cfg.enable) {
+
+    hardware.sane.extraBackends = [
+      pkgs.brscan4
+    ];
+
+    environment.etc = singleton {
+      target = "opt/brother/scanner/brscan4";
+      source = "${etcFiles}/etc/opt/brother/scanner/brscan4";
+    };
+
+    assertions = [
+      { assertion = all (x: !(null != x.ip && null != x.nodename)) netDeviceList;
+          
+        message = ''
+          When describing a network device as part of the attribute list
+          `hardware.sane.brscan4.netDevices`, only one of its `ip` or `nodename`
+          attribute should be specified, not both!
+        '';
+      }
+    ];
+
+  };
+}
\ No newline at end of file
diff --git a/nixos/modules/services/hardware/sane_extra_backends/brscan4_etc_files.nix b/nixos/modules/services/hardware/sane_extra_backends/brscan4_etc_files.nix
new file mode 100644
index 000000000000..bd114f0d2cca
--- /dev/null
+++ b/nixos/modules/services/hardware/sane_extra_backends/brscan4_etc_files.nix
@@ -0,0 +1,71 @@
+{ stdenv, lib, brscan4, netDevices ? [] }:
+
+/*
+
+Testing
+-------
+
+No net devices:
+
+~~~
+nix-shell -E 'with import <nixpkgs> { }; brscan4-etc-files'
+~~~
+
+Two net devices:
+
+~~~
+nix-shell -E 'with import <nixpkgs> { }; brscan4-etc-files.override{netDevices=[{name="a"; model="MFC-7860DW"; nodename="BRW0080927AFBCE";} {name="b"; model="MFC-7860DW"; ip="192.168.1.2";}];}'
+~~~
+
+*/
+
+with lib; 
+
+let
+
+  addNetDev = nd: ''
+    brsaneconfig4 -a \
+    name="${nd.name}" \
+    model="${nd.model}" \
+    ${if (hasAttr "nodename" nd && nd.nodename != null) then
+      ''nodename="${nd.nodename}"'' else
+      ''ip="${nd.ip}"''}'';
+  addAllNetDev = xs: concatStringsSep "\n" (map addNetDev xs);
+in
+
+stdenv.mkDerivation rec {
+
+  name = "brscan4-etc-files-0.4.3-3";
+  src = "${brscan4}/opt/brother/scanner/brscan4";
+
+  nativeBuildInputs = [ brscan4 ];
+
+  configurePhase = ":";
+
+  buildPhase = ''
+    TARGET_DIR="$out/etc/opt/brother/scanner/brscan4"
+    mkdir -p "$TARGET_DIR"
+    cp -rp "./models4" "$TARGET_DIR"
+    cp -rp "./Brsane4.ini" "$TARGET_DIR"
+    cp -rp "./brsanenetdevice4.cfg" "$TARGET_DIR"
+
+    export BRSANENETDEVICE4_CFG_FILENAME="$TARGET_DIR/brsanenetdevice4.cfg"
+
+    printf '${addAllNetDev netDevices}\n'
+
+    ${addAllNetDev netDevices}
+  '';
+
+  installPhase = ":";
+
+  dontStrip = true;
+  dontPatchELF = true;
+
+  meta = {
+    description = "Brother brscan4 sane backend driver etc files";
+    homepage = http://www.brother.com;
+    platforms = stdenv.lib.platforms.linux;
+    license = stdenv.lib.licenses.unfree;
+    maintainers = with stdenv.lib.maintainers; [ jraygauthier ];
+  };
+}
diff --git a/nixos/modules/services/logging/graylog.nix b/nixos/modules/services/logging/graylog.nix
new file mode 100644
index 000000000000..a7785decd19a
--- /dev/null
+++ b/nixos/modules/services/logging/graylog.nix
@@ -0,0 +1,161 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.graylog;
+  configBool = b: if b then "true" else "false";
+
+  confFile = pkgs.writeText "graylog.conf" ''
+    is_master = ${configBool cfg.isMaster}
+    node_id_file = ${cfg.nodeIdFile}
+    password_secret = ${cfg.passwordSecret}
+    root_username = ${cfg.rootUsername}
+    root_password_sha2 = ${cfg.rootPasswordSha2}
+    elasticsearch_cluster_name = ${cfg.elasticsearchClusterName}
+    elasticsearch_discovery_zen_ping_multicast_enabled = ${configBool cfg.elasticsearchDiscoveryZenPingMulticastEnabled}
+    elasticsearch_discovery_zen_ping_unicast_hosts = ${cfg.elasticsearchDiscoveryZenPingUnicastHosts}
+    message_journal_dir = ${cfg.messageJournalDir}
+    mongodb_uri = ${cfg.mongodbUri}
+
+    ${cfg.extraConfig}
+  '';
+in
+
+{
+  ###### interface
+
+  options = {
+
+    services.graylog = {
+
+      enable = mkEnableOption "Graylog";
+
+      package = mkOption {
+        type = types.package;
+        default = pkgs.graylog;
+        defaultText = "pkgs.graylog";
+        example = literalExample "pkgs.graylog";
+        description = "Graylog package to use.";
+      };
+
+      user = mkOption {
+        type = types.str;
+        default = "graylog";
+        example = literalExample "graylog";
+        description = "User account under which graylog runs";
+      };
+
+      isMaster = mkOption {
+        type = types.bool;
+        default = true;
+        description = "Whether this is the master instance of your Graylog cluster";
+      };
+
+      nodeIdFile = mkOption {
+        type = types.str;
+        default = "/var/lib/graylog/server/node-id";
+        description = "Path of the file containing the graylog node-id";
+      };
+
+      passwordSecret = mkOption {
+        type = types.str;
+        description = ''
+          You MUST set a secret to secure/pepper the stored user passwords here. Use at least 64 characters.
+          Generate one by using for example: pwgen -N 1 -s 96
+        '';
+      };
+
+      rootUsername = mkOption {
+        type = types.str;
+        default = "admin";
+        description = "Name of the default administrator user";
+      };
+
+      rootPasswordSha2 = mkOption {
+        type = types.str;
+        example = "e3c652f0ba0b4801205814f8b6bc49672c4c74e25b497770bb89b22cdeb4e952";
+        description = ''
+          You MUST specify a hash password for the root user (which you only need to initially set up the
+          system and in case you lose connectivity to your authentication backend)
+          This password cannot be changed using the API or via the web interface. If you need to change it,
+          modify it here.
+          Create one by using for example: echo -n yourpassword | shasum -a 256
+          and use the resulting hash value as string for the option
+        '';
+      };
+
+      elasticsearchClusterName = mkOption {
+        type = types.str;
+        example = "graylog";
+        description = "This must be the same as for your Elasticsearch cluster";
+      };
+
+      elasticsearchDiscoveryZenPingMulticastEnabled = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to use elasticsearch multicast discovery";
+      };
+
+      elasticsearchDiscoveryZenPingUnicastHosts = mkOption {
+        type = types.str;
+        default = "127.0.0.1:9300";
+        description = "Tells Graylogs Elasticsearch client how to find other cluster members. See Elasticsearch documentation for details";
+      };
+
+      messageJournalDir = mkOption {
+        type = types.str;
+        default = "/var/lib/graylog/data/journal";
+        description = "The directory which will be used to store the message journal. The directory must be exclusively used by Graylog and must not contain any other files than the ones created by Graylog itself";
+      };
+
+      mongodbUri = mkOption {
+        type = types.str;
+        default = "mongodb://localhost/graylog";
+        description = "MongoDB connection string. See http://docs.mongodb.org/manual/reference/connection-string/ for details";
+      };
+
+      extraConfig = mkOption {
+        type = types.str;
+        default = "";
+        description = "Any other configuration options you might want to add";
+      };
+
+    };
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    users.extraUsers = mkIf (cfg.user == "graylog") {
+      graylog = {
+        uid = config.ids.uids.graylog;
+        description = "Graylog server daemon user";
+      };
+    };
+
+    systemd.services.graylog = with pkgs; {
+      description = "Graylog Server";
+      wantedBy = [ "multi-user.target" ];
+      environment = {
+        JAVA_HOME = jre;
+        GRAYLOG_CONF = "${confFile}";
+      };
+      path = [ pkgs.openjdk8 pkgs.which pkgs.procps ];
+      preStart = ''
+        mkdir -p /var/lib/graylog -m 755
+        chown -R ${cfg.user} /var/lib/graylog
+
+        mkdir -p ${cfg.messageJournalDir} -m 755
+        chown -R ${cfg.user} ${cfg.messageJournalDir}
+      '';
+      serviceConfig = {
+        User="${cfg.user}";
+        PermissionsStartOnly=true;
+        ExecStart = "${cfg.package}/bin/graylogctl run";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/mail/rmilter.nix b/nixos/modules/services/mail/rmilter.nix
index a6e2a9fc7808..d1f7cd2e173e 100644
--- a/nixos/modules/services/mail/rmilter.nix
+++ b/nixos/modules/services/mail/rmilter.nix
@@ -7,9 +7,14 @@ let
   rspamdCfg = config.services.rspamd;
   cfg = config.services.rmilter;
 
+  inetSockets = map (sock: let s = stringSplit ":" sock; in "inet:${last s}:${head s}") cfg.bindInetSockets;
+  unixSockets = map (sock: "unix:${sock}") cfg.bindUnixSockets;
+
+  allSockets = unixSockets ++ inetSockets;
+
   rmilterConf = ''
 pidfile = /run/rmilter/rmilter.pid;
-bind_socket = ${cfg.bindSocket};
+bind_socket = ${if cfg.socketActivation then "fd:3" else concatStringsSep ", " allSockets};
 tempdir = /tmp;
 
   '' + (with cfg.rspamd; if enable then ''
@@ -68,14 +73,37 @@ in
         '';
        };
 
-      bindSocket =  mkOption {
-        type = types.string;
-        default = "unix:/run/rmilter/rmilter.sock";
-        description = "Socket to listed for MTA requests";
+      bindUnixSockets =  mkOption {
+        type = types.listOf types.str;
+        default = ["/run/rmilter.sock"];
+        description = ''
+          Unix domain sockets to listen for MTA requests.
+        '';
         example = ''
-            "unix:/run/rmilter/rmilter.sock" or
-            "inet:11990@127.0.0.1"
-          '';
+            [ "/run/rmilter.sock"]
+        '';
+      };
+
+      bindInetSockets = mkOption {
+        type = types.listOf types.str;
+        default = [];
+        description = ''
+          Inet addresses to listen (in format accepted by systemd.socket)
+        '';
+        example = ''
+            ["127.0.0.1:11990"]
+        '';
+      };
+
+      socketActivation = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Enable systemd socket activation for rmilter.
+          (disabling socket activation not recommended
+          when unix socket used, and follow to wrong
+          permissions on unix domain socket.)
+        '';
       };
 
       rspamd = {
@@ -86,7 +114,7 @@ in
 
         servers = mkOption {
           type = types.listOf types.str;
-          default = ["r:0.0.0.0:11333"];
+          default = ["r:/run/rspamd.sock"];
           description = ''
             Spamd socket definitions.
             Is server name is prefixed with r: it is rspamd server.
@@ -129,7 +157,7 @@ in
           type = types.str;
           description = "Addon to postfix configuration";
           default = ''
-smtpd_milters = ${cfg.bindSocket}
+smtpd_milters = ${head allSockets}
 # or for TCP socket
 # # smtpd_milters = inet:localhost:9900
 milter_protocol = 6
@@ -169,21 +197,30 @@ milter_default_action = accept
 
       serviceConfig = {
         ExecStart = "${pkgs.rmilter}/bin/rmilter ${optionalString cfg.debug "-d"} -n -c ${rmilterConfigFile}";
+        ExecReload = "/bin/kill -USR1 $MAINPID";
         User = cfg.user;
         Group = cfg.group;
         PermissionsStartOnly = true;
         Restart = "always";
+        RuntimeDirectory = "rmilter";
+        RuntimeDirectoryPermissions="0755";
       };
 
-      preStart = ''
-        ${pkgs.coreutils}/bin/mkdir -p /run/rmilter
-        ${pkgs.coreutils}/bin/chown ${cfg.user}:${cfg.group} /run/rmilter
-      '';
+    };
 
+    systemd.sockets.rmilter = mkIf cfg.socketActivation {
+      description = "Rmilter service socket";
+      wantedBy = [ "sockets.target" ];
+      socketConfig = {
+          ListenStream = cfg.bindUnixSockets ++ cfg.bindInetSockets;
+          SocketUser = cfg.user;
+          SocketGroup = cfg.group;
+          SocketMode = "0660";
+      };
     };
 
     services.postfix.extraConfig = optionalString cfg.postfix.enable cfg.postfix.configFragment;
-
+    users.users.postfix.extraGroups = [ cfg.group ];
   };
 
 }
diff --git a/nixos/modules/services/mail/rspamd.nix b/nixos/modules/services/mail/rspamd.nix
index a083f8293243..412b99ccc570 100644
--- a/nixos/modules/services/mail/rspamd.nix
+++ b/nixos/modules/services/mail/rspamd.nix
@@ -6,6 +6,35 @@ let
 
   cfg = config.services.rspamd;
 
+  mkBindSockets = socks: concatStringsSep "\n" (map (each: "  bind_socket = \"${each}\"") socks);
+
+  rspamdConf =
+    ''
+      .include "$CONFDIR/common.conf"
+
+      options {
+        pidfile = "$RUNDIR/rspamd.pid";
+        .include "$CONFDIR/options.inc"
+      }
+
+      logging {
+        type = "file";
+        filename = "$LOGDIR/rspamd.log";
+        .include "$CONFDIR/logging.inc"
+      }
+
+      worker {
+      ${mkBindSockets cfg.bindSocket}
+        .include "$CONFDIR/worker-normal.inc"
+      }
+
+      worker {
+      ${mkBindSockets cfg.bindUISocket}
+        .include "$CONFDIR/worker-controller.inc"
+      }
+   '';
+   rspamdConfFile = pkgs.writeText "rspamd.conf" rspamdConf;
+
 in
 
 {
@@ -26,6 +55,32 @@ in
         description = "Whether to run the rspamd daemon in debug mode.";
       };
 
+      bindSocket = mkOption {
+        type = types.listOf types.str;
+        default = [
+          "/run/rspamd.sock mode=0666 owner=${cfg.user}"
+        ];
+        description = ''
+          List of sockets to listen, in format acceptable by rspamd
+        '';
+        example = ''
+          bindSocket = [
+            "/run/rspamd.sock mode=0666 owner=rspamd"
+            "*:11333"
+          ];
+        '';
+      };
+
+      bindUISocket = mkOption {
+        type = types.listOf types.str;
+        default = [
+          "localhost:11334"
+        ];
+        description = ''
+          List of sockets for web interface, in format acceptable by rspamd
+        '';
+      };
+
       user = mkOption {
         type = types.string;
         default = "rspamd";
@@ -62,7 +117,7 @@ in
 
     users.extraGroups = singleton {
       name = cfg.group;
-      gid = config.ids.gids.spamd;
+      gid = config.ids.gids.rspamd;
     };
 
     systemd.services.rspamd = {
@@ -72,7 +127,7 @@ in
       after = [ "network.target" ];
 
       serviceConfig = {
-        ExecStart = "${pkgs.rspamd}/bin/rspamd ${optionalString cfg.debug "-d"} --user=${cfg.user} --group=${cfg.group} --pid=/run/rspamd.pid -f";
+        ExecStart = "${pkgs.rspamd}/bin/rspamd ${optionalString cfg.debug "-d"} --user=${cfg.user} --group=${cfg.group} --pid=/run/rspamd.pid -c ${rspamdConfFile} -f";
         RuntimeDirectory = "/var/lib/rspamd";
         PermissionsStartOnly = true;
         Restart = "always";
diff --git a/nixos/modules/services/misc/taskserver/default.nix b/nixos/modules/services/misc/taskserver/default.nix
index 8459aafeee73..b7d14e90a2b7 100644
--- a/nixos/modules/services/misc/taskserver/default.nix
+++ b/nixos/modules/services/misc/taskserver/default.nix
@@ -449,7 +449,7 @@ in {
         };
       };
     })
-    (mkIf needToCreateCA {
+    (mkIf (cfg.enable && needToCreateCA) {
       systemd.services.taskserver-ca = {
         wantedBy = [ "taskserver.service" ];
         after = [ "taskserver-init.service" ];
@@ -533,7 +533,7 @@ in {
         '';
       };
     })
-    (mkIf (cfg.listenHost != "localhost") {
+    (mkIf (cfg.enable && cfg.listenHost != "localhost") {
       networking.firewall.allowedTCPPorts = [ cfg.listenPort ];
     })
     { meta.doc = ./taskserver.xml; }
diff --git a/nixos/modules/services/networking/copy-com.nix b/nixos/modules/services/networking/copy-com.nix
deleted file mode 100644
index ee0d043d471b..000000000000
--- a/nixos/modules/services/networking/copy-com.nix
+++ /dev/null
@@ -1,54 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
-
-  cfg = config.services.copy-com;
-
-in
-
-{
-  options = {
-
-    services.copy-com = {
-
-	  enable = mkOption {
-          default = false;
-          description = "
-            Enable the Copy.com client.
-            NOTE: before enabling the client for the first time, it must be
-            configured by first running CopyConsole (command line) or CopyAgent
-            (graphical) as the appropriate user.
-          ";
-      };
-
-      user = mkOption {
-        description = "The user for which the Copy.com client should be run.";
-      };
-
-      debug = mkOption {
-        default = false;
-        description = "Output more (debugging) messages to the console.";
-      };
-	  };
-  };
-
-  config = mkIf cfg.enable {
-    environment.systemPackages = [ pkgs.postfix ];
-
-    systemd.services."copy-com-${cfg.user}" = {
-      description = "Copy.com client";
-      wants = [ "network-online.target" ];
-      after = [ "network-online.target" "local-fs.target" ];
-      wantedBy = [ "multi-user.target" ];
-      serviceConfig = {
-        ExecStart = "${pkgs.copy-com}/bin/CopyConsole ${if cfg.debug then "-consoleOutput -debugToConsole=dirwatch,path-watch,csm_path,csm -debug -console" else ""}";
-        User = "${cfg.user}";
-      };
-
-    };
-  };
-
-}
-
diff --git a/nixos/modules/services/search/elasticsearch.nix b/nixos/modules/services/search/elasticsearch.nix
index c51a42b8e9c1..17ac8fe7e245 100644
--- a/nixos/modules/services/search/elasticsearch.nix
+++ b/nixos/modules/services/search/elasticsearch.nix
@@ -145,6 +145,7 @@ in {
         # Install plugins
         ln -sfT ${esPlugins}/plugins ${cfg.dataDir}/plugins
         ln -sfT ${cfg.package}/lib ${cfg.dataDir}/lib
+        ln -sfT ${cfg.package}/modules ${cfg.dataDir}/modules
         if [ "$(id -u)" = 0 ]; then chown -R elasticsearch ${cfg.dataDir}; fi
       '';
       postStart = mkBefore ''
diff --git a/nixos/modules/services/security/fail2ban.nix b/nixos/modules/services/security/fail2ban.nix
index afbd81be91f2..33c4910fc0ce 100644
--- a/nixos/modules/services/security/fail2ban.nix
+++ b/nixos/modules/services/security/fail2ban.nix
@@ -99,34 +99,32 @@ in
 
         wantedBy = [ "multi-user.target" ];
         after = [ "network.target" ];
+        partOf = optional config.networking.firewall.enable "firewall.service";
 
         restartTriggers = [ fail2banConf jailConf ];
         path = [ pkgs.fail2ban pkgs.iptables ];
 
         preStart =
           ''
-            mkdir -p /run/fail2ban -m 0755
             mkdir -p /var/lib/fail2ban
           '';
 
+        unitConfig.Documentation = "man:fail2ban(1)";
+
         serviceConfig =
-          { ExecStart = "${pkgs.fail2ban}/bin/fail2ban-server -f";
+          { Type = "forking";
+            ExecStart = "${pkgs.fail2ban}/bin/fail2ban-client -x start";
+            ExecStop = "${pkgs.fail2ban}/bin/fail2ban-client stop";
+            ExecReload = "${pkgs.fail2ban}/bin/fail2ban-client reload";
+            PIDFile = "/run/fail2ban/fail2ban.pid";
+            Restart = "always";
+
             ReadOnlyDirectories = "/";
-            ReadWriteDirectories = "/run /var/tmp /var/lib";
+            ReadWriteDirectories = "/run/fail2ban /var/tmp /var/lib";
+            PrivateTmp = "true";
+            RuntimeDirectory = "fail2ban";
             CapabilityBoundingSet = "CAP_DAC_READ_SEARCH CAP_NET_ADMIN CAP_NET_RAW";
           };
-
-        postStart =
-          ''
-            # Wait for the server to start listening.
-            for ((n = 0; n < 20; n++)); do
-              if fail2ban-client ping; then break; fi
-              sleep 0.5
-            done
-
-            # Reload its configuration.
-            fail2ban-client reload
-          '';
       };
 
     # Add some reasonable default jails.  The special "DEFAULT" jail
diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix
index b112fc2422a7..16996b9f96c1 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -165,6 +165,8 @@ in {
         '';
       };
 
+    services.xserver.updateDbusEnvironment = true;
+
     environment.variables.GIO_EXTRA_MODULES = [ "${gnome3.dconf}/lib/gio/modules"
                                                 "${gnome3.glib_networking.out}/lib/gio/modules"
                                                 "${gnome3.gvfs}/lib/gio/modules" ];
diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix
index 33b6dd32c193..60934ed5f190 100644
--- a/nixos/modules/services/x11/desktop-managers/xfce.nix
+++ b/nixos/modules/services/x11/desktop-managers/xfce.nix
@@ -42,10 +42,13 @@ in
             # Set GTK_DATA_PREFIX so that GTK+ can find the Xfce themes.
             export GTK_DATA_PREFIX=${config.system.path}
 
-            exec ${pkgs.stdenv.shell} ${pkgs.xfce.xinitrc}
+            ${pkgs.stdenv.shell} ${pkgs.xfce.xinitrc} &
+            waitPID=$!
           '';
       };
 
+    services.xserver.updateDbusEnvironment = true;
+
     environment.systemPackages =
       [ pkgs.gtk # To get GTK+'s themes.
         pkgs.hicolor_icon_theme
diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix
index be634fc259a2..376f9f4b46b5 100644
--- a/nixos/modules/services/x11/display-managers/default.nix
+++ b/nixos/modules/services/x11/display-managers/default.nix
@@ -126,6 +126,14 @@ let
         (*) echo "$0: Desktop manager '$desktopManager' not found.";;
       esac
 
+      ${optionalString (cfg.startDbusSession && cfg.updateDbusEnvironment) ''
+        ${pkgs.glib}/bin/gdbus call --session \
+          --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus \
+          --method org.freedesktop.DBus.UpdateActivationEnvironment \
+          "{$(env | ${pkgs.gnused}/bin/sed "s/'/\\\\'/g; s/\([^=]*\)=\(.*\)/'\1':'\2'/" \
+                  | ${pkgs.coreutils}/bin/paste -sd,)}"
+      ''}
+
       test -n "$waitPID" && wait "$waitPID"
       exit 0
     '';
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index dcf9f820f59c..9cb9c8de31d7 100644
--- a/nixos/modules/services/x11/xserver.nix
+++ b/nixos/modules/services/x11/xserver.nix
@@ -233,6 +233,15 @@ in
         '';
       };
 
+      updateDbusEnvironment = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to update the DBus activation environment after launching the
+          desktop manager.
+        '';
+      };
+
       layout = mkOption {
         type = types.str;
         default = "us";
diff --git a/nixos/modules/virtualisation/ec2-amis.nix b/nixos/modules/virtualisation/ec2-amis.nix
index e0aad5e42f20..5257aaf62025 100644
--- a/nixos/modules/virtualisation/ec2-amis.nix
+++ b/nixos/modules/virtualisation/ec2-amis.nix
@@ -90,40 +90,40 @@
   "15.09".us-west-2.pv-ebs = "ami-005fb160";
   "15.09".us-west-2.pv-s3 = "ami-cd55bbad";
 
-  "16.03".ap-northeast-1.hvm-ebs = "ami-885040e6";
-  "16.03".ap-northeast-1.hvm-s3 = "ami-d15a4abf";
-  "16.03".ap-northeast-1.pv-ebs = "ami-7f455511";
-  "16.03".ap-northeast-1.pv-s3 = "ami-6d7d6d03";
-  "16.03".ap-southeast-1.hvm-ebs = "ami-478a5f24";
-  "16.03".ap-southeast-1.hvm-s3 = "ami-b2885dd1";
-  "16.03".ap-southeast-1.pv-ebs = "ami-55b46136";
-  "16.03".ap-southeast-1.pv-s3 = "ami-92b762f1";
-  "16.03".ap-southeast-2.hvm-ebs = "ami-26b09345";
-  "16.03".ap-southeast-2.hvm-s3 = "ami-52ac8f31";
-  "16.03".ap-southeast-2.pv-ebs = "ami-1fb3907c";
-  "16.03".ap-southeast-2.pv-s3 = "ami-49b1922a";
-  "16.03".eu-central-1.hvm-ebs = "ami-2bd63744";
-  "16.03".eu-central-1.hvm-s3 = "ami-82d435ed";
-  "16.03".eu-central-1.pv-ebs = "ami-b729c8d8";
-  "16.03".eu-central-1.pv-s3 = "ami-a12dccce";
-  "16.03".eu-west-1.hvm-ebs = "ami-87c242f4";
-  "16.03".eu-west-1.hvm-s3 = "ami-b6c343c5";
-  "16.03".eu-west-1.pv-ebs = "ami-6bc94918";
-  "16.03".eu-west-1.pv-s3 = "ami-00cb4b73";
-  "16.03".sa-east-1.hvm-ebs = "ami-845cd3e8";
-  "16.03".sa-east-1.hvm-s3 = "ami-8142cded";
-  "16.03".sa-east-1.pv-ebs = "ami-1643cc7a";
-  "16.03".sa-east-1.pv-s3 = "ami-1646c97a";
-  "16.03".us-east-1.hvm-ebs = "ami-2cc4d046";
-  "16.03".us-east-1.hvm-s3 = "ami-9bc9ddf1";
-  "16.03".us-east-1.pv-ebs = "ami-7df4e017";
-  "16.03".us-east-1.pv-s3 = "ami-90f2e6fa";
-  "16.03".us-west-1.hvm-ebs = "ami-d8116db8";
-  "16.03".us-west-1.hvm-s3 = "ami-a7166ac7";
-  "16.03".us-west-1.pv-ebs = "ami-e90c7089";
-  "16.03".us-west-1.pv-s3 = "ami-5b0c703b";
-  "16.03".us-west-2.hvm-ebs = "ami-b339ccd3";
-  "16.03".us-west-2.hvm-s3 = "ami-2c3bce4c";
-  "16.03".us-west-2.pv-ebs = "ami-0625d066";
-  "16.03".us-west-2.pv-s3 = "ami-7414e114";
+  "16.03".ap-northeast-1.hvm-ebs = "ami-b6edf5d8";
+  "16.03".ap-northeast-1.hvm-s3 = "ami-b1e3fbdf";
+  "16.03".ap-northeast-1.pv-ebs = "ami-6190880f";
+  "16.03".ap-northeast-1.pv-s3 = "ami-908d95fe";
+  "16.03".ap-southeast-1.hvm-ebs = "ami-35b16656";
+  "16.03".ap-southeast-1.hvm-s3 = "ami-41be6922";
+  "16.03".ap-southeast-1.pv-ebs = "ami-4cb96e2f";
+  "16.03".ap-southeast-1.pv-s3 = "ami-3bb96e58";
+  "16.03".ap-southeast-2.hvm-ebs = "ami-debc91bd";
+  "16.03".ap-southeast-2.hvm-s3 = "ami-55bc9136";
+  "16.03".ap-southeast-2.pv-ebs = "ami-b38ba6d0";
+  "16.03".ap-southeast-2.pv-s3 = "ami-9e8ba6fd";
+  "16.03".eu-central-1.hvm-ebs = "ami-7c967413";
+  "16.03".eu-central-1.hvm-s3 = "ami-b29072dd";
+  "16.03".eu-central-1.pv-ebs = "ami-7a947615";
+  "16.03".eu-central-1.pv-s3 = "ami-729b791d";
+  "16.03".eu-west-1.hvm-ebs = "ami-ff27a98c";
+  "16.03".eu-west-1.hvm-s3 = "ami-6c21af1f";
+  "16.03".eu-west-1.pv-ebs = "ami-a33cb2d0";
+  "16.03".eu-west-1.pv-s3 = "ami-ec38b69f";
+  "16.03".sa-east-1.hvm-ebs = "ami-5bef6637";
+  "16.03".sa-east-1.hvm-s3 = "ami-55f87139";
+  "16.03".sa-east-1.pv-ebs = "ami-76e56c1a";
+  "16.03".sa-east-1.pv-s3 = "ami-e1f8718d";
+  "16.03".us-east-1.hvm-ebs = "ami-4bfd1926";
+  "16.03".us-east-1.hvm-s3 = "ami-60c5210d";
+  "16.03".us-east-1.pv-ebs = "ami-c0c92dad";
+  "16.03".us-east-1.pv-s3 = "ami-f9d63294";
+  "16.03".us-west-1.hvm-ebs = "ami-13aad473";
+  "16.03".us-west-1.hvm-s3 = "ami-e1a8d681";
+  "16.03".us-west-1.pv-ebs = "ami-c0a6d8a0";
+  "16.03".us-west-1.pv-s3 = "ami-6aa9d70a";
+  "16.03".us-west-2.hvm-ebs = "ami-265dad46";
+  "16.03".us-west-2.hvm-s3 = "ami-cd40b0ad";
+  "16.03".us-west-2.pv-ebs = "ami-7b4aba1b";
+  "16.03".us-west-2.pv-s3 = "ami-0849b968";
 }
diff --git a/nixos/release.nix b/nixos/release.nix
index d78c1bb1c150..8409191200c8 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -103,6 +103,19 @@ in rec {
   # Build the initial ramdisk so Hydra can keep track of its size over time.
   initialRamdisk = buildFromConfig ({ pkgs, ... }: { }) (config: config.system.build.initialRamdisk);
 
+  netboot.x86_64-linux = let build = (import lib/eval-config.nix {
+      system = "x86_64-linux";
+      modules = [
+        ./modules/installer/netboot/netboot-minimal.nix
+        versionModule
+      ];
+    }).config.system.build;
+  in
+    pkgs.symlinkJoin {name="netboot"; paths=[
+      build.netbootRamdisk
+      build.kernel
+      build.netbootIpxeScript
+    ];};
 
   iso_minimal = forAllSystems (system: makeIso {
     module = ./modules/installer/cd-dvd/installation-cd-minimal.nix;
diff --git a/nixos/tests/boot.nix b/nixos/tests/boot.nix
index 905d16458825..af7db5aa8164 100644
--- a/nixos/tests/boot.nix
+++ b/nixos/tests/boot.nix
@@ -44,5 +44,44 @@ in {
         usb => glob("${iso}/iso/*.iso"),
         bios => '${pkgs.OVMF}/FV/OVMF.fd'
       '';
-  }
-
+    netboot = let
+      config = (import ../lib/eval-config.nix {
+          inherit system;
+          modules =
+            [ ../modules/installer/netboot/netboot.nix
+              ../modules/testing/test-instrumentation.nix
+              { key = "serial"; }
+            ];
+        }).config;
+      ipxeScriptDir = pkgs.writeTextFile {
+        name = "ipxeScriptDir";
+        text = ''
+          #!ipxe
+          dhcp
+          kernel bzImage init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} console=ttyS0
+          initrd initrd
+          boot
+        '';
+        destination = "/boot.ipxe";
+      };
+      ipxeBootDir = pkgs.symlinkJoin {
+        name = "ipxeBootDir";
+        paths = [
+          config.system.build.netbootRamdisk
+          config.system.build.kernel
+          ipxeScriptDir
+        ];
+      };
+    in
+      makeTest {
+        name = "boot-netboot";
+        nodes = { };
+        testScript =
+          ''
+            my $machine = createMachine({ qemuFlags => '-boot order=n -net nic,model=e1000 -net user,tftp=${ipxeBootDir}/,bootfile=boot.ipxe -m 2000M' });
+            $machine->start;
+            $machine->waitForUnit("multi-user.target");
+            $machine->shutdown;
+          '';
+      };
+}