summary refs log tree commit diff
path: root/nixos/modules/services
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/services')
-rw-r--r--nixos/modules/services/databases/postgresql.nix6
-rw-r--r--nixos/modules/services/databases/redis.nix5
-rw-r--r--nixos/modules/services/desktops/accountsservice.nix8
-rw-r--r--nixos/modules/services/editors/emacs.nix2
-rw-r--r--nixos/modules/services/mail/opensmtpd.nix2
-rw-r--r--nixos/modules/services/misc/gitit.nix2
-rw-r--r--nixos/modules/services/misc/gitlab.nix41
-rw-r--r--nixos/modules/services/misc/gitlab.xml17
-rw-r--r--nixos/modules/services/misc/nix-daemon.nix2
-rw-r--r--nixos/modules/services/misc/nixos-manual.nix2
-rw-r--r--nixos/modules/services/misc/taskserver/default.nix3
-rw-r--r--nixos/modules/services/networking/cjdns.nix2
-rw-r--r--nixos/modules/services/networking/dnscrypt-proxy.nix48
-rw-r--r--nixos/modules/services/networking/dnscrypt-proxy.xml76
-rw-r--r--nixos/modules/services/networking/ferm.nix63
-rw-r--r--nixos/modules/services/networking/mjpg-streamer.nix8
-rw-r--r--nixos/modules/services/networking/quagga.nix187
-rw-r--r--nixos/modules/services/networking/teamspeak3.nix75
-rw-r--r--nixos/modules/services/networking/unbound.nix10
-rw-r--r--nixos/modules/services/networking/wpa_supplicant.nix99
-rw-r--r--nixos/modules/services/networking/zerotierone.nix16
-rw-r--r--nixos/modules/services/printing/cupsd.nix6
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix2
-rw-r--r--nixos/modules/services/web-servers/nginx/location-options.nix21
-rw-r--r--nixos/modules/services/x11/desktop-managers/enlightenment.nix2
-rw-r--r--nixos/modules/services/x11/display-managers/default.nix3
26 files changed, 548 insertions, 160 deletions
diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix
index 80ee32f4ee33..24ef4637ec98 100644
--- a/nixos/modules/services/databases/postgresql.nix
+++ b/nixos/modules/services/databases/postgresql.nix
@@ -11,12 +11,14 @@ let
     if cfg.extraPlugins == [] then pg
     else pkgs.buildEnv {
       name = "postgresql-and-plugins-${(builtins.parseDrvName pg.name).version}";
-      paths = [ pg ] ++ cfg.extraPlugins;
+      paths = [ pg pg.lib ] ++ cfg.extraPlugins;
+      buildInputs = [ pkgs.makeWrapper ];
       postBuild =
         ''
           mkdir -p $out/bin
           rm $out/bin/{pg_config,postgres,pg_ctl}
           cp --target-directory=$out/bin ${pg}/bin/{postgres,pg_config,pg_ctl}
+          wrapProgram $out/bin/postgres --set NIX_PGLIBDIR $out/lib
         '';
     };
 
@@ -253,4 +255,6 @@ in
 
   };
 
+  meta.doc = ./postgresql.xml;
+
 }
diff --git a/nixos/modules/services/databases/redis.nix b/nixos/modules/services/databases/redis.nix
index 480e1184ffa3..a039ad138f6f 100644
--- a/nixos/modules/services/databases/redis.nix
+++ b/nixos/modules/services/databases/redis.nix
@@ -234,9 +234,8 @@ in
         serviceConfig.Type = "oneshot";
 
         script = ''
-          if ! test -e ${cfg.dbpath}; then
-              install -d -m0700 -o ${cfg.user} ${cfg.dbpath}
-          fi
+          install -d -m0700 -o ${cfg.user} ${cfg.dbpath}
+          chown -R ${cfg.user} ${cfg.dbpath}
         '';
       };
 
diff --git a/nixos/modules/services/desktops/accountsservice.nix b/nixos/modules/services/desktops/accountsservice.nix
index c28c27295761..2a7450669ea0 100644
--- a/nixos/modules/services/desktops/accountsservice.nix
+++ b/nixos/modules/services/desktops/accountsservice.nix
@@ -35,6 +35,14 @@ with lib;
     services.dbus.packages = [ pkgs.accountsservice ];
 
     systemd.packages = [ pkgs.accountsservice ];
+
+    systemd.services.accounts-daemon= {
+
+      wantedBy = [ "graphical.target" ];
+
+    } // (mkIf (!config.users.mutableUsers) {
+      environment.NIXOS_USERS_PURE = "true";
+    });
   };
 
 }
diff --git a/nixos/modules/services/editors/emacs.nix b/nixos/modules/services/editors/emacs.nix
index 43b4219c51dd..6795ec52fe4d 100644
--- a/nixos/modules/services/editors/emacs.nix
+++ b/nixos/modules/services/editors/emacs.nix
@@ -83,4 +83,6 @@ in {
       EDITOR = mkOverride 900 "${editorScript}/bin/emacseditor";
     } else {};
   };
+
+  meta.doc = ./emacs.xml;
 }
