summary refs log tree commit diff
path: root/nixos/modules
diff options
context:
space:
mode:
authorVladimír Čunát <vcunat@gmail.com>2017-01-26 16:49:41 +0100
committerVladimír Čunát <vcunat@gmail.com>2017-01-26 16:49:41 +0100
commit6973c7739ea1581595931e8c8b3b76241083b2df (patch)
treef56826492e0e260f24aeeedd2e47d36785ba3519 /nixos/modules
parent5dacc53af3f4537fab693952b5f13b6cafcde6d4 (diff)
parentbca9bcb3c3dd3b2e46f8e07db9a8326de01697c7 (diff)
downloadnixlib-6973c7739ea1581595931e8c8b3b76241083b2df.tar
nixlib-6973c7739ea1581595931e8c8b3b76241083b2df.tar.gz
nixlib-6973c7739ea1581595931e8c8b3b76241083b2df.tar.bz2
nixlib-6973c7739ea1581595931e8c8b3b76241083b2df.tar.lz
nixlib-6973c7739ea1581595931e8c8b3b76241083b2df.tar.xz
nixlib-6973c7739ea1581595931e8c8b3b76241083b2df.tar.zst
nixlib-6973c7739ea1581595931e8c8b3b76241083b2df.zip
Merge branch 'master' into staging
There were some larger rebuilds because of security.
Diffstat (limited to 'nixos/modules')
-rw-r--r--nixos/modules/i18n/input-method/ibus.nix2
-rw-r--r--nixos/modules/misc/ids.nix3
-rw-r--r--nixos/modules/misc/locate.nix94
-rw-r--r--nixos/modules/module-list.nix5
-rw-r--r--nixos/modules/profiles/installation-device.nix14
-rw-r--r--nixos/modules/programs/environment.nix3
-rw-r--r--nixos/modules/programs/man.nix1
-rw-r--r--nixos/modules/rename.nix5
-rw-r--r--nixos/modules/security/acme.nix2
-rw-r--r--nixos/modules/services/games/factorio.nix87
-rw-r--r--nixos/modules/services/logging/journalbeat.nix76
-rw-r--r--nixos/modules/services/logging/logstash.nix14
-rw-r--r--nixos/modules/services/misc/apache-kafka.nix2
-rw-r--r--nixos/modules/services/monitoring/vnstat.nix43
-rw-r--r--nixos/modules/services/network-filesystems/tahoe.nix2
-rw-r--r--nixos/modules/services/networking/dnscrypt-wrapper.nix187
-rw-r--r--nixos/modules/services/networking/firewall.nix20
-rw-r--r--nixos/modules/services/networking/flannel.nix2
-rw-r--r--nixos/modules/services/networking/kresd.nix119
-rw-r--r--nixos/modules/services/networking/networkmanager.nix5
-rw-r--r--nixos/modules/services/networking/pdns-recursor.nix168
-rw-r--r--nixos/modules/services/networking/smokeping.nix2
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix40
-rw-r--r--nixos/modules/services/web-servers/nginx/vhost-options.nix9
-rw-r--r--nixos/modules/services/x11/desktop-managers/kde5.nix5
25 files changed, 838 insertions, 72 deletions
diff --git a/nixos/modules/i18n/input-method/ibus.nix b/nixos/modules/i18n/input-method/ibus.nix
index 3eaf9e2ab370..a5bbe6bcb559 100644
--- a/nixos/modules/i18n/input-method/ibus.nix
+++ b/nixos/modules/i18n/input-method/ibus.nix
@@ -44,7 +44,7 @@ in
       panel = mkOption {
         type = with types; nullOr path;
         default = null;
-        example = literalExample "${pkgs.kde5.plasma-desktop}/lib/libexec/kimpanel-ibus-panel";
+        example = literalExample "''${pkgs.kde5.plasma-desktop}/lib/libexec/kimpanel-ibus-panel";
         description = "Replace the IBus panel with another panel.";
       };
     };
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index 5058d41bf753..2005f2518ba0 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -284,6 +284,8 @@
       glance = 266;
       couchpotato = 267;
       gogs = 268;
+      pdns-recursor = 269;
+      kresd = 270;
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
@@ -538,6 +540,7 @@
       glance = 266;
       couchpotato = 267;
       gogs = 268;
+      kresd = 270;
 
       # 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/misc/locate.nix b/nixos/modules/misc/locate.nix
index 3cb5bb1a351a..a9c84f6db243 100644
--- a/nixos/modules/misc/locate.nix
+++ b/nixos/modules/misc/locate.nix
@@ -4,10 +4,12 @@ with lib;
 
 let
   cfg = config.services.locate;