diff --git a/nixos/modules/services/mail/opensmtpd.nix b/nixos/modules/services/mail/opensmtpd.nix
index e773cdedaea2..fb94560e10aa 100644
--- a/nixos/modules/services/mail/opensmtpd.nix
+++ b/nixos/modules/services/mail/opensmtpd.nix
@@ -109,12 +109,14 @@ in {
       after = [ "network.target" ];
       preStart = ''
         mkdir -p /var/spool/smtpd
+        chmod 711 /var/spool/smtpd
 
         mkdir -p /var/spool/smtpd/offline
         chown root.smtpq /var/spool/smtpd/offline
         chmod 770 /var/spool/smtpd/offline
 
         mkdir -p /var/spool/smtpd/purge
+        chown smtpq.root /var/spool/smtpd/purge
         chmod 700 /var/spool/smtpd/purge
       '';
       serviceConfig.ExecStart = "${opensmtpd}/sbin/smtpd -d -f ${conf} ${args}";
diff --git a/nixos/modules/services/misc/gitit.nix b/nixos/modules/services/misc/gitit.nix
index befd8c628f16..44880ebeda14 100644
--- a/nixos/modules/services/misc/gitit.nix
+++ b/nixos/modules/services/misc/gitit.nix
@@ -663,7 +663,7 @@ in
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
       path = with pkgs; [ curl ]
-             ++ optional cfg.pdfExport texLiveFull
+             ++ optional cfg.pdfExport texlive.combined.scheme-basic
 	     ++ optional (cfg.repositoryType == "darcs") darcs
 	     ++ optional (cfg.repositoryType == "mercurial") mercurial
 	     ++ optional (cfg.repositoryType == "git") git;
diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix
index 39283d2d9437..b3f09999adba 100644
--- a/nixos/modules/services/misc/gitlab.nix
+++ b/nixos/modules/services/misc/gitlab.nix
@@ -43,7 +43,9 @@ let
 
   secretsYml = ''
     production:
-      db_key_base: ${cfg.secrets.db_key_base}
+      secret_key_base: ${cfg.secrets.secret}
+      otp_key_base: ${cfg.secrets.otp}
+      db_key_base: ${cfg.secrets.db}
   '';
 
   gitlabConfig = {
@@ -121,7 +123,7 @@ let
       makeWrapper ${cfg.packages.gitlab.env}/bin/bundle $out/bin/gitlab-bundle \
           ${concatStrings (mapAttrsToList (name: value: "--set ${name} '${value}' ") gitlabEnv)} \
           --set GITLAB_CONFIG_PATH '${cfg.statePath}/config' \
-          --set PATH '${stdenv.lib.makeBinPath [ pkgs.nodejs pkgs.gzip config.services.postgresql.package ]}:$PATH' \
+          --set PATH '${lib.makeBinPath [ pkgs.nodejs pkgs.gzip config.services.postgresql.package ]}:$PATH' \
           --set RAKEOPT '-f ${cfg.packages.gitlab}/share/gitlab/Rakefile' \
           --run 'cd ${cfg.packages.gitlab}/share/gitlab'
       makeWrapper $out/bin/gitlab-bundle $out/bin/gitlab-rake \
@@ -318,11 +320,10 @@ in {
         };
       };
 
-      secrets.db_key_base = mkOption {
+      secrets.secret = mkOption {
         type = types.str;
-        example = "";
         description = ''
-          The db_key_base secrets is used to encrypt variables in the DB. If
+          The secret is used to encrypt variables in the DB. If
           you change or lose this key you will be unable to access variables
           stored in database.
 
@@ -331,6 +332,30 @@ in {
         '';
       };
 
+      secrets.db = mkOption {
+        type = types.str;
+        description = ''
+          The secret is used to encrypt variables in the DB. If
+          you change or lose this key you will be unable to access variables
+          stored in database.
+
+          Make sure the secret is at least 30 characters and all random,
+          no regular words or you'll be exposed to dictionary attacks.
+        '';
+      };
+
+      secrets.otp = mkOption {
+        type = types.str;
+        description = ''
+          The secret is used to encrypt secrets for OTP tokens. If
+          you change or lose this key, users which have 2FA enabled for login
+          won't be able to login anymore.
+
+          Make sure the secret is at least 30 characters and all random,
+          no regular words or you'll be exposed to dictionary attacks.
+        '';
+      };
+
       extraConfig = mkOption {
         type = types.attrs;
         default = {};
@@ -458,8 +483,7 @@ in {
         rm -rf ${cfg.statePath}/config ${cfg.statePath}/shell/hooks
         mkdir -p ${cfg.statePath}/config ${cfg.statePath}/shell
 
-        # TODO: What exactly is gitlab-shell doing with the secret?
-        tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c 20 > ${cfg.statePath}/config/gitlab_shell_secret
+        tr -dc A-Za-z0-9 < /dev/urandom | head -c 32 > ${cfg.statePath}/config/gitlab_shell_secret
 
         # The uploads directory is hardcoded somewhere deep in rails. It is
         # symlinked in the gitlab package to /run/gitlab/uploads to make it
@@ -532,4 +556,7 @@ in {
     };
 
   };
+
+  meta.doc = ./gitlab.xml;
+
 }
diff --git a/nixos/modules/services/misc/gitlab.xml b/nixos/modules/services/misc/gitlab.xml
index 83f715a50b43..f9636f8e1278 100644
--- a/nixos/modules/services/misc/gitlab.xml
+++ b/nixos/modules/services/misc/gitlab.xml
@@ -62,7 +62,11 @@ services.gitlab = {
     address = "localhost";
     port = 25;
   };
-  secrets.db_key_base = "ei3eeP1ohsh0uu3ad4YeeMeeheengah3AiZee2ohl4Ooj5mie4Ohl0vishoghaes";
+  secrets = {
+    db = "uPgq1gtwwHiatiuE0YHqbGa5lEIXH7fMsvuTNgdzJi8P0Dg12gibTzBQbq5LT7PNzcc3BP9P1snHVnduqtGF43PgrQtU7XL93ts6gqe9CBNhjtaqUwutQUDkygP5NrV6";
+    secret = "devzJ0Tz0POiDBlrpWmcsjjrLaltyiAdS8TtgT9YNBOoUcDsfppiY3IXZjMVtKgXrFImIennFGOpPN8IkP8ATXpRgDD5rxVnKuTTwYQaci2NtaV1XxOQGjdIE50VGsR3";
+    otp = "e1GATJVuS2sUh7jxiPzZPre4qtzGGaS22FR50Xs1TerRVdgI3CBVUi5XYtQ38W4xFeS4mDqi5cQjExE838iViSzCdcG19XSL6qNsfokQP9JugwiftmhmCadtsnHErBMI";
+  };
   extraConfig = {
     gitlab = {
       email_from = "gitlab-no-reply@example.com";
@@ -75,11 +79,12 @@ services.gitlab = {
 </programlisting>
 </para>
 
-<para>If you're setting up a new Gitlab instance, generate a new
-<literal>db_key_base</literal> secret to encrypt sensible data in the
-database. If you're restoring an existing Gitlab instance, you must
-specify the <literal>db_key_base</literal> secret from
-<literal>config/secrets.yml</literal> in your Gitlab state folder.</para>
+<para>If you're setting up a new Gitlab instance, generate new secrets. You
+for instance use <literal>tr -dc A-Za-z0-9 &lt; /dev/urandom | head -c 128</literal>
+to generate a new secret. Gitlab encrypts sensitive data stored in the database.
+If you're restoring an existing Gitlab instance, you must specify the secrets
+secret from <literal>config/secrets.yml</literal> located in your Gitlab state
+folder.</para>
 
 <para>Refer to <xref linkend="ch-options" /> for all available configuration
 options for the <literal>services.gitlab</literal> module.</para>
diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix
index fe5132d4973e..333782d15bcb 100644
--- a/nixos/modules/services/misc/nix-daemon.nix
+++ b/nixos/modules/services/misc/nix-daemon.nix
@@ -311,7 +311,7 @@ in
       nixPath = mkOption {
         type = types.listOf types.str;
         default =
-          [ "/nix/var/nix/profiles/per-user/root/channels/nixos"
+          [ "nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs"
             "nixos-config=/etc/nixos/configuration.nix"
             "/nix/var/nix/profiles/per-user/root/channels"
           ];
diff --git a/nixos/modules/services/misc/nixos-manual.nix b/nixos/modules/services/misc/nixos-manual.nix
index a60d5f7983bc..306ee346523d 100644
--- a/nixos/modules/services/misc/nixos-manual.nix
+++ b/nixos/modules/services/misc/nixos-manual.nix
@@ -17,7 +17,7 @@ let
     Caveat: even if the package is reached by a different means,
     the path above will be shown and not e.g. `${config.services.foo.package}`. */
   manual = import ../../../doc/manual {
-    inherit pkgs;
+    inherit pkgs config;
     version = config.system.nixosRelease;
     revision = "release-${config.system.nixosRelease}";
     options =
diff --git a/nixos/modules/services/misc/taskserver/default.nix b/nixos/modules/services/misc/taskserver/default.nix
index c846ffd04551..6d458feec345 100644
--- a/nixos/modules/services/misc/taskserver/default.nix
+++ b/nixos/modules/services/misc/taskserver/default.nix
@@ -534,6 +534,7 @@ in {
     (mkIf (cfg.enable && cfg.listenHost != "localhost") {
       networking.firewall.allowedTCPPorts = [ cfg.listenPort ];
     })
-    { meta.doc = ./taskserver.xml; }
   ];
+
+  meta.doc = ./doc.xml;
 }
diff --git a/nixos/modules/services/networking/cjdns.nix b/nixos/modules/services/networking/cjdns.nix
index f4063a3406f1..0495b32c6fa8 100644
--- a/nixos/modules/services/networking/cjdns.nix
+++ b/nixos/modules/services/networking/cjdns.nix
@@ -253,7 +253,7 @@ in
     networking.extraHosts = "${cjdnsHosts}";
 
     assertions = [
-      { assertion = ( cfg.ETHInterface.bind != "" || cfg.UDPInterface.bind != "" || cfg.confFile == "" );
+      { assertion = ( cfg.ETHInterface.bind != "" || cfg.UDPInterface.bind != "" || cfg.confFile != "" );
         message = "Neither cjdns.ETHInterface.bind nor cjdns.UDPInterface.bind defined.";
       }
       { assertion = config.networking.enableIPv6;
diff --git a/nixos/modules/services/networking/dnscrypt-proxy.nix b/nixos/modules/services/networking/dnscrypt-proxy.nix
index cf36ccf05725..2714e8d75993 100644
--- a/nixos/modules/services/networking/dnscrypt-proxy.nix
+++ b/nixos/modules/services/networking/dnscrypt-proxy.nix
@@ -28,31 +28,15 @@ let
 in
 
 {
+  meta = {
+    maintainers = with maintainers; [ joachifm ];
+    doc = ./dnscrypt-proxy.xml;
+  };
+
   options = {
     services.dnscrypt-proxy = {
-      enable = mkEnableOption "dnscrypt-proxy" // { description = ''
-        Whether to enable the DNSCrypt client proxy. The proxy relays
-        DNS queries to a DNSCrypt enabled upstream resolver. The traffic
-        between the client and the upstream resolver is encrypted and
-        authenticated, mitigating the risk of MITM attacks and third-party
-        snooping (assuming the upstream is trustworthy).
-
-        Enabling this option does not alter the system nameserver; to relay
-        local queries, prepend <literal>127.0.0.1</literal> to
-        <option>networking.nameservers</option>.
-
-        The recommended configuration is to run DNSCrypt proxy as a forwarder
-        for a caching DNS client, as in
-        <programlisting>
-        {
-          services.dnscrypt-proxy.enable = true;
-          services.dnscrypt-proxy.localPort = 43;
-          services.dnsmasq.enable = true;
-          services.dnsmasq.servers = [ "127.0.0.1#43" ];
-          services.dnsmasq.resolveLocalQueries = true; # this is the default
-        }
-        </programlisting>
-      ''; };
+      enable = mkEnableOption "DNSCrypt client proxy";
+
       localAddress = mkOption {
         default = "127.0.0.1";
         type = types.str;
@@ -62,6 +46,7 @@ in
           of other machines (typically on the local network).
         '';
       };
+
       localPort = mkOption {
         default = 53;
         type = types.int;
@@ -72,6 +57,7 @@ in
           to a different value; otherwise leave the default.
         '';
       };
+
       resolverName = mkOption {
         default = "dnscrypt.eu-nl";
         type = types.nullOr types.str;
@@ -82,6 +68,7 @@ in
           extensions, and claims to not keep logs.
         '';
       };
+
       resolverList = mkOption {
         description = ''
           The list of upstream DNSCrypt resolvers. By default, we use the most
@@ -94,6 +81,7 @@ in
         };
         defaultText = "pkgs.fetchurl { url = ...; sha256 = ...; }";
       };
+
       customResolver = mkOption {
         default = null;
         description = ''
@@ -103,26 +91,30 @@ in
         type = types.nullOr (types.submodule ({ ... }: { options = {
           address = mkOption {
             type = types.str;
-            description = "Resolver IP address";
+            description = "IP address";
             example = "208.67.220.220";
           };
+
           port = mkOption {
             type = types.int;
-            description = "Resolver port";
+            description = "Port";
             default = 443;
           };
+
           name = mkOption {
             type = types.str;
-            description = "Provider fully qualified domain name";
+            description = "Fully qualified domain name";
             example = "2.dnscrypt-cert.opendns.com";
           };
+
           key = mkOption {
             type = types.str;
-            description = "Provider public key";
+            description = "Public key";
             example = "B735:1140:206F:225D:3E2B:D822:D7FD:691E:A1C3:3CC8:D666:8D0C:BE04:BFAB:CA43:FB79";
           };
         }; }));
       };
+
       tcpOnly = mkOption {
         default = false;
         type = types.bool;
@@ -131,6 +123,7 @@ in
           TCP instead of UDP (on port 443). Use only if the UDP port is blocked.
         '';
       };
+
       ephemeralKeys = mkOption {
         default = false;
         type = types.bool;
@@ -212,7 +205,6 @@ in
         ExecStart = "${dnscrypt-proxy}/bin/dnscrypt-proxy ${toString daemonArgs}";
 
         User = "dnscrypt-proxy";
-        Group = "dnscrypt-proxy";
 
         PrivateTmp = true;
         PrivateDevices = true;
diff --git a/nixos/modules/services/networking/dnscrypt-proxy.xml b/nixos/modules/services/networking/dnscrypt-proxy.xml
new file mode 100644
index 000000000000..e212a8d3e2c3
--- /dev/null
+++ b/nixos/modules/services/networking/dnscrypt-proxy.xml
@@ -0,0 +1,76 @@
+<chapter 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-dnscrypt-proxy">
+
+  <title>DNSCrypt client proxy</title>
+
+  <para>
+    The DNSCrypt client proxy relays DNS queries to a DNSCrypt enabled
+    upstream resolver. The traffic between the client and the upstream
+    resolver is encrypted and authenticated, mitigating the risk of MITM
+    attacks, DNS poisoning attacks, and third-party snooping (assuming the
+    upstream is trustworthy).
+  </para>
+
+  <sect1><title>Basic configuration</title>
+
+  <para>
+    To enable the client proxy, set
+    <programlisting>
+      services.dnscrypt-proxy.enable = true;
+    </programlisting>
+  </para>
+
+  <para>
+    Enabling the client proxy does not alter the system nameserver; to
+    relay local queries, prepend <literal>127.0.0.1</literal> to
+    <option>networking.nameservers</option>.
+  </para>
+
+  </sect1>
+
+  <sect1><title>As a forwarder for a caching DNS client</title>
+
+  <para>
+    By default, DNSCrypt proxy acts as a transparent proxy for the
+    system stub resolver. Because the client does not cache lookups, this
+    setup can significantly slow down e.g., web browsing. The recommended
+    configuration is to run DNSCrypt proxy as a forwarder for a caching DNS
+    client. To achieve this, change the default proxy listening port to
+    a non-standard value and point the caching client to it:
+    <programlisting>
+      services.dnscrypt-proxy.localPort = 43;
+    </programlisting>
+  </para>
+
+  <sect2><title>dnsmasq</title>
+  <para>
+    <programlisting>
+      {
+      services.dnsmasq.enable = true;
+      services.dnsmasq.servers = [ "127.0.0.1#43" ];
+      }
+    </programlisting>
+  </para>
+  </sect2>
+
+  <sect2><title>unbound</title>
+  <para>
+    <programlisting>
+      {
+      networking.nameservers = [ "127.0.0.1" ];
+      services.unbound.enable = true;
+      services.unbound.forwardAddresses = [ "127.0.0.1@43" ];
+      services.unbound.extraConfig = ''
+        do-not-query-localhost: no
+      '';
+      }
+    </programlisting>
+  </para>
+  </sect2>
+
+  </sect1>
+
+</chapter>
diff --git a/nixos/modules/services/networking/ferm.nix b/nixos/modules/services/networking/ferm.nix
new file mode 100644
index 000000000000..6271e82541f4
--- /dev/null
+++ b/nixos/modules/services/networking/ferm.nix
@@ -0,0 +1,63 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.ferm;
+
+  configFile = pkgs.stdenv.mkDerivation {
+    name = "ferm.conf";
+    text = cfg.config;
+    preferLocalBuild = true;
+    buildCommand = ''
+      echo -n "$text" > $out
+      ${cfg.package}/bin/ferm --noexec $out
+    '';
+  };
+in {
+  options = {
+    services.ferm = {
+      enable = mkOption {
+        default = false;
+        example = true;
+        type = types.bool;
+        description = ''
+          Whether to enable Ferm Firewall.
+          *Warning*: Enabling this service WILL disable the existing NixOS
+          firewall! Default firewall rules provided by packages are not
+          considered at the moment.
+        '';
+      };
+      config = mkOption {
+        description = "Verbatim ferm.conf configuration.";
+        default = "";
+        defaultText = "empty firewall, allows any traffic";
+        type = types.lines;
+      };
+      package = mkOption {
+        description = "The ferm package.";
+        type = types.package;
+        default = pkgs.ferm;
+        defaultText = "pkgs.ferm";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.firewall.enable = false;
+    systemd.services.ferm = {
+      description = "Ferm Firewall";
+      after = [ "ipset.target" ];
+      before = [ "network-pre.target" ];
+      wants = [ "network-pre.target" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        Type="oneshot";
+        RemainAfterExit = "yes";
+        ExecStart = "${cfg.package}/bin/ferm ${configFile}";
+        ExecReload = "${cfg.package}/bin/ferm ${configFile}";
+        ExecStop = "${cfg.package}/bin/ferm -F ${configFile}";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/networking/mjpg-streamer.nix b/nixos/modules/services/networking/mjpg-streamer.nix
index 9986f549aecf..1286b0c7ef6c 100644
--- a/nixos/modules/services/networking/mjpg-streamer.nix
+++ b/nixos/modules/services/networking/mjpg-streamer.nix
@@ -59,8 +59,12 @@ in {
       description = "mjpg-streamer webcam streamer";
       wantedBy = [ "multi-user.target" ];
 
-      serviceConfig.User = cfg.user;
-      serviceConfig.Group = cfg.group;
+      serviceConfig = {
+        User = cfg.user;
+        Group = cfg.group;
+        Restart = "on-failure";
+        RestartSec = 1;
+      };
 
       script = ''
         IPLUGIN="${cfg.inputPlugin}"
diff --git a/nixos/modules/services/networking/quagga.nix b/nixos/modules/services/networking/quagga.nix
new file mode 100644
index 000000000000..ac83da920638
--- /dev/null
+++ b/nixos/modules/services/networking/quagga.nix
@@ -0,0 +1,187 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.quagga;
+
+  services = [ "babel" "bgp" "isis" "ospf6" "ospf" "pim" "rip" "ripng" ];
+  allServices = services ++ [ "zebra" ];
+
+  isEnabled = service: cfg.${service}.enable;
+
+  daemonName = service: if service == "zebra" then service else "${service}d";
+
+  configFile = service:
+    let
+      scfg = cfg.${service};
+    in
+      if scfg.configFile != null then scfg.configFile
+      else pkgs.writeText "${daemonName service}.conf"
+        ''
+          ! Quagga ${daemonName service} configuration
+          !
+          hostname ${config.networking.hostName}
+          log syslog
+          service password-encryption
+          !
+          ${scfg.config}
+          !
+          end
+        '';
+
+  serviceOptions = service:
+    {
+      enable = mkEnableOption "the Quagga ${toUpper service} routing protocol";
+
+      configFile = mkOption {
+        type = types.nullOr types.path;
+        default = null;
+        example = "/etc/quagga/${daemonName service}.conf";
+        description = ''
+          Configuration file to use for Quagga ${daemonName service}.
+          By default the NixOS generated files are used.
+        '';
+      };
+
+      config = mkOption {
+        type = types.lines;
+        default = "";
+        example =
+          let
+            examples = {
+              rip = ''
+                router rip
+                  network 10.0.0.0/8
+              '';
+
+              ospf = ''
+                router ospf
+                  network 10.0.0.0/8 area 0
+              '';
+
+              bgp = ''
+                router bgp 65001
+                  neighbor 10.0.0.1 remote-as 65001
+              '';
+            };
+          in
+            examples.${service} or "";
+        description = ''
+          ${daemonName service} configuration statements.
+        '';
+      };
+
+      vtyListenAddress = mkOption {
+        type = types.str;
+        default = "127.0.0.1";
+        description = ''
+          Address to bind to for the VTY interface.
+        '';
+      };
+
+      vtyListenPort = mkOption {
+        type = types.nullOr types.int;
+        default = null;
+        description = ''
+          TCP Port to bind to for the VTY interface.
+        '';
+      };
+    };
+
+in
+
+{
+
+  ###### interface
+
+  options.services.quagga =
+    {
+
+      zebra = (serviceOptions "zebra") // {
+
+        enable = mkOption {
+          type = types.bool;
+          default = any isEnabled services;
+          example = true;
+          description = ''
+            Whether to enable the Zebra routing manager.
+
+            The Zebra routing manager is automatically enabled
+            if any routing protocols are configured.
+          '';
+        };
+
+      };
+
+    } // (genAttrs services serviceOptions);
+
+  ###### implementation
+
+  config = mkIf (any isEnabled allServices) {
+
+    environment.systemPackages = [
+      pkgs.quagga               # for the vtysh tool
+    ];
+
+    users.users.quagga = {
+      description = "Quagga daemon user";
+      isSystemUser = true;
+      group = "quagga";
+    };
+
+    users.groups = {
+      quagga = {};
+      # Members of the quaggavty group can use vtysh to inspect the Quagga daemons
+      quaggavty = {};
+    };
+
+    systemd.services =
+      let
+        quaggaService = service:
+          let
+            scfg = cfg.${service};
+            daemon = daemonName service;
+          in
+            nameValuePair daemon ({
+              wantedBy = [ "multi-user.target" ];
+              restartTriggers = [ (configFile service) ];
+
+              serviceConfig = {
+                Type = "forking";
+                PIDFile = "/run/quagga/${daemon}.pid";
+                ExecStart = "@${pkgs.quagga}/libexec/quagga/${daemon} ${daemon} -d -f ${configFile service}"
+                  + optionalString (scfg.vtyListenAddress != "") " -A ${scfg.vtyListenAddress}"
+                  + optionalString (scfg.vtyListenPort != null) " -P ${toString scfg.vtyListenPort}";
+                ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+                Restart = "on-abort";
+              };
+            } // (
+              if service == "zebra" then
+                {
+                  description = "Quagga Zebra routing manager";
+                  unitConfig.Documentation = "man:zebra(8)";
+                  after = [ "network.target" ];
+                  preStart = ''
+                    install -m 0755 -o quagga -g quagga -d /run/quagga
+
+                    ${pkgs.iproute}/bin/ip route flush proto zebra
+                  '';
+                }
+              else
+                {
+                  description = "Quagga ${toUpper service} routing daemon";
+                  unitConfig.Documentation = "man:${daemon}(8) man:zebra(8)";
+                  bindsTo = [ "zebra.service" ];
+                  after = [ "network.target" "zebra.service" ];
+                }
+            ));
+       in
+         listToAttrs (map quaggaService (filter isEnabled allServices));
+
+  };
+
+  meta.maintainers = with lib.maintainers; [ tavyc ];
+
+}
diff --git a/nixos/modules/services/networking/teamspeak3.nix b/nixos/modules/services/networking/teamspeak3.nix
index 5f04926eed24..3703921ff703 100644
--- a/nixos/modules/services/networking/teamspeak3.nix
+++ b/nixos/modules/services/networking/teamspeak3.nix
@@ -95,47 +95,44 @@ in
 
   ###### implementation
 
-  config = mkMerge [
-    (mkIf cfg.enable {
-      users.users.teamspeak = {
-        description = "Teamspeak3 voice communication server daemon";
-        group = group;
-        uid = config.ids.uids.teamspeak;
-        home = cfg.dataDir;
-        createHome = true;
-      };
-
-      users.groups.teamspeak = {
-        gid = config.ids.gids.teamspeak;
-      };
+  config = mkIf cfg.enable {
+    users.users.teamspeak = {
+      description = "Teamspeak3 voice communication server daemon";
+      group = group;
+      uid = config.ids.uids.teamspeak;
+      home = cfg.dataDir;
+      createHome = true;
+    };
 
-      systemd.services.teamspeak3-server = {
-        description = "Teamspeak3 voice communication server daemon";
-        after = [ "network.target" ];
-        wantedBy = [ "multi-user.target" ];
+    users.groups.teamspeak = {
+      gid = config.ids.gids.teamspeak;
+    };
 
-        preStart = ''
-          mkdir -p ${cfg.logPath}
-          chown ${user}:${group} ${cfg.logPath}
+    systemd.services.teamspeak3-server = {
+      description = "Teamspeak3 voice communication server daemon";
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+
+      preStart = ''
+        mkdir -p ${cfg.logPath}
+        chown ${user}:${group} ${cfg.logPath}
+      '';
+
+      serviceConfig = {
+        ExecStart = ''
+          ${ts3}/bin/ts3server \
+            dbsqlpath=${ts3}/lib/teamspeak/sql/ logpath=${cfg.logPath} \
+            voice_ip=${cfg.voiceIP} default_voice_port=${toString cfg.defaultVoicePort} \
+            filetransfer_ip=${cfg.fileTransferIP} filetransfer_port=${toString cfg.fileTransferPort} \
+            query_ip=${cfg.queryIP} query_port=${toString cfg.queryPort}
         '';
-
-        serviceConfig = {
-          ExecStart = ''
-            ${ts3}/bin/ts3server \
-              dbsqlpath=${ts3}/lib/teamspeak/sql/ logpath=${cfg.logPath} \
-              voice_ip=${cfg.voiceIP} default_voice_port=${toString cfg.defaultVoicePort} \
-              filetransfer_ip=${cfg.fileTransferIP} filetransfer_port=${toString cfg.fileTransferPort} \
-              query_ip=${cfg.queryIP} query_port=${toString cfg.queryPort}
-          '';
-          WorkingDirectory = cfg.dataDir;
-          User = user;
-          Group = group;
-          PermissionsStartOnly = true;
-        };
+        WorkingDirectory = cfg.dataDir;
+        User = user;
+        Group = group;
+        PermissionsStartOnly = true;
       };
-    })
-    {
-      meta.maintainers = with lib.maintainers; [ arobyn ];
-    }
-  ];
+    };
+  };
+
+  meta.maintainers = with lib.maintainers; [ arobyn ];
 }
diff --git a/nixos/modules/services/networking/unbound.nix b/nixos/modules/services/networking/unbound.nix
index 0dd24478f409..ed0744c44ccf 100644
--- a/nixos/modules/services/networking/unbound.nix
+++ b/nixos/modules/services/networking/unbound.nix
@@ -43,14 +43,10 @@ in
   options = {
     services.unbound = {
 
-      enable = mkOption {
-        default = false;
-        type = types.bool;
-        description = "Whether to enable the Unbound domain name server.";
-      };
+      enable = mkEnableOption "Unbound domain name server";
 
       allowedAccess = mkOption {
-        default = ["127.0.0.0/24"];
+        default = [ "127.0.0.0/24" ];
         type = types.listOf types.str;
         description = "What networks are allowed to use unbound as a resolver.";
       };
@@ -97,7 +93,7 @@ in
     };
 
     systemd.services.unbound = {
-      description="Unbound recursive Domain Name Server";
+      description = "Unbound recursive Domain Name Server";
       after = [ "network.target" ];
       before = [ "nss-lookup.target" ];
       wants = [" nss-lookup.target" ];
diff --git a/nixos/modules/services/networking/wpa_supplicant.nix b/nixos/modules/services/networking/wpa_supplicant.nix
index 8d22c10d3f78..de99ce4f0260 100644
--- a/nixos/modules/services/networking/wpa_supplicant.nix
+++ b/nixos/modules/services/networking/wpa_supplicant.nix
@@ -111,57 +111,54 @@ in {
     };
   };
 
-  config = mkMerge [
-    (mkIf cfg.enable {
-      assertions = flip mapAttrsToList cfg.networks (name: cfg: {
-        assertion = cfg.psk == null || cfg.pskRaw == null;
-        message = ''networking.wireless."${name}".psk and networking.wireless."${name}".pskRaw are mutually exclusive'';
-      });
-
-      environment.systemPackages =  [ pkgs.wpa_supplicant ];
-
-      services.dbus.packages = [ pkgs.wpa_supplicant ];
-
-      # FIXME: start a separate wpa_supplicant instance per interface.
-      systemd.services.wpa_supplicant = let
-        ifaces = cfg.interfaces;
-        deviceUnit = interface: [ "sys-subsystem-net-devices-${interface}.device" ];
-      in {
-        description = "WPA Supplicant";
-
-        after = [ "network-interfaces.target" ] ++ lib.concatMap deviceUnit ifaces;
-        requires = lib.concatMap deviceUnit ifaces;
-        wantedBy = [ "network.target" ];
-
-        path = [ pkgs.wpa_supplicant ];
-
-        script = ''
-          ${if ifaces == [] then ''
-            for i in $(cd /sys/class/net && echo *); do
-              DEVTYPE=
-              source /sys/class/net/$i/uevent
-              if [ "$DEVTYPE" = "wlan" -o -e /sys/class/net/$i/wireless ]; then
-                ifaces="$ifaces''${ifaces:+ -N} -i$i"
-              fi
-            done
-          '' else ''
-            ifaces="${concatStringsSep " -N " (map (i: "-i${i}") ifaces)}"
-          ''}
-          exec wpa_supplicant -s -u -D${cfg.driver} -c ${configFile} $ifaces
-        '';
-      };
-
-      powerManagement.resumeCommands = ''
-        ${config.systemd.package}/bin/systemctl try-restart wpa_supplicant
+  config = mkIf cfg.enable {
+    assertions = flip mapAttrsToList cfg.networks (name: cfg: {
+      assertion = cfg.psk == null || cfg.pskRaw == null;
+      message = ''networking.wireless."${name}".psk and networking.wireless."${name}".pskRaw are mutually exclusive'';
+    });
+
+    environment.systemPackages =  [ pkgs.wpa_supplicant ];
+
+    services.dbus.packages = [ pkgs.wpa_supplicant ];
+
+    # FIXME: start a separate wpa_supplicant instance per interface.
+    systemd.services.wpa_supplicant = let
+      ifaces = cfg.interfaces;
+      deviceUnit = interface: [ "sys-subsystem-net-devices-${interface}.device" ];
+    in {
+      description = "WPA Supplicant";
+
+      after = [ "network-interfaces.target" ] ++ lib.concatMap deviceUnit ifaces;
+      requires = lib.concatMap deviceUnit ifaces;
+      wantedBy = [ "network.target" ];
+
+      path = [ pkgs.wpa_supplicant ];
+
+      script = ''
+        ${if ifaces == [] then ''
+          for i in $(cd /sys/class/net && echo *); do
+            DEVTYPE=
+            source /sys/class/net/$i/uevent
+            if [ "$DEVTYPE" = "wlan" -o -e /sys/class/net/$i/wireless ]; then
+              ifaces="$ifaces''${ifaces:+ -N} -i$i"
+            fi
+          done
+        '' else ''
+          ifaces="${concatStringsSep " -N " (map (i: "-i${i}") ifaces)}"
+        ''}
+        exec wpa_supplicant -s -u -D${cfg.driver} -c ${configFile} $ifaces
       '';
+    };
 
-      # Restart wpa_supplicant when a wlan device appears or disappears.
-      services.udev.extraRules = ''
-        ACTION=="add|remove", SUBSYSTEM=="net", ENV{DEVTYPE}=="wlan", RUN+="${config.systemd.package}/bin/systemctl try-restart wpa_supplicant.service"
-      '';
-    })
-    {
-      meta.maintainers = with lib.maintainers; [ globin ];
-    }
-  ];
+    powerManagement.resumeCommands = ''
+      ${config.systemd.package}/bin/systemctl try-restart wpa_supplicant
+    '';
+
+    # Restart wpa_supplicant when a wlan device appears or disappears.
+    services.udev.extraRules = ''
+      ACTION=="add|remove", SUBSYSTEM=="net", ENV{DEVTYPE}=="wlan", RUN+="${config.systemd.package}/bin/systemctl try-restart wpa_supplicant.service"
+    '';
+  };
+
+  meta.maintainers = with lib.maintainers; [ globin ];
 }
diff --git a/nixos/modules/services/networking/zerotierone.nix b/nixos/modules/services/networking/zerotierone.nix
index e66648f683f4..86e0204ec2f7 100644
--- a/nixos/modules/services/networking/zerotierone.nix
+++ b/nixos/modules/services/networking/zerotierone.nix
@@ -7,11 +7,19 @@ let
 in
 {
   options.services.zerotierone.enable = mkEnableOption "ZeroTierOne";
-  
+  options.services.zerotierone.package = mkOption {
+    default = pkgs.zerotierone;
+    defaultText = "pkgs.zerotierone";
+    type = types.package;
+    description = ''
+      ZeroTier One package to use.
+    '';
+  };
+
   config = mkIf cfg.enable {
     systemd.services.zerotierone = {
       description = "ZeroTierOne";
-      path = [ pkgs.zerotierone ];
+      path = [ cfg.package ];
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
       preStart =
@@ -21,7 +29,7 @@ in
         chown -R root:root /var/lib/zerotier-one
         '';
       serviceConfig = {
-        ExecStart = "${pkgs.zerotierone}/bin/zerotier-one";
+        ExecStart = "${cfg.package}/bin/zerotier-one";
         Restart = "always";
         KillMode = "process";
       };
@@ -30,6 +38,6 @@ in
     # ZeroTier does not issue DHCP leases, but some strangers might...
     networking.dhcpcd.denyInterfaces = [ "zt0" ];
 
-    environment.systemPackages = [ pkgs.zerotierone ];
+    environment.systemPackages = [ cfg.package ];
   };
 }
diff --git a/nixos/modules/services/printing/cupsd.nix b/nixos/modules/services/printing/cupsd.nix
index 0bcb1a0c20c4..368d7ac761ac 100644
--- a/nixos/modules/services/printing/cupsd.nix
+++ b/nixos/modules/services/printing/cupsd.nix
@@ -4,7 +4,7 @@ with lib;
 
 let
 
-  inherit (pkgs) cups cups-pk-helper cups_filters gutenprint;
+  inherit (pkgs) cups cups-pk-helper cups-filters gutenprint;
 
   cfg = config.services.printing;
 
@@ -34,7 +34,7 @@ let
   bindir = pkgs.buildEnv {
     name = "cups-progs";
     paths =
-      [ cups.out additionalBackends cups_filters pkgs.ghostscript ]
+      [ cups.out additionalBackends cups-filters pkgs.ghostscript ]
       ++ optional cfg.gutenprint gutenprint
       ++ cfg.drivers;
     pathsToLink = [ "/lib/cups" "/share/cups" "/bin" ];
@@ -329,7 +329,7 @@ in
 
         path = [ cups ];
 
-        serviceConfig.ExecStart = "${cups_filters}/bin/cups-browsed";
+        serviceConfig.ExecStart = "${cups-filters}/bin/cups-browsed";
 
         restartTriggers = [ browsedFile ];
       };
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index af7753470de6..6e62606f323e 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -165,6 +165,8 @@ let
   mkLocations = locations: concatStringsSep "\n" (mapAttrsToList (location: config: ''
     location ${location} {
       ${optionalString (config.proxyPass != null) "proxy_pass ${config.proxyPass};"}
+      ${optionalString (config.index != null) "index ${config.index};"}
+      ${optionalString (config.tryFiles != null) "try_files ${config.tryFiles};"}
       ${optionalString (config.root != null) "root ${config.root};"}
       ${config.extraConfig}
     }
diff --git a/nixos/modules/services/web-servers/nginx/location-options.nix b/nixos/modules/services/web-servers/nginx/location-options.nix
index 8aaa3e96f800..e1885b160664 100644
--- a/nixos/modules/services/web-servers/nginx/location-options.nix
+++ b/nixos/modules/services/web-servers/nginx/location-options.nix
@@ -14,8 +14,25 @@ with lib;
       default = null;
       example = "http://www.example.org/";
       description = ''
-        Adds proxy_pass directive and sets default proxy headers Host, X-Real-Ip
-        and X-Forwarded-For.
+        Adds proxy_pass directive.
+      '';
+    };
+
+    index = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      example = "index.php index.html";
+      description = ''
+        Adds index directive.
+      '';
+    };
+
+    tryFiles = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      example = "$uri =404";
+      description = ''
+        Adds try_files directive.
       '';
     };
 
diff --git a/nixos/modules/services/x11/desktop-managers/enlightenment.nix b/nixos/modules/services/x11/desktop-managers/enlightenment.nix
index 2e788d869607..8a03dd65b335 100644
--- a/nixos/modules/services/x11/desktop-managers/enlightenment.nix
+++ b/nixos/modules/services/x11/desktop-managers/enlightenment.nix
@@ -29,7 +29,7 @@ in
   config = mkIf (xcfg.enable && cfg.enable) {
 
     environment.systemPackages = [
-      e.efl e.evas e.emotion e.elementary e.enlightenment
+      e.efl e.enlightenment
       e.terminology e.econnman
       pkgs.xorg.xauth # used by kdesu
       pkgs.gtk # To get GTK+'s themes.
diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix
index 1c928ff22a1f..75d80609f73f 100644
--- a/nixos/modules/services/x11/display-managers/default.nix
+++ b/nixos/modules/services/x11/display-managers/default.nix
@@ -306,7 +306,8 @@ in
   };
 
   imports = [
-   (mkRemovedOptionModule [ "services" "xserver" "displayManager" "desktopManagerHandlesLidAndPower" ])
+   (mkRemovedOptionModule [ "services" "xserver" "displayManager" "desktopManagerHandlesLidAndPower" ]
+     "The option is no longer necessary because all display managers have already delegated lid management to systemd.")
   ];
 
 }