+  isMLocate = hasPrefix "mlocate" cfg.locate.name;
+  isFindutils = hasPrefix "findutils" cfg.locate.name;
 in {
-  options.services.locate = {
+  options.services.locate = with types; {
     enable = mkOption {
-      type = types.bool;
+      type = bool;
       default = false;
       description = ''
         If enabled, NixOS will periodically update the database of
@@ -16,8 +18,9 @@ in {
     };
 
     locate = mkOption {
-      type = types.package;
+      type = package;
       default = pkgs.findutils;
+      defaultText = "pkgs.findutils";
       example = "pkgs.mlocate";
       description = ''
         The locate implementation to use
@@ -25,7 +28,7 @@ in {
     };
 
     interval = mkOption {
-      type = types.str;
+      type = str;
       default = "02:15";
       example = "hourly";
       description = ''
@@ -38,11 +41,8 @@ in {
       '';
     };
 
-    # This is no longer supported, but we keep it to give a better warning below
-    period = mkOption { visible = false; };
-
     extraFlags = mkOption {
-      type = types.listOf types.str;
+      type = listOf str;
       default = [ ];
       description = ''
         Extra flags to pass to <command>updatedb</command>.
@@ -50,7 +50,7 @@ in {
     };
 
     output = mkOption {
-      type = types.path;
+      type = path;
       default = "/var/cache/locatedb";
       description = ''
         The database file to build.
@@ -58,7 +58,7 @@ in {
     };
 
     localuser = mkOption {
-      type = types.str;
+      type = nullOr str;
       default = "nobody";
       description = ''
         The user to search non-network directories as, using
@@ -66,31 +66,81 @@ in {
       '';
     };
 
-    includeStore = mkOption {
-      type = types.bool;
+    pruneFS = mkOption {
+      type = listOf str;
+      default = ["afs" "anon_inodefs" "auto" "autofs" "bdev" "binfmt" "binfmt_misc" "cgroup" "cifs" "coda" "configfs" "cramfs" "cpuset" "debugfs" "devfs" "devpts" "devtmpfs" "ecryptfs" "eventpollfs" "exofs" "futexfs" "ftpfs" "fuse" "fusectl" "gfs" "gfs2" "hostfs" "hugetlbfs" "inotifyfs" "iso9660" "jffs2" "lustre" "misc" "mqueue" "ncpfs" "nnpfs" "ocfs" "ocfs2" "pipefs" "proc" "ramfs" "rpc_pipefs" "securityfs" "selinuxfs" "sfs" "shfs" "smbfs" "sockfs" "spufs" "nfs" "NFS" "nfs4" "nfsd" "sshfs" "subfs" "supermount" "sysfs" "tmpfs" "ubifs" "udf" "usbfs" "vboxsf" "vperfctrfs" ];
+      description = ''
+        Which filesystem types to exclude from indexing
+      '';
+    };
+
+    prunePaths = mkOption {
+      type = listOf path;
+      default = ["/tmp" "/var/tmp" "/var/cache" "/var/lock" "/var/run" "/var/spool" "/nix/store"];
+      description = ''
+        Which paths to exclude from indexing
+      '';
+    };
+
+    pruneNames = mkOption {
+      type = listOf str;
+      default = [];
+      description = ''
+        Directory components which should exclude paths containing them from indexing
+      '';
+    };
+
+    pruneBindMounts = mkOption {
+      type = bool;
       default = false;
       description = ''
-        Whether to include <filename>/nix/store</filename> in the locate database.
+        Whether not to index bind mounts
       '';
     };
+    
   };
 
-  config = {
-    warnings =
-      let opt = options.services.locate.period; in
-      optional opt.isDefined "The ‘services.locate.period’ option in ${showFiles opt.files} has been removed; please replace it with ‘services.locate.interval’, using the systemd.time(7) calendar event format.";
+  config = mkIf cfg.enable {
+    users.extraGroups = mkIf isMLocate { mlocate = {}; };
+
+    security.setuidOwners = mkIf isMLocate
+      [ { group = "mlocate";
+          owner = "root";
+          permissions = "u+rx,g+x,o+x";
+          setgid = true;
+          setuid = false;
+          program = "locate";
+        }
+      ];
+
+    nixpkgs.config = { locate.dbfile = cfg.output; };
+
+    environment.systemPackages = [ cfg.locate ];
+
+    environment.variables = mkIf (!isMLocate)
+      { LOCATE_PATH = cfg.output;
+      };
 
+    warnings = optional (isMLocate && cfg.localuser != null) "mlocate does not support searching as user other than root"
+            ++ optional (isFindutils && cfg.pruneNames != []) "findutils locate does not support pruning by directory component"
+            ++ optional (isFindutils && cfg.pruneBindMounts) "findutils locate does not support skipping bind mounts";
+  
     systemd.services.update-locatedb =
       { description = "Update Locate Database";
-        path  = [ pkgs.su ];
+        path = mkIf (!isMLocate) [ pkgs.su ];
         script =
           ''
-            mkdir -m 0755 -p $(dirname ${toString cfg.output})
+            install -m ${if isMLocate then "0750" else "0755"} -o root -g ${if isMLocate then "mlocate" else "root"} -d $(dirname ${cfg.output})
             exec ${cfg.locate}/bin/updatedb \
-              --localuser=${cfg.localuser} \
-              ${optionalString (!cfg.includeStore) "--prunepaths='/nix/store'"} \
+              ${optionalString (cfg.localuser != null) ''--localuser=${cfg.localuser}''} \
               --output=${toString cfg.output} ${concatStringsSep " " cfg.extraFlags}
           '';
+        environment = {
+          PRUNEFS = concatStringsSep " " cfg.pruneFS;
+          PRUNEPATHS = concatStringsSep " " cfg.prunePaths;
+          PRUNENAMES = concatStringsSep " " cfg.pruneNames;
+          PRUNE_BIND_MOUNTS = if cfg.pruneBindMounts then "yes" else "no";
+        };
         serviceConfig.Nice = 19;
         serviceConfig.IOSchedulingClass = "idle";
         serviceConfig.PrivateTmp = "yes";
@@ -100,7 +150,7 @@ in {
         serviceConfig.ReadWriteDirectories = dirOf cfg.output;
       };
 
-    systemd.timers.update-locatedb = mkIf cfg.enable
+    systemd.timers.update-locatedb =
       { description = "Update timer for locate database";
         partOf      = [ "update-locatedb.service" ];
         wantedBy    = [ "timers.target" ];
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index e99e344b932d..9100f5b27a04 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -212,6 +212,7 @@
   ./services/logging/awstats.nix
   ./services/logging/fluentd.nix
   ./services/logging/graylog.nix
+  ./services/logging/journalbeat.nix
   ./services/logging/klogd.nix
   ./services/logging/logcheck.nix
   ./services/logging/logrotate.nix
@@ -332,6 +333,7 @@
   ./services/monitoring/telegraf.nix
   ./services/monitoring/ups.nix
   ./services/monitoring/uptime.nix
+  ./services/monitoring/vnstat.nix
   ./services/monitoring/zabbix-agent.nix
   ./services/monitoring/zabbix-server.nix
   ./services/network-filesystems/cachefilesd.nix
@@ -370,6 +372,7 @@
   ./services/networking/dhcpd.nix
   ./services/networking/dnschain.nix
   ./services/networking/dnscrypt-proxy.nix
+  ./services/networking/dnscrypt-wrapper.nix
   ./services/networking/dnsmasq.nix
   ./services/networking/ejabberd.nix
   ./services/networking/fan.nix
@@ -396,6 +399,7 @@
   ./services/networking/iodine.nix
   ./services/networking/ircd-hybrid/default.nix
   ./services/networking/kippo.nix
+  ./services/networking/kresd.nix
   ./services/networking/lambdabot.nix
   ./services/networking/libreswan.nix
   ./services/networking/logmein-hamachi.nix
@@ -426,6 +430,7 @@
   ./services/networking/pdnsd.nix
   ./services/networking/polipo.nix
   ./services/networking/powerdns.nix
+  ./services/networking/pdns-recursor.nix
   ./services/networking/pptpd.nix
   ./services/networking/prayer.nix
   ./services/networking/privoxy.nix
diff --git a/nixos/modules/profiles/installation-device.nix b/nixos/modules/profiles/installation-device.nix
index b2973d88b157..a24fa75e01db 100644
--- a/nixos/modules/profiles/installation-device.nix
+++ b/nixos/modules/profiles/installation-device.nix
@@ -45,8 +45,13 @@ with lib;
             "Type `systemctl start display-manager' to\nstart the graphical user interface."}
       '';
 
-    # Allow sshd to be started manually through "start sshd".
-    services.openssh.enable = true;
+    # Allow sshd to be started manually through "systemctl start sshd".
+    services.openssh = {
+      enable = true;
+      # Allow password login to the installation, if the user sets a password via "passwd"
+      # It is safe as root doesn't have a password by default and SSH is disabled by default
+      permitRootLogin = "yes";
+    };
     systemd.services.sshd.wantedBy = mkOverride 50 [];
 
     # Enable wpa_supplicant, but don't start it by default.
@@ -66,9 +71,8 @@ with lib;
     boot.kernel.sysctl."vm.overcommit_memory" = "1";
 
     # To speed up installation a little bit, include the complete
-    # stdenv in the Nix store on the CD.  Archive::Cpio is needed for
-    # the initrd builder.
-    system.extraDependencies = [ pkgs.stdenv pkgs.busybox pkgs.perlPackages.ArchiveCpio ];
+    # stdenv in the Nix store on the CD.
+    system.extraDependencies = with pkgs; [ stdenv stdenvNoCC busybox ];
 
     # Show all debug messages from the kernel but don't log refused packets
     # because we have the firewall enabled. This makes installs from the
diff --git a/nixos/modules/programs/environment.nix b/nixos/modules/programs/environment.nix
index a35b5cc9513e..a1615c920c02 100644
--- a/nixos/modules/programs/environment.nix
+++ b/nixos/modules/programs/environment.nix
@@ -17,8 +17,7 @@ in
   config = {
 
     environment.variables =
-      { LOCATE_PATH = "/var/cache/locatedb";
-        NIXPKGS_CONFIG = "/etc/nix/nixpkgs-config.nix";
+      { NIXPKGS_CONFIG = "/etc/nix/nixpkgs-config.nix";
         PAGER = mkDefault "less -R";
         EDITOR = mkDefault "nano";
       };
diff --git a/nixos/modules/programs/man.nix b/nixos/modules/programs/man.nix
index e59ffd6f936d..5b20a38d8856 100644
--- a/nixos/modules/programs/man.nix
+++ b/nixos/modules/programs/man.nix
@@ -11,6 +11,7 @@ with lib;
       default = true;
       description = ''
         Whether to enable manual pages and the <command>man</command> command.
+        This also includes "man" outputs of all <literal>systemPackages</literal>.
       '';
     };
 
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index ad1ba86980d5..4e7f62fc8f5c 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -18,6 +18,7 @@ with lib;
     (mkRenamedOptionModule [ "services" "elasticsearch" "host" ] [ "services" "elasticsearch" "listenAddress" ])
     (mkRenamedOptionModule [ "services" "graphite" "api" "host" ] [ "services" "graphite" "api" "listenAddress" ])
     (mkRenamedOptionModule [ "services" "graphite" "web" "host" ] [ "services" "graphite" "web" "listenAddress" ])
+    (mkRenamedOptionModule [ "services" "logstash" "address" ] [ "services" "logstash" "listenAddress" ])
     (mkRenamedOptionModule [ "services" "kibana" "host" ] [ "services" "kibana" "listenAddress" ])
     (mkRenamedOptionModule [ "services" "mpd" "network" "host" ] [ "services" "mpd" "network" "listenAddress" ])
     (mkRenamedOptionModule [ "services" "neo4j" "host" ] [ "services" "neo4j" "listenAddress" ])
@@ -167,6 +168,10 @@ with lib;
     # dhcpd
     (mkRenamedOptionModule [ "services" "dhcpd" ] [ "services" "dhcpd4" ])
 
+    # locate
+    (mkRenamedOptionModule [ "services" "locate" "period" ] [ "services" "locate" "interval" ])
+    (mkRemovedOptionModule [ "services" "locate" "includeStore" ] "Use services.locate.prunePaths" )
+
     # Options that are obsolete and have no replacement.
     (mkRemovedOptionModule [ "boot" "initrd" "luks" "enable" ] "")
     (mkRemovedOptionModule [ "programs" "bash" "enable" ] "")
diff --git a/nixos/modules/security/acme.nix b/nixos/modules/security/acme.nix
index 726e54711410..4e7c966a463a 100644
--- a/nixos/modules/security/acme.nix
+++ b/nixos/modules/security/acme.nix
@@ -284,6 +284,8 @@ in
             OnCalendar = cfg.renewInterval;
             Unit = "acme-${cert}.service";
             Persistent = "yes";
+            AccuracySec = "5m";
+            RandomizedDelaySec = "1h";
           };
         })
       );
diff --git a/nixos/modules/services/games/factorio.nix b/nixos/modules/services/games/factorio.nix
index 0369752997a7..e7f070d08773 100644
--- a/nixos/modules/services/games/factorio.nix
+++ b/nixos/modules/services/games/factorio.nix
@@ -14,6 +14,31 @@ let
     read-data=${factorio}/share/factorio/data
     write-data=${stateDir}
   '';
+  serverSettings = {
+    name = cfg.game-name;
+    description = cfg.description;
+    visibility = {
+      public = cfg.public;
+      lan = cfg.lan;
+    };
+    username = cfg.username;
+    password = cfg.password;
+    token = cfg.token;
+    game_password = cfg.game-password;
+    require_user_verification = true;
+    max_upload_in_kilobytes_per_second = 0;
+    minimum_latency_in_ticks = 0;
+    ignore_player_limit_for_returning_players = false;
+    allow_commands = "admins-only";
+    autosave_interval = cfg.autosave-interval;
+    autosave_slots = 5;
+    afk_autokick_interval = 0;
+    auto_pause = true;
+    only_admins_can_pause_the_game = true;
+    autosave_only_on_server = true;
+    admins = [];
+  };
+  serverSettingsFile = pkgs.writeText "server-settings.json" (builtins.toJSON (filterAttrsRecursive (n: v: v != null) serverSettings));
   modDir = pkgs.factorio-mkModDirDrv cfg.mods;
 in
 {
@@ -67,12 +92,68 @@ in
           derivations via nixos-channel. Until then, this is for experts only.
         '';
       };
+      game-name = mkOption {
+        type = types.nullOr types.string;
+        default = "Factorio Game";
+        description = ''
+          Name of the game as it will appear in the game listing.
+        '';
+      };
+      description = mkOption {
+        type = types.nullOr types.string;
+        default = "";
+        description = ''
+          Description of the game that will appear in the listing.
+        '';
+      };
+      public = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Game will be published on the official Factorio matching server.
+        '';
+      };
+      lan = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Game will be broadcast on LAN.
+        '';
+      };
+      username = mkOption {
+        type = types.nullOr types.string;
+        default = null;
+        description = ''
+          Your factorio.com login credentials. Required for games with visibility public.
+        '';
+      };
+      password = mkOption {
+        type = types.nullOr types.string;
+        default = null;
+        description = ''
+          Your factorio.com login credentials. Required for games with visibility public.
+        '';
+      };
+      token = mkOption {
+        type = types.nullOr types.string;
+        default = null;
+        description = ''
+          Authentication token. May be used instead of 'password' above.
+        '';
+      };
+      game-password = mkOption {
+        type = types.nullOr types.string;
+        default = null;
+        description = ''
+          Game password.
+        '';
+      };
       autosave-interval = mkOption {
         type = types.nullOr types.int;
         default = null;
-        example = 2;
+        example = 10;
         description = ''
-          The time, in minutes, between autosaves.
+          Autosave interval in minutes.
         '';
       };
     };
@@ -120,8 +201,8 @@ in
           "--config=${cfg.configFile}"
           "--port=${toString cfg.port}"
           "--start-server=${mkSavePath cfg.saveName}"
+          "--server-settings=${serverSettingsFile}"
           (optionalString (cfg.mods != []) "--mod-directory=${modDir}")
-          (optionalString (cfg.autosave-interval != null) "--autosave-interval ${toString cfg.autosave-interval}")
         ];
       };
     };
diff --git a/nixos/modules/services/logging/journalbeat.nix b/nixos/modules/services/logging/journalbeat.nix
new file mode 100644
index 000000000000..8186a3b02c37
--- /dev/null
+++ b/nixos/modules/services/logging/journalbeat.nix
@@ -0,0 +1,76 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.journalbeat;
+
+  journalbeatYml = pkgs.writeText "journalbeat.yml" ''
+    name: ${cfg.name}
+    tags: ${builtins.toJSON cfg.tags}
+
+    journalbeat.cursor_state_file: ${cfg.stateDir}/cursor-state
+
+    ${cfg.extraConfig}
+  '';
+
+in
+{
+  options = {
+
+    services.journalbeat = {
+
+      enable = mkEnableOption "journalbeat";
+
+      name = mkOption {
+        type = types.str;
+        default = "journalbeat";
+        description = "Name of the beat";
+      };
+
+      tags = mkOption {
+        type = types.listOf types.str;
+        default = [];
+        description = "Tags to place on the shipped log messages";
+      };
+
+      stateDir = mkOption {
+        type = types.str;
+        default = "/var/lib/journalbeat";
+        description = "The state directory. Journalbeat's own logs and other data are stored here.";
+      };
+
+      extraConfig = mkOption {
+        type = types.lines;
+        default = ''
+          journalbeat:
+            seek_position: cursor
+            cursor_seek_fallback: tail
+            write_cursor_state: true
+            cursor_flush_period: 5s
+            clean_field_names: true
+            convert_to_numbers: false
+            move_metadata_to_field: journal
+            default_type: journal
+        '';
+        description = "Any other configuration options you want to add";
+      };
+
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    systemd.services.journalbeat = with pkgs; {
+      description = "Journalbeat log shipper";
+      wantedBy = [ "multi-user.target" ];
+      preStart = ''
+        mkdir -p ${cfg.stateDir}/data
+        mkdir -p ${cfg.stateDir}/logs
+      '';
+      serviceConfig = {
+        ExecStart = "${pkgs.journalbeat}/bin/journalbeat -c ${journalbeatYml} -path.data ${cfg.stateDir}/data -path.logs ${cfg.stateDir}/logs";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/logging/logstash.nix b/nixos/modules/services/logging/logstash.nix
index 62f6e187ea07..c9477b9e3ab0 100644
--- a/nixos/modules/services/logging/logstash.nix
+++ b/nixos/modules/services/logging/logstash.nix
@@ -63,7 +63,7 @@ in
         description = "Enable the logstash web interface.";
       };
 
-      address = mkOption {
+      listenAddress = mkOption {
         type = types.str;
         default = "0.0.0.0";
         description = "Address on which to start webserver.";
@@ -77,7 +77,7 @@ in
 
       inputConfig = mkOption {
         type = types.lines;
-        default = ''stdin { type => "example" }'';
+        default = ''generator { }'';
         description = "Logstash input configuration.";
         example = ''
           # Read from journal
@@ -90,7 +90,7 @@ in
 
       filterConfig = mkOption {
         type = types.lines;
-        default = ''noop {}'';
+        default = "";
         description = "logstash filter configuration.";
         example = ''
           if [type] == "syslog" {
@@ -108,11 +108,11 @@ in
 
       outputConfig = mkOption {
         type = types.lines;
-        default = ''stdout { debug => true debug_format => "json"}'';
+        default = ''stdout { codec => rubydebug }'';
         description = "Logstash output configuration.";
         example = ''
-          redis { host => "localhost" data_type => "list" key => "logstash" codec => json }
-          elasticsearch { embedded => true }
+          redis { host => ["localhost"] data_type => "list" key => "logstash" codec => json }
+          elasticsearch { }
         '';
       };
 
@@ -147,7 +147,7 @@ in
               ${cfg.outputConfig}
             }
           ''} " +
-          ops cfg.enableWeb "-- web -a ${cfg.address} -p ${cfg.port}";
+          ops cfg.enableWeb "-- web -a ${cfg.listenAddress} -p ${cfg.port}";
       };
     };
   };
diff --git a/nixos/modules/services/misc/apache-kafka.nix b/nixos/modules/services/misc/apache-kafka.nix
index c856d3294c01..cff053396885 100644
--- a/nixos/modules/services/misc/apache-kafka.nix
+++ b/nixos/modules/services/misc/apache-kafka.nix
@@ -38,7 +38,7 @@ in {
 
     brokerId = mkOption {
       description = "Broker ID.";
-      default = 0;
+      default = -1;
       type = types.int;
     };
 
diff --git a/nixos/modules/services/monitoring/vnstat.nix b/nixos/modules/services/monitoring/vnstat.nix
new file mode 100644
index 000000000000..f6be7c7fd34a
--- /dev/null
+++ b/nixos/modules/services/monitoring/vnstat.nix
@@ -0,0 +1,43 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.vnstat;
+in {
+  options.services.vnstat = {
+    enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Whether to enable update of network usage statistics via vnstatd.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    users.extraUsers.vnstatd = {
+      isSystemUser = true;
+      description = "vnstat daemon user";
+      home = "/var/lib/vnstat";
+      createHome = true;
+    };
+
+    systemd.services.vnstat = {
+      description = "vnStat network traffic monitor";
+      path = [ pkgs.coreutils ];
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      unitConfig.documentation = "man:vnstatd(1) man:vnstat(1) man:vnstat.conf(5)";
+      preStart = "chmod 755 /var/lib/vnstat";
+      serviceConfig = {
+        ExecStart = "${pkgs.vnstat}/bin/vnstatd -n";
+        ExecReload = "kill -HUP $MAINPID";
+        ProtectHome = true;
+        PrivateDevices = true;
+        PrivateTmp = true;
+        User = "vnstatd";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/network-filesystems/tahoe.nix b/nixos/modules/services/network-filesystems/tahoe.nix
index ab9eac3829fb..f63f641d00be 100644
--- a/nixos/modules/services/network-filesystems/tahoe.nix
+++ b/nixos/modules/services/network-filesystems/tahoe.nix
@@ -343,7 +343,7 @@ in
             preStart = ''
               if [ \! -d ${nodedir} ]; then
                 mkdir -p /var/db/tahoe-lafs
-                tahoe create-node ${nodedir}
+                tahoe create-node --hostname=localhost ${nodedir}
               fi
 
               # Tahoe has created a predefined tahoe.cfg which we must now
diff --git a/nixos/modules/services/networking/dnscrypt-wrapper.nix b/nixos/modules/services/networking/dnscrypt-wrapper.nix
new file mode 100644
index 000000000000..85fac660d52e
--- /dev/null
+++ b/nixos/modules/services/networking/dnscrypt-wrapper.nix
@@ -0,0 +1,187 @@
+{ config, lib, pkgs, ... }:
+with lib;
+
+let
+  cfg     = config.services.dnscrypt-wrapper;
+  dataDir = "/var/lib/dnscrypt-wrapper";
+
+  daemonArgs = with cfg; [
+    "--listen-address=${address}:${toString port}"
+    "--resolver-address=${upstream.address}:${toString upstream.port}"
+    "--provider-name=${providerName}"
+    "--provider-publickey-file=public.key"
+    "--provider-secretkey-file=secret.key"
+    "--provider-cert-file=${providerName}.crt"
+    "--crypt-secretkey-file=${providerName}.key"
+  ];
+
+  genKeys = ''
+    # generates time-limited keypairs
+    keyGen() {
+      dnscrypt-wrapper --gen-crypt-keypair \
+        --crypt-secretkey-file=${cfg.providerName}.key
+
+      dnscrypt-wrapper --gen-cert-file \
+        --crypt-secretkey-file=${cfg.providerName}.key \
+        --provider-cert-file=${cfg.providerName}.crt \
+        --provider-publickey-file=public.key \
+        --provider-secretkey-file=secret.key \
+        --cert-file-expire-days=${toString cfg.keys.expiration}
+    }
+
+    cd ${dataDir}
+
+    # generate provider keypair (first run only)
+    if [ ! -f public.key ] || [ ! -f secret.key ]; then
+      dnscrypt-wrapper --gen-provider-keypair
+    fi
+
+    # generate new keys for rotation
+    if [ ! -f ${cfg.providerName}.key ] || [ ! -f ${cfg.providerName}.crt ]; then
+      keyGen
+    fi
+  '';
+
+  rotateKeys = ''
+    # check if keys are not expired
+    keyValid() {
+      fingerprint=$(dnscrypt-wrapper --show-provider-publickey-fingerprint | awk '{print $(NF)}')
+      dnscrypt-proxy --test=${toString (cfg.keys.checkInterval + 1)} \
+        --resolver-address=127.0.0.1:${toString cfg.port} \
+        --provider-name=${cfg.providerName} \
+        --provider-key=$fingerprint
+    }
+
+    cd ${dataDir}
+
+    # archive old keys and restart the service
+    if ! keyValid; then
+      mkdir -p oldkeys
+      mv ${cfg.providerName}.key oldkeys/${cfg.providerName}-$(date +%F-%T).key
+      mv ${cfg.providerName}.crt oldkeys/${cfg.providerName}-$(date +%F-%T).crt
+      systemctl restart dnscrypt-wrapper
+    fi
+  '';
+
+in {
+
+
+  ###### interface
+
+  options.services.dnscrypt-wrapper = {
+    enable = mkEnableOption "DNSCrypt wrapper";
+
+    address = mkOption {
+      type = types.str;
+      default = "127.0.0.1";
+      description = ''
+        The DNSCrypt wrapper will bind to this IP address.
+      '';
+    };
+
+    port = mkOption {
+      type = types.int;
+      default = 5353;
+      description = ''
+        The DNSCrypt wrapper will listen for DNS queries on this port.
+      '';
+    };
+
+    providerName = mkOption {
+      type = types.str;
+      default = "2.dnscrypt-cert.${config.networking.hostName}";
+      example = "2.dnscrypt-cert.myresolver";
+      description = ''
+        The name that will be given to this DNSCrypt resolver.
+        Note: the resolver name must start with <literal>2.dnscrypt-cert.</literal>.
+      '';
+    };
+
+    upstream.address = mkOption {
+      type = types.str;
+      default = "127.0.0.1";
+      description = ''
+        The IP address of the upstream DNS server DNSCrypt will "wrap".
+      '';
+    };
+
+    upstream.port = mkOption {
+      type = types.int;
+      default = 53;
+      description = ''
+        The port of the upstream DNS server DNSCrypt will "wrap".
+      '';
+    };
+
+    keys.expiration = mkOption {
+      type = types.int;
+      default = 30;
+      description = ''
+        The duration (in days) of the time-limited secret key.
+        This will be automatically rotated before expiration.
+      '';
+    };
+
+    keys.checkInterval = mkOption {
+      type = types.int;
+      default = 1440;
+      description = ''
+        The time interval (in minutes) between key expiration checks.
+      '';
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    users.users.dnscrypt-wrapper = {
+      description = "dnscrypt-wrapper daemon user";
+      home = "${dataDir}";
+      createHome = true;
+    };
+    users.groups.dnscrypt-wrapper = { };
+
+
+    systemd.services.dnscrypt-wrapper = {
+      description = "dnscrypt-wrapper daemon";
+      after    = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      path     = [ pkgs.dnscrypt-wrapper ];
+
+      serviceConfig = {
+        User = "dnscrypt-wrapper";
+        WorkingDirectory = dataDir;
+        Restart   = "on-failure";
+        ExecStart = "${pkgs.dnscrypt-wrapper}/bin/dnscrypt-wrapper ${toString daemonArgs}";
+      };
+
+      preStart = genKeys;
+    };
+
+
+    systemd.services.dnscrypt-wrapper-rotate = {
+      after    = [ "network.target" ];
+      requires = [ "dnscrypt-wrapper.service" ];
+      description = "Rotates DNSCrypt wrapper keys if soon to expire";
+
+      path   = with pkgs; [ dnscrypt-wrapper dnscrypt-proxy gawk ];
+      script = rotateKeys;
+    };
+
+
+    systemd.timers.dnscrypt-wrapper-rotate = {
+      description = "Periodically check DNSCrypt wrapper keys for expiration";
+      wantedBy = [ "multi-user.target" ];
+
+      timerConfig = {
+        Unit = "dnscrypt-wrapper-rotate.service";
+        OnBootSec = "1min";
+        OnUnitActiveSec = cfg.keys.checkInterval * 60;
+      };
+    };
+
+  };
+}
diff --git a/nixos/modules/services/networking/firewall.nix b/nixos/modules/services/networking/firewall.nix
index c251b52e03fd..34b731ad35c9 100644
--- a/nixos/modules/services/networking/firewall.nix
+++ b/nixos/modules/services/networking/firewall.nix
@@ -41,7 +41,6 @@ let
   kernelPackages = config.boot.kernelPackages;
 
   kernelHasRPFilter = kernelPackages.kernel.features.netfilterRPFilter or false;
-  kernelCanDisableHelpers = kernelPackages.kernel.features.canDisableNetfilterConntrackHelpers or false;
 
   helpers =
     ''
@@ -426,7 +425,7 @@ in
 
     networking.firewall.connectionTrackingModules = mkOption {
       type = types.listOf types.str;
-      default = [ "ftp" ];
+      default = [ ];
       example = [ "ftp" "irc" "sane" "sip" "tftp" "amanda" "h323" "netbios_sn" "pptp" "snmp" ];
       description =
         ''
@@ -435,9 +434,11 @@ in
 
           As helpers can pose as a security risk, it is advised to
           set this to an empty list and disable the setting
-          networking.firewall.autoLoadConntrackHelpers
+          networking.firewall.autoLoadConntrackHelpers unless you
+          know what you are doing. Connection tracking is disabled
+          by default.
 
-          Loading of helpers is recommended to be done through the new
+          Loading of helpers is recommended to be done through the
           CT target.  More info:
           https://home.regit.org/netfilter-en/secure-use-of-helpers/
         '';
@@ -445,7 +446,7 @@ in
 
     networking.firewall.autoLoadConntrackHelpers = mkOption {
       type = types.bool;
-      default = true;
+      default = false;
       description =
         ''
           Whether to auto-load connection-tracking helpers.
@@ -505,15 +506,14 @@ in
 
     environment.systemPackages = [ pkgs.iptables ] ++ cfg.extraPackages;
 
-    boot.kernelModules = map (x: "nf_conntrack_${x}") cfg.connectionTrackingModules;
-    boot.extraModprobeConfig = optionalString (!cfg.autoLoadConntrackHelpers) ''
-      options nf_conntrack nf_conntrack_helper=0
+    boot.kernelModules = (optional cfg.autoLoadConntrackHelpers "nf_conntrack")
+      ++ map (x: "nf_conntrack_${x}") cfg.connectionTrackingModules;
+    boot.extraModprobeConfig = optionalString cfg.autoLoadConntrackHelpers ''
+      options nf_conntrack nf_conntrack_helper=1
     '';
 
     assertions = [ { assertion = (cfg.checkReversePath != false) || kernelHasRPFilter;
                      message = "This kernel does not support rpfilter"; }
-                   { assertion = cfg.autoLoadConntrackHelpers || kernelCanDisableHelpers;
-                     message = "This kernel does not support disabling conntrack helpers"; }
                  ];
 
     systemd.services.firewall = {
diff --git a/nixos/modules/services/networking/flannel.nix b/nixos/modules/services/networking/flannel.nix
index ca47a18bc1f6..b93e28e34efd 100644
--- a/nixos/modules/services/networking/flannel.nix
+++ b/nixos/modules/services/networking/flannel.nix
@@ -149,6 +149,6 @@ in {
       serviceConfig.ExecStart = "${cfg.package}/bin/flannel";
     };
 
-    services.etcd.enable = mkDefault cfg.etcd.endpoints == ["http://127.0.0.1:2379"];
+    services.etcd.enable = mkDefault (cfg.etcd.endpoints == ["http://127.0.0.1:2379"]);
   };
 }
diff --git a/nixos/modules/services/networking/kresd.nix b/nixos/modules/services/networking/kresd.nix
new file mode 100644
index 000000000000..18e2ab9aebf1
--- /dev/null
+++ b/nixos/modules/services/networking/kresd.nix
@@ -0,0 +1,119 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.kresd;
+  package = pkgs.knot-resolver;
+
+  configFile = pkgs.writeText "kresd.conf" cfg.extraConfig;
+in
+
+{
+  meta.maintainers = [ maintainers.vcunat /* upstream developer */ ];
+
+  ###### interface
+  options.services.kresd = {
+    enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Whether to enable knot-resolver domain name server.
+        DNSSEC validation is turned on by default.
+        You can run <literal>sudo nc -U /run/kresd/control</literal>
+        and give commands interactively to kresd.
+      '';
+    };
+    extraConfig = mkOption {
+      type = types.lines;
+      default = "";
+      description = ''
+        Extra lines to be added verbatim to the generated configuration file.
+      '';
+    };
+    cacheDir = mkOption {
+      type = types.path;
+      default = "/var/cache/kresd";
+      description = ''
+        Directory for caches.  They are intended to survive reboots.
+      '';
+    };
+    interfaces = mkOption {
+      type = with types; listOf str;
+      default = [ "::1" "127.0.0.1" ];
+      description = ''
+        What addresses the server should listen on.
+      '';
+    };
+    # TODO: perhaps options for more common stuff like cache size or forwarding
+  };
+
+  ###### implementation
+  config = mkIf cfg.enable {
+    environment.etc."kresd.conf".source = configFile; # not required
+
+    users.extraUsers = singleton
+      { name = "kresd";
+        uid = config.ids.uids.kresd;
+        group = "kresd";
+        description = "Knot-resolver daemon user";
+      };
+    users.extraGroups = singleton
+      { name = "kresd";
+        gid = config.ids.gids.kresd;
+      };
+
+    systemd.sockets.kresd = rec {
+      wantedBy = [ "sockets.target" ];
+      before = wantedBy;
+      listenStreams = map
+        # Syntax depends on being IPv6 or IPv4.
+        (iface: if elem ":" (stringToCharacters iface) then "[${iface}]:53" else "${iface}:53")
+        cfg.interfaces;
+      socketConfig.ListenDatagram = listenStreams;
+    };
+
+    systemd.sockets.kresd-control = rec {
+      wantedBy = [ "sockets.target" ];
+      before = wantedBy;
+      partOf = [ "kresd.socket" ];
+      listenStreams = [ "/run/kresd/control" ];
+      socketConfig = {
+        FileDescriptorName = "control";
+        Service = "kresd.service";
+        SocketMode = "0660"; # only root user/group may connect
+      };
+    };
+
+    # Create the cacheDir; tmpfiles don't work on nixos-rebuild switch.
+    systemd.services.kresd-cachedir = {
+      serviceConfig.Type = "oneshot";
+      script = ''
+        if [ ! -d '${cfg.cacheDir}' ]; then
+          mkdir -p '${cfg.cacheDir}'
+          chown kresd:kresd '${cfg.cacheDir}'
+        fi
+      '';
+    };
+
+    systemd.services.kresd = {
+      description = "Knot-resolver daemon";
+
+      serviceConfig = {
+        User = "kresd";
+        Type = "notify";
+        WorkingDirectory = cfg.cacheDir;
+      };
+
+      script = ''
+        exec '${package}/bin/kresd' --config '${configFile}' \
+          -k '${cfg.cacheDir}/root.key'
+      '';
+
+      after = [ "kresd-cachedir.service" ];
+      requires = [ "kresd.socket" "kresd-cachedir.service" ];
+      wantedBy = [ "sockets.target" ];
+    };
+  };
+}
diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix
index 8f353979d3fc..c11d4434c206 100644
--- a/nixos/modules/services/networking/networkmanager.nix
+++ b/nixos/modules/services/networking/networkmanager.nix
@@ -174,7 +174,7 @@ in {
 
     assertions = [{
       assertion = config.networking.wireless.enable == false;
-      message = "You can not use networking.networkmanager with services.networking.wireless";
+      message = "You can not use networking.networkmanager with networking.wireless";
     }];
 
     boot.kernelModules = [ "ppp_mppe" ]; # Needed for most (all?) PPTP VPN connections.
@@ -239,7 +239,8 @@ in {
     # Turn off NixOS' network management
     networking = {
       useDHCP = false;
-      wireless.enable = false;
+      # use mkDefault to trigger the assertion about the conflict above
+      wireless.enable = lib.mkDefault false;
     };
 
     powerManagement.resumeCommands = ''
diff --git a/nixos/modules/services/networking/pdns-recursor.nix b/nixos/modules/services/networking/pdns-recursor.nix
new file mode 100644
index 000000000000..26be72d2a61e
--- /dev/null
+++ b/nixos/modules/services/networking/pdns-recursor.nix
@@ -0,0 +1,168 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  dataDir  = "/var/lib/pdns-recursor";
+  username = "pdns-recursor";
+
+  cfg   = config.services.pdns-recursor;
+  zones = mapAttrsToList (zone: uri: "${zone}.=${uri}") cfg.forwardZones;
+
+  configFile = pkgs.writeText "recursor.conf" ''
+    local-address=${cfg.dns.address}
+    local-port=${toString cfg.dns.port}
+    allow-from=${concatStringsSep "," cfg.dns.allowFrom}
+
+    webserver-address=${cfg.api.address}
+    webserver-port=${toString cfg.api.port}
+    webserver-allow-from=${concatStringsSep "," cfg.api.allowFrom}
+
+    forward-zones=${concatStringsSep "," zones}
+    export-etc-hosts=${if cfg.exportHosts then "yes" else "no"}
+    dnssec=${cfg.dnssecValidation}
+    serve-rfc1918=${if cfg.serveRFC1918 then "yes" else "no"}
+
+    ${cfg.extraConfig}
+  '';
+
+in {
+  options.services.pdns-recursor = {
+    enable = mkEnableOption "PowerDNS Recursor, a recursive DNS server";
+
+    dns.address = mkOption {
+      type = types.str;
+      default = "0.0.0.0";
+      description = ''
+        IP address Recursor DNS server will bind to.
+      '';
+    };
+
+    dns.port = mkOption {
+      type = types.int;
+      default = 53;
+      description = ''
+        Port number Recursor DNS server will bind to.
+      '';
+    };
+
+    dns.allowFrom = mkOption {
+      type = types.listOf types.str;
+      default = [ "10.0.0.0/8" "172.16.0.0/12" "192.168.0.0/16" ];
+      example = [ "0.0.0.0/0" ];
+      description = ''
+        IP address ranges of clients allowed to make DNS queries.
+      '';
+    };
+
+    api.address = mkOption {
+      type = types.str;
+      default = "0.0.0.0";
+      description = ''
+        IP address Recursor REST API server will bind to.
+      '';
+    };
+
+    api.port = mkOption {
+      type = types.int;
+      default = 8082;
+      description = ''
+        Port number Recursor REST API server will bind to.
+      '';
+    };
+
+    api.allowFrom = mkOption {
+      type = types.listOf types.str;
+      default = [ "0.0.0.0/0" ];
+      description = ''
+        IP address ranges of clients allowed to make API requests.
+      '';
+    };
+
+    exportHosts = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+       Whether to export names and IP addresses defined in /etc/hosts.
+      '';
+    };
+
+    forwardZones = mkOption {
+      type = types.attrs;
+      example = { eth = "127.0.0.1:5353"; };
+      default = {};
+      description = ''
+        DNS zones to be forwarded to other servers.
+      '';
+    };
+
+    dnssecValidation = mkOption {
+      type = types.enum ["off" "process-no-validate" "process" "log-fail" "validate"];
+      default = "validate";
+      description = ''
+        Controls the level of DNSSEC processing done by the PowerDNS Recursor.
+        See https://doc.powerdns.com/md/recursor/dnssec/ for a detailed explanation.
+      '';
+    };
+
+    serveRFC1918 = mkOption {
+      type = types.bool;
+      default = true;
+      description = ''
+        Whether to directly resolve the RFC1918 reverse-mapping domains:
+        <literal>10.in-addr.arpa</literal>,
+        <literal>168.192.in-addr.arpa</literal>,
+        <literal>16-31.172.in-addr.arpa</literal>
+        This saves load on the AS112 servers.
+      '';
+    };
+
+    extraConfig = mkOption {
+      type = types.lines;
+      default = "";
+      description = ''
+        Extra options to be appended to the configuration file.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    users.extraUsers."${username}" = {
+      home = dataDir;
+      createHome = true;
+      uid = config.ids.uids.pdns-recursor;
+      description = "PowerDNS Recursor daemon user";
+    };
+
+    systemd.services.pdns-recursor = {
+      unitConfig.Documentation = "man:pdns_recursor(1) man:rec_control(1)";
+      description = "PowerDNS recursive server";
+      wantedBy = [ "multi-user.target" ];
+      after    = [ "network.target" ];
+
+      serviceConfig = {
+        User = username;
+        Restart    ="on-failure";
+        RestartSec = "5";
+        PrivateTmp = true;
+        PrivateDevices = true;
+        AmbientCapabilities = "cap_net_bind_service";
+        ExecStart = ''${pkgs.pdns-recursor}/bin/pdns_recursor \
+          --config-dir=${dataDir} \
+          --socket-dir=${dataDir} \
+          --disable-syslog
+        '';
+      };
+
+      preStart = ''
+        # Link configuration file into recursor home directory
+        configPath=${dataDir}/recursor.conf
+        if [ "$(realpath $configPath)" != "${configFile}" ]; then
+          rm -f $configPath
+          ln -s ${configFile} $configPath
+        fi
+      '';
+    };
+  };
+}
diff --git a/nixos/modules/services/networking/smokeping.nix b/nixos/modules/services/networking/smokeping.nix
index 04312c39062f..6648ada0c0de 100644
--- a/nixos/modules/services/networking/smokeping.nix
+++ b/nixos/modules/services/networking/smokeping.nix
@@ -273,7 +273,7 @@ in
         message = "services.smokeping: sendmail and Mailhost cannot both be enabled.";
       }
     ];
-    security.setuidPrograms = [ "fping" ];
+    security.setuidPrograms = [ "fping" "fping6" ];
     environment.systemPackages = [ pkgs.fping ];
     users.extraUsers = singleton {
       name = cfg.user;
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index 68a672c42c90..c9eacdd85dcd 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -5,7 +5,11 @@ with lib;
 let
   cfg = config.services.nginx;
   virtualHosts = mapAttrs (vhostName: vhostConfig:
-    vhostConfig // (optionalAttrs vhostConfig.enableACME {
+    vhostConfig // {
+      serverName = if vhostConfig.serverName != null
+        then vhostConfig.serverName
+        else vhostName;
+    } // (optionalAttrs vhostConfig.enableACME {
       sslCertificate = "/var/lib/acme/${vhostName}/fullchain.pem";
       sslCertificateKey = "/var/lib/acme/${vhostName}/key.pem";
     })
@@ -112,8 +116,9 @@ let
     ${cfg.appendConfig}
   '';
 
-  vhosts = concatStringsSep "\n" (mapAttrsToList (serverName: vhost:
+  vhosts = concatStringsSep "\n" (mapAttrsToList (vhostName: vhost:
       let
+        serverName = vhost.serverName;
         ssl = vhost.enableSSL || vhost.forceSSL;
         port = if vhost.port != null then vhost.port else (if ssl then 443 else 80);
         listenString = toString port + optionalString ssl " ssl http2"
@@ -161,7 +166,7 @@ let
             ssl_certificate_key ${vhost.sslCertificateKey};
           ''}
 
-          ${optionalString (vhost.basicAuth != {}) (mkBasicAuth serverName vhost.basicAuth)}
+          ${optionalString (vhost.basicAuth != {}) (mkBasicAuth vhostName vhost.basicAuth)}
 
           ${mkLocations vhost.locations}
 
@@ -178,8 +183,8 @@ let
       ${config.extraConfig}
     }
   '') locations);
-  mkBasicAuth = serverName: authDef: let
-    htpasswdFile = pkgs.writeText "${serverName}.htpasswd" (
+  mkBasicAuth = vhostName: authDef: let
+    htpasswdFile = pkgs.writeText "${vhostName}.htpasswd" (
       concatStringsSep "\n" (mapAttrsToList (user: password: ''
         ${user}:{PLAIN}${password}
       '') authDef)
@@ -393,17 +398,20 @@ in
     };
 
     security.acme.certs = filterAttrs (n: v: v != {}) (
-      mapAttrs (vhostName: vhostConfig:
-        optionalAttrs vhostConfig.enableACME {
-          user = cfg.user;
-          group = cfg.group;
-          webroot = vhostConfig.acmeRoot;
-          extraDomains = genAttrs vhostConfig.serverAliases (alias: null);
-          postRun = ''
-            systemctl reload nginx
-          '';
-        }
-      ) virtualHosts
+      let
+        vhostsConfigs = mapAttrsToList (vhostName: vhostConfig: vhostConfig) virtualHosts;
+        acmeEnabledVhosts = filter (vhostConfig: vhostConfig.enableACME) vhostsConfigs;
+        acmePairs = map (vhostConfig: { name = vhostConfig.serverName; value = {
+            user = cfg.user;
+            group = cfg.group;
+            webroot = vhostConfig.acmeRoot;
+            extraDomains = genAttrs vhostConfig.serverAliases (alias: null);
+            postRun = ''
+              systemctl reload nginx
+            '';
+          }; }) acmeEnabledVhosts;
+      in
+        listToAttrs acmePairs
     );
 
     users.extraUsers = optionalAttrs (cfg.user == "nginx") (singleton
diff --git a/nixos/modules/services/web-servers/nginx/vhost-options.nix b/nixos/modules/services/web-servers/nginx/vhost-options.nix
index dcebbc9229fc..c0ea645b3dfe 100644
--- a/nixos/modules/services/web-servers/nginx/vhost-options.nix
+++ b/nixos/modules/services/web-servers/nginx/vhost-options.nix
@@ -8,6 +8,15 @@
 with lib;
 {
   options = {
+    serverName = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        Name of this virtual host. Defaults to attribute name in virtualHosts.
+      '';
+      example = "example.org";
+    };
+
     serverAliases = mkOption {
       type = types.listOf types.str;
       default = [];
diff --git a/nixos/modules/services/x11/desktop-managers/kde5.nix b/nixos/modules/services/x11/desktop-managers/kde5.nix
index ee4ec0fc819f..8f081a1e9d2a 100644
--- a/nixos/modules/services/x11/desktop-managers/kde5.nix
+++ b/nixos/modules/services/x11/desktop-managers/kde5.nix
@@ -249,6 +249,11 @@ in
 
       security.pam.services.kde = { allowNullPassword = true; };
 
+      # use kimpanel as the default IBus panel
+      i18n.inputMethod.ibus.panel =
+        lib.mkDefault
+        "${pkgs.kde5.plasma-desktop}/lib/libexec/kimpanel-ibus-panel";
+
     })
   ];