about summary refs log tree commit diff
path: root/nixos/modules
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules')
-rw-r--r--nixos/modules/config/power-management.nix3
-rw-r--r--nixos/modules/config/shells-environment.nix2
-rw-r--r--nixos/modules/installer/cd-dvd/sd-image-aarch64.nix10
-rw-r--r--nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix1
-rw-r--r--nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix1
-rw-r--r--nixos/modules/misc/ids.nix4
-rw-r--r--nixos/modules/misc/nixpkgs.nix7
-rw-r--r--nixos/modules/module-list.nix7
-rw-r--r--nixos/modules/profiles/clone-config.nix2
-rw-r--r--nixos/modules/programs/less.nix118
-rw-r--r--nixos/modules/programs/zsh/oh-my-zsh.nix16
-rw-r--r--nixos/modules/programs/zsh/zsh.nix5
-rw-r--r--nixos/modules/security/sudo.nix129
-rw-r--r--nixos/modules/services/desktops/gnome3/chrome-gnome-shell.nix27
-rw-r--r--nixos/modules/services/hardware/amd-hybrid-graphics.nix46
-rw-r--r--nixos/modules/services/mail/postfix.nix139
-rw-r--r--nixos/modules/services/misc/home-assistant.nix116
-rw-r--r--nixos/modules/services/misc/matrix-synapse.nix63
-rw-r--r--nixos/modules/services/misc/nix-daemon.nix58
-rw-r--r--nixos/modules/services/monitoring/netdata.nix54
-rw-r--r--nixos/modules/services/network-filesystems/samba.nix13
-rw-r--r--nixos/modules/services/networking/aria2.nix10
-rw-r--r--nixos/modules/services/networking/kresd.nix6
-rw-r--r--nixos/modules/services/networking/openvpn.nix28
-rw-r--r--nixos/modules/services/networking/resilio.nix2
-rw-r--r--nixos/modules/services/networking/ssh/sshd.nix12
-rw-r--r--nixos/modules/services/networking/stunnel.nix221
-rw-r--r--nixos/modules/services/web-servers/mighttpd2.nix132
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix19
-rw-r--r--nixos/modules/services/web-servers/nginx/vhost-options.nix16
-rw-r--r--nixos/modules/services/x11/desktop-managers/plasma5.nix12
-rw-r--r--nixos/modules/services/x11/desktop-managers/xfce.nix145
-rw-r--r--nixos/modules/services/x11/window-managers/2bwm.nix4
-rw-r--r--nixos/modules/system/boot/initrd-network.nix4
-rw-r--r--nixos/modules/system/boot/kernel.nix8
-rw-r--r--nixos/modules/tasks/network-interfaces-scripted.nix4
-rw-r--r--nixos/modules/tasks/network-interfaces-systemd.nix24
-rw-r--r--nixos/modules/tasks/network-interfaces.nix10
-rw-r--r--nixos/modules/testing/test-instrumentation.nix19
-rw-r--r--nixos/modules/virtualisation/container-config.nix2
-rw-r--r--nixos/modules/virtualisation/google-compute-image.nix2
-rw-r--r--nixos/modules/virtualisation/libvirtd.nix1
-rw-r--r--nixos/modules/virtualisation/qemu-vm.nix16
-rw-r--r--nixos/modules/virtualisation/virtualbox-image.nix2
44 files changed, 1200 insertions, 320 deletions
diff --git a/nixos/modules/config/power-management.nix b/nixos/modules/config/power-management.nix
index a4a4d6e1a6af..4c37e8a6208c 100644
--- a/nixos/modules/config/power-management.nix
+++ b/nixos/modules/config/power-management.nix
@@ -69,9 +69,6 @@ in
 
   config = mkIf cfg.enable {
 
-    # Leftover for old setups, should be set by nixos-generate-config now
-    powerManagement.cpuFreqGovernor = mkDefault "ondemand";
-
     systemd.targets.post-resume = {
       description = "Post-Resume Actions";
       requires = [ "post-resume.service" ];
diff --git a/nixos/modules/config/shells-environment.nix b/nixos/modules/config/shells-environment.nix
index 65f2e5d7af99..398660967c52 100644
--- a/nixos/modules/config/shells-environment.nix
+++ b/nixos/modules/config/shells-environment.nix
@@ -36,7 +36,7 @@ in
       default = {};
       description = ''
         A set of environment variables used in the global environment.
-        These variables will be set on shell initialisation.
+        These variables will be set on shell initialisation (e.g. in /etc/profile).
         The value of each variable can be either a string or a list of
         strings.  The latter is concatenated, interspersed with colon
         characters.
diff --git a/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix b/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix
index efb9ba39bcd4..3306846b7fa7 100644
--- a/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix
+++ b/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix
@@ -27,6 +27,7 @@ in
   boot.loader.grub.enable = false;
   boot.loader.generic-extlinux-compatible.enable = true;
 
+  boot.consoleLogLevel = lib.mkDefault 7;
   boot.kernelPackages = pkgs.linuxPackages_latest;
 
   # The serial ports listed here are:
@@ -42,8 +43,17 @@ in
     populateBootCommands = let
       configTxt = pkgs.writeText "config.txt" ''
         kernel=u-boot-rpi3.bin
+
+        # Boot in 64-bit mode.
         arm_control=0x200
+
+        # U-Boot used to need this to work, regardless of whether UART is actually used or not.
+        # TODO: check when/if this can be removed.
         enable_uart=1
+
+        # Prevent the firmware from smashing the framebuffer setup done by the mainline kernel
+        # when attempting to show low-voltage or overtemperature warnings.
+        avoid_warnings=1
       '';
       in ''
         (cd ${pkgs.raspberrypifw}/share/raspberrypi/boot && cp bootcode.bin fixup*.dat start*.elf $NIX_BUILD_TOP/boot/)
diff --git a/nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix b/nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix
index 880a6bf2e1e8..f23275bc16d5 100644
--- a/nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix
+++ b/nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix
@@ -27,6 +27,7 @@ in
   boot.loader.grub.enable = false;
   boot.loader.generic-extlinux-compatible.enable = true;
 
+  boot.consoleLogLevel = lib.mkDefault 7;
   boot.kernelPackages = pkgs.linuxPackages_latest;
   # The serial ports listed here are:
   # - ttyS0: for Tegra (Jetson TK1)
diff --git a/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix b/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix
index eb676eae05e8..2833b75b84d8 100644
--- a/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix
+++ b/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix
@@ -27,6 +27,7 @@ in
   boot.loader.grub.enable = false;
   boot.loader.generic-extlinux-compatible.enable = true;
 
+  boot.consoleLogLevel = lib.mkDefault 7;
   boot.kernelPackages = pkgs.linuxPackages_rpi;
 
   # FIXME: this probably should be in installation-device.nix
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index c6440dd906fd..28ed10a5ece6 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -301,6 +301,8 @@
       pykms = 282;
       kodi = 283;
       restya-board = 284;
+      mighttpd2 = 285;
+      hass = 286;
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
@@ -570,6 +572,8 @@
       pykms = 282;
       kodi = 283;
       restya-board = 284;
+      mighttpd2 = 285;
+      hass = 286;
 
       # 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/nixpkgs.nix b/nixos/modules/misc/nixpkgs.nix
index 1793c1447d60..c3e7ab9a666a 100644
--- a/nixos/modules/misc/nixpkgs.nix
+++ b/nixos/modules/misc/nixpkgs.nix
@@ -4,10 +4,10 @@ with lib;
 
 let
   isConfig = x:
-    builtins.isAttrs x || builtins.isFunction x;
+    builtins.isAttrs x || lib.isFunction x;
 
   optCall = f: x:
-    if builtins.isFunction f
+    if lib.isFunction f
     then f x
     else f;
 
@@ -38,7 +38,7 @@ let
   overlayType = mkOptionType {
     name = "nixpkgs-overlay";
     description = "nixpkgs overlay";
-    check = builtins.isFunction;
+    check = lib.isFunction;
     merge = lib.mergeOneOption;
   };
 
@@ -69,7 +69,6 @@ in
           [ (self: super: {
               openssh = super.openssh.override {
                 hpnSupport = true;
-                withKerberos = true;
                 kerberos = self.libkrb5;
               };
             };
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 8d329b5b4b25..2ec8b28c3fc4 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -84,6 +84,7 @@
   ./programs/info.nix
   ./programs/java.nix
   ./programs/kbdlight.nix
+  ./programs/less.nix
   ./programs/light.nix
   ./programs/man.nix
   ./programs/mosh.nix
@@ -200,6 +201,7 @@
   ./services/desktops/dleyna-server.nix
   ./services/desktops/geoclue2.nix
   ./services/desktops/gnome3/at-spi2-core.nix
+  ./services/desktops/gnome3/chrome-gnome-shell.nix
   ./services/desktops/gnome3/evolution-data-server.nix
   ./services/desktops/gnome3/gnome-disks.nix
   ./services/desktops/gnome3/gnome-documents.nix
@@ -225,7 +227,6 @@
   ./services/games/terraria.nix
   ./services/hardware/acpid.nix
   ./services/hardware/actkbd.nix
-  ./services/hardware/amd-hybrid-graphics.nix
   ./services/hardware/bluetooth.nix
   ./services/hardware/brltty.nix
   ./services/hardware/freefall.nix
@@ -314,6 +315,7 @@
   ./services/misc/gogs.nix
   ./services/misc/gollum.nix
   ./services/misc/gpsd.nix
+  ./services/misc/home-assistant.nix
   ./services/misc/ihaskell.nix
   ./services/misc/irkerd.nix
   ./services/misc/jackett.nix
@@ -424,6 +426,7 @@
   ./services/network-filesystems/yandex-disk.nix
   ./services/network-filesystems/xtreemfs.nix
   ./services/networking/amuled.nix
+  ./services/networking/aria2.nix
   ./services/networking/asterisk.nix
   ./services/networking/atftpd.nix
   ./services/networking/avahi-daemon.nix
@@ -540,6 +543,7 @@
   ./services/networking/ssh/lshd.nix
   ./services/networking/ssh/sshd.nix
   ./services/networking/strongswan.nix
+  ./services/networking/stunnel.nix
   ./services/networking/supplicant.nix
   ./services/networking/supybot.nix
   ./services/networking/syncthing.nix
@@ -634,6 +638,7 @@
   ./services/web-servers/lighttpd/default.nix
   ./services/web-servers/lighttpd/gitweb.nix
   ./services/web-servers/lighttpd/inginious.nix
+  ./services/web-servers/mighttpd2.nix
   ./services/web-servers/minio.nix
   ./services/web-servers/nginx/default.nix
   ./services/web-servers/phpfpm/default.nix
diff --git a/nixos/modules/profiles/clone-config.nix b/nixos/modules/profiles/clone-config.nix
index 77d86f8d7405..5b4e68beb6a6 100644
--- a/nixos/modules/profiles/clone-config.nix
+++ b/nixos/modules/profiles/clone-config.nix
@@ -17,7 +17,7 @@ let
   # you should use files).
   moduleFiles =
     # FIXME: use typeOf (Nix 1.6.1).
-    filter (x: !isAttrs x && !builtins.isFunction x) modules;
+    filter (x: !isAttrs x && !lib.isFunction x) modules;
 
   # Partition module files because between NixOS and non-NixOS files.  NixOS
   # files may change if the repository is updated.
diff --git a/nixos/modules/programs/less.nix b/nixos/modules/programs/less.nix
new file mode 100644
index 000000000000..c0283c9e6862
--- /dev/null
+++ b/nixos/modules/programs/less.nix
@@ -0,0 +1,118 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.programs.less;
+
+  configFile = ''
+    #command
+    ${concatStringsSep "\n"
+      (mapAttrsToList (command: action: "${command} ${action}") cfg.commands)
+    }
+    ${if cfg.clearDefaultCommands then "#stop" else ""}
+
+    #line-edit
+    ${concatStringsSep "\n"
+      (mapAttrsToList (command: action: "${command} ${action}") cfg.lineEditingKeys)
+    }
+
+    #env
+    ${concatStringsSep "\n"
+      (mapAttrsToList (variable: values: "${variable}=${values}") cfg.envVariables)
+    }
+  '';
+
+  lessKey = pkgs.runCommand "lesskey"
+            { src = pkgs.writeText "lessconfig" configFile; }
+            "${pkgs.less}/bin/lesskey -o $out $src";
+
+in
+
+{
+  options = {
+
+    programs.less = {
+
+      enable = mkEnableOption "less";
+
+      commands = mkOption {
+        type = types.attrsOf types.str;
+        default = {};
+        example = {
+          "h" = "noaction 5\e(";
+          "l" = "noaction 5\e)";
+        };
+        description = "Defines new command keys.";
+      };
+
+      clearDefaultCommands = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Clear all default commands.
+          You should remember to set the quit key.
+          Otherwise you will not be able to leave less without killing it.
+        '';
+      };
+
+      lineEditingKeys = mkOption {
+        type = types.attrsOf types.str;
+        default = {};
+        example = {
+          "\e" = "abort";
+        };
+        description = "Defines new line-editing keys.";
+      };
+
+      envVariables = mkOption {
+        type = types.attrsOf types.str;
+        default = {};
+        example = {
+          LESS = "--quit-if-one-screen";
+        };
+        description = "Defines environment variables.";
+      };
+
+      lessopen = mkOption {
+        type = types.nullOr types.str;
+        default = "|${pkgs.lesspipe}/bin/lesspipe.sh %s";
+        description = ''
+          Before less opens a file, it first gives your input preprocessor a chance to modify the way the contents of the file are displayed.
+        '';
+      };
+
+      lessclose = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        description = ''
+          When less closes a file opened in such a way, it will call another program, called the input postprocessor, which may  perform  any  desired  clean-up  action (such  as deleting the replacement file created by LESSOPEN).
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    environment.systemPackages = [ pkgs.less ];
+
+    environment.variables = {
+      "LESSKEY_SYSTEM" = toString lessKey;
+    } // optionalAttrs (cfg.lessopen != null) {
+      "LESSOPEN" = cfg.lessopen;
+    } // optionalAttrs (cfg.lessclose != null) {
+      "LESSCLOSE" = cfg.lessclose;
+    };
+
+    warnings = optional (
+      cfg.clearDefaultCommands && (all (x: x != "quit") (attrValues cfg.commands))
+    ) ''
+      config.programs.less.clearDefaultCommands clears all default commands of less but there is no alternative binding for exiting.
+      Consider adding a binding for 'quit'.
+    '';
+  };
+
+  meta.maintainers = with maintainers; [ johnazoidberg ];
+
+}
diff --git a/nixos/modules/programs/zsh/oh-my-zsh.nix b/nixos/modules/programs/zsh/oh-my-zsh.nix
index 9077643c4440..b995d390b279 100644
--- a/nixos/modules/programs/zsh/oh-my-zsh.nix
+++ b/nixos/modules/programs/zsh/oh-my-zsh.nix
@@ -48,6 +48,15 @@ in
             Name of the theme to be used by oh-my-zsh.
           '';
         };
+
+        cacheDir = mkOption {
+          default = "$HOME/.cache/oh-my-zsh";
+          type = types.str;
+          description = ''
+            Cache directory to be used by `oh-my-zsh`.
+            Without this option it would default to the read-only nix store.
+          '';
+        };
       };
     };
 
@@ -74,6 +83,13 @@ in
           "ZSH_THEME=\"${cfg.theme}\""
         }
 
+        ${optionalString (cfg.cacheDir != null) ''
+          if [[ ! -d "${cfg.cacheDir}" ]]; then
+            mkdir -p "${cfg.cacheDir}"
+          fi
+          ZSH_CACHE_DIR=${cfg.cacheDir}
+        ''}
+
         source $ZSH/oh-my-zsh.sh
       '';
     };
diff --git a/nixos/modules/programs/zsh/zsh.nix b/nixos/modules/programs/zsh/zsh.nix
index 6fb1346bbb33..5102bfef0325 100644
--- a/nixos/modules/programs/zsh/zsh.nix
+++ b/nixos/modules/programs/zsh/zsh.nix
@@ -36,8 +36,9 @@ in
       shellAliases = mkOption {
         default = config.environment.shellAliases;
         description = ''
-          Set of aliases for zsh shell. See <option>environment.shellAliases</option>
-          for an option format description.
+          Set of aliases for zsh shell. Overrides the default value taken from
+           <option>environment.shellAliases</option>.
+          See <option>environment.shellAliases</option> for an option format description.
         '';
         type = types.attrs; # types.attrsOf types.stringOrPath;
       };
diff --git a/nixos/modules/security/sudo.nix b/nixos/modules/security/sudo.nix
index cfd0595e63b7..a57f14bb5ae1 100644
--- a/nixos/modules/security/sudo.nix
+++ b/nixos/modules/security/sudo.nix
@@ -8,6 +8,22 @@ let
 
   inherit (pkgs) sudo;
 
+  toUserString = user: if (isInt user) then "#${toString user}" else "${user}";
+  toGroupString = group: if (isInt group) then "%#${toString group}" else "%${group}";
+
+  toCommandOptionsString = options:
+    "${concatStringsSep ":" options}${optionalString (length options != 0) ":"} ";
+
+  toCommandsString = commands:
+    concatStringsSep ", " (
+      map (command:
+        if (isString command) then
+          command
+        else
+          "${toCommandOptionsString command.options}${command.command}"
+      ) commands
+    );
+
 in
 
 {
@@ -47,6 +63,97 @@ in
         '';
     };
 
+    security.sudo.extraRules = mkOption {
+      description = ''
+        Define specific rules to be in the <filename>sudoers</filename> file.
+      '';
+      default = [];
+      example = [
+        # Allow execution of any command by all users in group sudo,
+        # requiring a password.
+        { groups = [ "sudo" ]; commands = [ "ALL" ]; }
+
+        # Allow execution of "/home/root/secret.sh" by user `backup`, `database`
+        # and the group with GID `1006` without a password.
+        { users = [ "backup" ]; groups = [ 1006 ];
+          commands = [ { command = "/home/root/secret.sh"; options = [ "SETENV" "NOPASSWD" ]; } ]; }
+
+        # Allow all users of group `bar` to run two executables as user `foo`
+        # with arguments being pre-set.
+        { groups = [ "bar" ]; runAs = "foo";
+          commands =
+            [ "/home/baz/cmd1.sh hello-sudo"
+              { command = ''/home/baz/cmd2.sh ""''; options = [ "SETENV" ]; } ]; }
+      ];
+      type = with types; listOf (submodule {
+        options = {
+          users = mkOption {
+            type = with types; listOf (either string int);
+            description = ''
+              The usernames / UIDs this rule should apply for.
+            '';
+            default = [];
+          };
+
+          groups = mkOption {
+            type = with types; listOf (either string int);
+            description = ''
+              The groups / GIDs this rule should apply for.
+            '';
+            default = [];
+          };
+
+          host = mkOption {
+            type = types.string;
+            default = "ALL";
+            description = ''
+              For what host this rule should apply.
+            '';
+          };
+
+          runAs = mkOption {
+            type = with types; string;
+            default = "ALL:ALL";
+            description = ''
+              Under which user/group the specified command is allowed to run.
+
+              A user can be specified using just the username: <code>"foo"</code>.
+              It is also possible to specify a user/group combination using <code>"foo:bar"</code>
+              or to only allow running as a specific group with <code>":bar"</code>.
+            '';
+          };
+
+          commands = mkOption {
+            description = ''
+              The commands for which the rule should apply.
+            '';
+            type = with types; listOf (either string (submodule {
+
+              options = {
+                command = mkOption {
+                  type = with types; string;
+                  description = ''
+                    A command being either just a path to a binary to allow any arguments,
+                    the full command with arguments pre-set or with <code>""</code> used as the argument,
+                    not allowing arguments to the command at all.
+                  '';
+                };
+
+                options = mkOption {
+                  type = with types; listOf (enum [ "NOPASSWD" "PASSWD" "NOEXEC" "EXEC" "SETENV" "NOSETENV" "LOG_INPUT" "NOLOG_INPUT" "LOG_OUTPUT" "NOLOG_OUTPUT" ]);
+                  description = ''
+                    Options for running the command. Refer to the <a href="https://www.sudo.ws/man/1.7.10/sudoers.man.html">sudo manual</a>.
+                  '';
+                  default = [];
+                };
+              };
+
+            }));
+          };
+        };
+      });
+    };
+
     security.sudo.extraConfig = mkOption {
       type = types.lines;
       default = "";
@@ -61,10 +168,16 @@ in
 
   config = mkIf cfg.enable {
 
+    security.sudo.extraRules = [
+      { groups = [ "wheel" ];
+        commands = [ { command = "ALL"; options = (if cfg.wheelNeedsPassword then [ "SETENV" ] else [ "NOPASSWD" "SETENV" ]); } ];
+      }
+    ];
+
     security.sudo.configFile =
       ''
         # Don't edit this file. Set the NixOS options ‘security.sudo.configFile’
-        # or ‘security.sudo.extraConfig’ instead.
+        # or ‘security.sudo.extraRules’ instead.
 
         # Keep SSH_AUTH_SOCK so that pam_ssh_agent_auth.so can do its magic.
         Defaults env_keep+=SSH_AUTH_SOCK
@@ -72,8 +185,18 @@ in
         # "root" is allowed to do anything.
         root        ALL=(ALL:ALL) SETENV: ALL
 
-        # Users in the "wheel" group can do anything.
-        %wheel      ALL=(ALL:ALL) ${if cfg.wheelNeedsPassword then "" else "NOPASSWD: ALL, "}SETENV: ALL
+        # extraRules
+        ${concatStringsSep "\n" (
+          lists.flatten (
+            map (
+              rule: if (length rule.commands != 0) then [
+                (map (user: "${toUserString user}	${rule.host}=(${rule.runAs})	${toCommandsString rule.commands}") rule.users)
+                (map (group: "${toGroupString group}	${rule.host}=(${rule.runAs})	${toCommandsString rule.commands}") rule.groups)
+              ] else []
+            ) cfg.extraRules
+          )
+        )}
+
         ${cfg.extraConfig}
       '';
 
diff --git a/nixos/modules/services/desktops/gnome3/chrome-gnome-shell.nix b/nixos/modules/services/desktops/gnome3/chrome-gnome-shell.nix
new file mode 100644
index 000000000000..2740a22c7ca0
--- /dev/null
+++ b/nixos/modules/services/desktops/gnome3/chrome-gnome-shell.nix
@@ -0,0 +1,27 @@
+# Chrome GNOME Shell native host connector.
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+  ###### interface
+  options = {
+    services.gnome3.chrome-gnome-shell.enable = mkEnableOption ''
+      Chrome GNOME Shell native host connector, a DBus service
+      allowing to install GNOME Shell extensions from a web browser.
+    '';
+  };
+
+
+  ###### implementation
+  config = mkIf config.services.gnome3.chrome-gnome-shell.enable {
+    environment.etc = {
+      "chromium/native-messaging-hosts/org.gnome.chrome_gnome_shell.json".source = "${pkgs.chrome-gnome-shell}/etc/chromium/native-messaging-hosts/org.gnome.chrome_gnome_shell.json";
+      "opt/chrome/native-messaging-hosts/org.gnome.chrome_gnome_shell.json".source = "${pkgs.chrome-gnome-shell}/etc/opt/chrome/native-messaging-hosts/org.gnome.chrome_gnome_shell.json";
+    };
+
+    environment.systemPackages = [ pkgs.chrome-gnome-shell ];
+
+    services.dbus.packages = [ pkgs.chrome-gnome-shell ];
+  };
+}
diff --git a/nixos/modules/services/hardware/amd-hybrid-graphics.nix b/nixos/modules/services/hardware/amd-hybrid-graphics.nix
deleted file mode 100644
index b0f9ff56d1b2..000000000000
--- a/nixos/modules/services/hardware/amd-hybrid-graphics.nix
+++ /dev/null
@@ -1,46 +0,0 @@
-{ config, pkgs, lib, ... }:
-
-{
-
-  ###### interface
-
-  options = {
-
-    hardware.amdHybridGraphics.disable = lib.mkOption {
-      default = false;
-      type = lib.types.bool;
-      description = ''
-        Completely disable the AMD graphics card and use the
-        integrated graphics processor instead.
-      '';
-    };
-
-  };
-
-
-  ###### implementation
-
-  config = lib.mkIf config.hardware.amdHybridGraphics.disable {
-    systemd.services."amd-hybrid-graphics" = {
-      path = [ pkgs.bash ];
-      description = "Disable AMD Card";
-      after = [ "sys-kernel-debug.mount" ];
-      before = [ "systemd-vconsole-setup.service" "display-manager.service" ];
-      requires = [ "sys-kernel-debug.mount" "vgaswitcheroo.path" ];
-      serviceConfig = {
-        Type = "oneshot";
-        RemainAfterExit = true;
-        ExecStart = "${pkgs.bash}/bin/sh -c 'echo -e \"IGD\\nOFF\" > /sys/kernel/debug/vgaswitcheroo/switch'";
-        ExecStop = "${pkgs.bash}/bin/sh -c 'echo ON >/sys/kernel/debug/vgaswitcheroo/switch'";
-      };
-    };
-    systemd.paths."vgaswitcheroo" = {
-      pathConfig = {
-        PathExists = "/sys/kernel/debug/vgaswitcheroo/switch";
-        Unit = "amd-hybrid-graphics.service";
-      };
-      wantedBy = ["multi-user.target"];
-    };
-  };
-
-}
diff --git a/nixos/modules/services/mail/postfix.nix b/nixos/modules/services/mail/postfix.nix
index 867c0ea6761c..22af7e876af2 100644
--- a/nixos/modules/services/mail/postfix.nix
+++ b/nixos/modules/services/mail/postfix.nix
@@ -15,20 +15,18 @@ let
   haveVirtual = cfg.virtual != "";
 
   clientAccess =
-    if (cfg.dnsBlacklistOverrides != "")
-    then [ "check_client_access hash:/etc/postfix/client_access" ]
-    else [];
+    optional (cfg.dnsBlacklistOverrides != "")
+      "check_client_access hash:/etc/postfix/client_access";
 
   dnsBl =
-    if (cfg.dnsBlacklists != [])
-    then [ (concatStringsSep ", " (map (s: "reject_rbl_client " + s) cfg.dnsBlacklists)) ]
-    else [];
+    optionals (cfg.dnsBlacklists != [])
+      (map (s: "reject_rbl_client " + s) cfg.dnsBlacklists);
 
   clientRestrictions = concatStringsSep ", " (clientAccess ++ dnsBl);
 
   mainCf = let
     escape = replaceStrings ["$"] ["$$"];
-    mkList = items: "\n  " + concatStringsSep "\n  " items;
+    mkList = items: "\n  " + concatStringsSep ",\n  " items;
     mkVal = value:
       if isList value then mkList value
         else " " + (if value == true then "yes"
@@ -36,72 +34,9 @@ let
         else toString value);
     mkEntry = name: value: "${escape name} =${mkVal value}";
   in
-    concatStringsSep "\n" (mapAttrsToList mkEntry (recursiveUpdate defaultConf cfg.config))
+    concatStringsSep "\n" (mapAttrsToList mkEntry cfg.config)
       + "\n" + cfg.extraConfig;
 
-  defaultConf = {
-    compatibility_level  = "9999";
-    mail_owner           = user;
-    default_privs        = "nobody";
-
-    # NixOS specific locations
-    data_directory       = "/var/lib/postfix/data";
-    queue_directory      = "/var/lib/postfix/queue";
-
-    # Default location of everything in package
-    meta_directory       = "${pkgs.postfix}/etc/postfix";
-    command_directory    = "${pkgs.postfix}/bin";
-    sample_directory     = "/etc/postfix";
-    newaliases_path      = "${pkgs.postfix}/bin/newaliases";
-    mailq_path           = "${pkgs.postfix}/bin/mailq";
-    readme_directory     = false;
-    sendmail_path        = "${pkgs.postfix}/bin/sendmail";
-    daemon_directory     = "${pkgs.postfix}/libexec/postfix";
-    manpage_directory    = "${pkgs.postfix}/share/man";
-    html_directory       = "${pkgs.postfix}/share/postfix/doc/html";
-    shlib_directory      = false;
-    relayhost            = if cfg.relayHost == "" then "" else
-                             if cfg.lookupMX
-                             then "${cfg.relayHost}:${toString cfg.relayPort}"
-                             else "[${cfg.relayHost}]:${toString cfg.relayPort}";
-
-    mail_spool_directory = "/var/spool/mail/";
-    setgid_group         = setgidGroup;
-  }
-  // optionalAttrs config.networking.enableIPv6 { inet_protocols = "all"; }
-  // optionalAttrs (cfg.networks != null) { mynetworks = cfg.networks; }
-  // optionalAttrs (cfg.networksStyle != "") { mynetworks_style = cfg.networksStyle; }
-  // optionalAttrs (cfg.hostname != "") { myhostname = cfg.hostname; }
-  // optionalAttrs (cfg.domain != "") { mydomain = cfg.domain; }
-  // optionalAttrs (cfg.origin != "") { myorigin =  cfg.origin; }
-  // optionalAttrs (cfg.destination != null) { mydestination = cfg.destination; }
-  // optionalAttrs (cfg.relayDomains != null) { relay_domains = cfg.relayDomains; }
-  // optionalAttrs (cfg.recipientDelimiter != "") { recipient_delimiter = cfg.recipientDelimiter; }
-  // optionalAttrs haveAliases { alias_maps = "${cfg.aliasMapType}:/etc/postfix/aliases"; }
-  // optionalAttrs haveTransport { transport_maps = "hash:/etc/postfix/transport"; }
-  // optionalAttrs haveVirtual { virtual_alias_maps = "${cfg.virtualMapType}:/etc/postfix/virtual"; }
-  // optionalAttrs (cfg.dnsBlacklists != []) { smtpd_client_restrictions = clientRestrictions; }
-  // optionalAttrs cfg.useSrs {
-    sender_canonical_maps = "tcp:127.0.0.1:10001";
-    sender_canonical_classes = "envelope_sender";
-    recipient_canonical_maps = "tcp:127.0.0.1:10002";
-    recipient_canonical_classes= "envelope_recipient";
-  }
-  // optionalAttrs cfg.enableHeaderChecks { header_checks = "regexp:/etc/postfix/header_checks"; }
-  // optionalAttrs (cfg.sslCert != "") {
-    smtp_tls_CAfile = cfg.sslCACert;
-    smtp_tls_cert_file = cfg.sslCert;
-    smtp_tls_key_file = cfg.sslKey;
-
-    smtp_use_tls = true;
-
-    smtpd_tls_CAfile = cfg.sslCACert;
-    smtpd_tls_cert_file = cfg.sslCert;
-    smtpd_tls_key_file = cfg.sslKey;
-
-    smtpd_use_tls = true;
-  };
-
   masterCfOptions = { options, config, name, ... }: {
     options = {
       name = mkOption {
@@ -507,7 +442,6 @@ in
 
       config = mkOption {
         type = with types; attrsOf (either bool (either str (listOf str)));
-        default = defaultConf;
         description = ''
           The main.cf configuration file as key value set.
         '';
@@ -749,6 +683,67 @@ in
           '';
         };
 
+      services.postfix.config = (mapAttrs (_: v: mkDefault v) {
+        compatibility_level  = "9999";
+        mail_owner           = cfg.user;
+        default_privs        = "nobody";
+
+        # NixOS specific locations
+        data_directory       = "/var/lib/postfix/data";
+        queue_directory      = "/var/lib/postfix/queue";
+
+        # Default location of everything in package
+        meta_directory       = "${pkgs.postfix}/etc/postfix";
+        command_directory    = "${pkgs.postfix}/bin";
+        sample_directory     = "/etc/postfix";
+        newaliases_path      = "${pkgs.postfix}/bin/newaliases";
+        mailq_path           = "${pkgs.postfix}/bin/mailq";
+        readme_directory     = false;
+        sendmail_path        = "${pkgs.postfix}/bin/sendmail";
+        daemon_directory     = "${pkgs.postfix}/libexec/postfix";
+        manpage_directory    = "${pkgs.postfix}/share/man";
+        html_directory       = "${pkgs.postfix}/share/postfix/doc/html";
+        shlib_directory      = false;
+        mail_spool_directory = "/var/spool/mail/";
+        setgid_group         = cfg.setgidGroup;
+      })
+      // optionalAttrs (cfg.relayHost != "") { relayhost = if cfg.lookupMX
+                                                           then "${cfg.relayHost}:${toString cfg.relayPort}"
+                                                           else "[${cfg.relayHost}]:${toString cfg.relayPort}"; }
+      // optionalAttrs config.networking.enableIPv6 { inet_protocols = mkDefault "all"; }
+      // optionalAttrs (cfg.networks != null) { mynetworks = cfg.networks; }
+      // optionalAttrs (cfg.networksStyle != "") { mynetworks_style = cfg.networksStyle; }
+      // optionalAttrs (cfg.hostname != "") { myhostname = cfg.hostname; }
+      // optionalAttrs (cfg.domain != "") { mydomain = cfg.domain; }
+      // optionalAttrs (cfg.origin != "") { myorigin =  cfg.origin; }
+      // optionalAttrs (cfg.destination != null) { mydestination = cfg.destination; }
+      // optionalAttrs (cfg.relayDomains != null) { relay_domains = cfg.relayDomains; }
+      // optionalAttrs (cfg.recipientDelimiter != "") { recipient_delimiter = cfg.recipientDelimiter; }
+      // optionalAttrs haveAliases { alias_maps = [ "${cfg.aliasMapType}:/etc/postfix/aliases" ]; }
+      // optionalAttrs haveTransport { transport_maps = [ "hash:/etc/postfix/transport" ]; }
+      // optionalAttrs haveVirtual { virtual_alias_maps = [ "${cfg.virtualMapType}:/etc/postfix/virtual" ]; }
+      // optionalAttrs (cfg.dnsBlacklists != []) { smtpd_client_restrictions = clientRestrictions; }
+      // optionalAttrs cfg.useSrs {
+        sender_canonical_maps = [ "tcp:127.0.0.1:10001" ];
+        sender_canonical_classes = [ "envelope_sender" ];
+        recipient_canonical_maps = [ "tcp:127.0.0.1:10002" ];
+        recipient_canonical_classes = [ "envelope_recipient" ];
+      }
+      // optionalAttrs cfg.enableHeaderChecks { header_checks = [ "regexp:/etc/postfix/header_checks" ]; }
+      // optionalAttrs (cfg.sslCert != "") {
+        smtp_tls_CAfile = cfg.sslCACert;
+        smtp_tls_cert_file = cfg.sslCert;
+        smtp_tls_key_file = cfg.sslKey;
+
+        smtp_use_tls = true;
+
+        smtpd_tls_CAfile = cfg.sslCACert;
+        smtpd_tls_cert_file = cfg.sslCert;
+        smtpd_tls_key_file = cfg.sslKey;
+
+        smtpd_use_tls = true;
+      };
+
       services.postfix.masterConfig = {
         smtp_inet = {
           name = "smtp";
diff --git a/nixos/modules/services/misc/home-assistant.nix b/nixos/modules/services/misc/home-assistant.nix
new file mode 100644
index 000000000000..666fa68b01ce
--- /dev/null
+++ b/nixos/modules/services/misc/home-assistant.nix
@@ -0,0 +1,116 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.home-assistant;
+
+  configFile = pkgs.writeText "configuration.yaml" (builtins.toJSON cfg.config);
+
+  availableComponents = pkgs.home-assistant.availableComponents;
+
+  # Returns whether component is used in config
+  useComponent = component: hasAttrByPath (splitString "." component) cfg.config;
+
+  # List of components used in config
+  extraComponents = filter useComponent availableComponents;
+
+  package = if cfg.autoExtraComponents
+    then (cfg.package.override { inherit extraComponents; })
+    else cfg.package;
+
+in {
+  meta.maintainers = with maintainers; [ dotlambda ];
+
+  options.services.home-assistant = {
+    enable = mkEnableOption "Home Assistant";
+
+    configDir = mkOption {
+      default = "/var/lib/hass";
+      type = types.path;
+      description = "The config directory, where your <filename>configuration.yaml</filename> is located.";
+    };
+
+    config = mkOption {
+      default = null;
+      type = with types; nullOr attrs;
+      example = literalExample ''
+        {
+          homeassistant = {
+            name = "Home";
+            time_zone = "UTC";
+          };
+          frontend = { };
+          http = { };
+          feedreader.urls = [ "https://nixos.org/blogs.xml" ];
+        }
+      '';
+      description = ''
+        Your <filename>configuration.yaml</filename> as a Nix attribute set.
+        Beware that setting this option will delete your previous <filename>configuration.yaml</filename>.
+      '';
+    };
+
+    package = mkOption {
+      default = pkgs.home-assistant;
+      defaultText = "pkgs.home-assistant";
+      type = types.package;
+      example = literalExample ''
+        pkgs.home-assistant.override {
+          extraPackages = ps: with ps; [ colorlog ];
+        }
+      '';
+      description = ''
+        Home Assistant package to use.
+        Override <literal>extraPackages</literal> in order to add additional dependencies.
+      '';
+    };
+
+    autoExtraComponents = mkOption {
+      default = true;
+      type = types.bool;
+      description = ''
+        If set to <literal>true</literal>, the components used in <literal>config</literal>
+        are set as the specified package's <literal>extraComponents</literal>.
+        This in turn adds all packaged dependencies to the derivation.
+        You might still see import errors in your log.
+        In this case, you will need to package the necessary dependencies yourself
+        or ask for someone else to package them.
+        If a dependency is packaged but not automatically added to this list,
+        you might need to specify it in <literal>extraPackages</literal>.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.services.home-assistant = {
+      description = "Home Assistant";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+      preStart = lib.optionalString (cfg.config != null) ''
+        rm -f ${cfg.configDir}/configuration.yaml
+        ln -s ${configFile} ${cfg.configDir}/configuration.yaml
+      '';
+      serviceConfig = {
+        ExecStart = ''
+          ${package}/bin/hass --config "${cfg.configDir}"
+        '';
+        User = "hass";
+        Group = "hass";
+        Restart = "on-failure";
+        ProtectSystem = "strict";
+        ReadWritePaths = "${cfg.configDir}";
+        PrivateTmp = true;
+      };
+    };
+
+    users.extraUsers.hass = {
+      home = cfg.configDir;
+      createHome = true;
+      group = "hass";
+      uid = config.ids.uids.hass;
+    };
+
+    users.extraGroups.hass.gid = config.ids.gids.hass;
+  };
+}
diff --git a/nixos/modules/services/misc/matrix-synapse.nix b/nixos/modules/services/misc/matrix-synapse.nix
index 80979547d339..7e880ad09b89 100644
--- a/nixos/modules/services/misc/matrix-synapse.nix
+++ b/nixos/modules/services/misc/matrix-synapse.nix
@@ -4,6 +4,8 @@ with lib;
 
 let
   cfg = config.services.matrix-synapse;
+  pg = config.services.postgresql;
+  usePostgresql = cfg.database_type == "psycopg2";
   logConfigFile = pkgs.writeText "log_config.yaml" cfg.logConfig;
   mkResource = r: ''{names: ${builtins.toJSON r.names}, compress: ${boolToString r.compress}}'';
   mkListener = l: ''{port: ${toString l.port}, bind_address: "${l.bind_address}", type: ${l.type}, tls: ${boolToString l.tls}, x_forwarded: ${boolToString l.x_forwarded}, resources: [${concatStringsSep "," (map mkResource l.resources)}]}'';
@@ -38,7 +40,7 @@ database: {
   name: "${cfg.database_type}",
   args: {
     ${concatStringsSep ",\n    " (
-      mapAttrsToList (n: v: "\"${n}\": ${v}") cfg.database_args
+      mapAttrsToList (n: v: "\"${n}\": ${builtins.toJSON v}") cfg.database_args
     )}
   }
 }
@@ -155,7 +157,7 @@ in {
       tls_certificate_path = mkOption {
         type = types.nullOr types.str;
         default = null;
-        example = "/var/lib/matrix-synapse/homeserver.tls.crt";
+        example = "${cfg.dataDir}/homeserver.tls.crt";
         description = ''
           PEM encoded X509 certificate for TLS.
           You can replace the self-signed certificate that synapse
@@ -167,7 +169,7 @@ in {
       tls_private_key_path = mkOption {
         type = types.nullOr types.str;
         default = null;
-        example = "/var/lib/matrix-synapse/homeserver.tls.key";
+        example = "${cfg.dataDir}/homeserver.tls.key";
         description = ''
           PEM encoded private key for TLS. Specify null if synapse is not
           speaking TLS directly.
@@ -176,7 +178,7 @@ in {
       tls_dh_params_path = mkOption {
         type = types.nullOr types.str;
         default = null;
-        example = "/var/lib/matrix-synapse/homeserver.tls.dh";
+        example = "${cfg.dataDir}/homeserver.tls.dh";
         description = ''
           PEM dh parameters for ephemeral keys
         '';
@@ -184,6 +186,7 @@ in {
       server_name = mkOption {
         type = types.str;
         example = "example.com";
+        default = config.networking.hostName;
         description = ''
           The domain name of the server, with optional explicit port.
           This is used by remote servers to connect to this server,
@@ -339,16 +342,39 @@ in {
       };
       database_type = mkOption {
         type = types.enum [ "sqlite3" "psycopg2" ];
-        default = "sqlite3";
+        default = if versionAtLeast config.system.stateVersion "18.03"
+          then "psycopg2"
+          else "sqlite3";
         description = ''
           The database engine name. Can be sqlite or psycopg2.
         '';
       };
+      create_local_database = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Whether to create a local database automatically.
+        '';
+      };
+      database_name = mkOption {
+        type = types.str;
+        default = "matrix-synapse";
+        description = "Database name.";
+      };
+      database_user = mkOption {
+        type = types.str;
+        default = "matrix-synapse";
+        description = "Database user name.";
+      };
       database_args = mkOption {
         type = types.attrs;
         default = {
-          database = "${cfg.dataDir}/homeserver.db";
-        };
+          sqlite3 = { database = "${cfg.dataDir}/homeserver.db"; };
+          psycopg2 = {
+            user = cfg.database_user;
+            database = cfg.database_name;
+          };
+        }."${cfg.database_type}";
         description = ''
           Arguments to pass to the engine.
         '';
@@ -623,15 +649,36 @@ in {
         gid = config.ids.gids.matrix-synapse;
       } ];
 
+    services.postgresql.enable = mkIf usePostgresql (mkDefault true);
+
     systemd.services.matrix-synapse = {
       description = "Synapse Matrix homeserver";
-      after = [ "network.target" ];
+      after = [ "network.target" "postgresql.service" ];
       wantedBy = [ "multi-user.target" ];
       preStart = ''
         ${cfg.package}/bin/homeserver \
           --config-path ${configFile} \
           --keys-directory ${cfg.dataDir} \
           --generate-keys
+      '' + optionalString (usePostgresql && cfg.create_local_database) ''
+        if ! test -e "${cfg.dataDir}/db-created"; then
+          ${pkgs.sudo}/bin/sudo -u ${pg.superUser} \
+            ${pg.package}/bin/createuser \
+            --login \
+            --no-createdb \
+            --no-createrole \
+            --encrypted \
+            ${cfg.database_user}
+          ${pkgs.sudo}/bin/sudo -u ${pg.superUser} \
+            ${pg.package}/bin/createdb \
+            --owner=${cfg.database_user} \
+            --encoding=UTF8 \
+            --lc-collate=C \
+            --lc-ctype=C \
+            --template=template0 \
+            ${cfg.database_name}
+          touch "${cfg.dataDir}/db-created"
+        fi
       '';
       serviceConfig = {
         Type = "simple";
diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix
index beca820d2d60..a169b0f2c784 100644
--- a/nixos/modules/services/misc/nix-daemon.nix
+++ b/nixos/modules/services/misc/nix-daemon.nix
@@ -8,7 +8,7 @@ let
 
   nix = cfg.package.out;
 
-  isNix112 = versionAtLeast (getVersion nix) "1.12pre";
+  isNix20 = versionAtLeast (getVersion nix) "2.0pre";
 
   makeNixBuildUser = nr:
     { name = "nixbld${toString nr}";
@@ -26,32 +26,40 @@ let
 
   nixConf =
     let
-      # If we're using sandbox for builds, then provide /bin/sh in
-      # the sandbox as a bind-mount to bash. This means we also need to
-      # include the entire closure of bash.
+      # In Nix < 2.0, If we're using sandbox for builds, then provide
+      # /bin/sh in the sandbox as a bind-mount to bash. This means we
+      # also need to include the entire closure of bash. Nix >= 2.0
+      # provides a /bin/sh by default.
       sh = pkgs.stdenv.shell;
       binshDeps = pkgs.writeReferencesToFile sh;
     in
-      pkgs.runCommand "nix.conf" {extraOptions = cfg.extraOptions; } ''
-        extraPaths=$(for i in $(cat ${binshDeps}); do if test -d $i; then echo $i; fi; done)
+      pkgs.runCommand "nix.conf" { extraOptions = cfg.extraOptions; inherit binshDeps; } ''
+        ${optionalString (!isNix20) ''
+          extraPaths=$(for i in $(cat binshDeps); do if test -d $i; then echo $i; fi; done)
+        ''}
         cat > $out <<END
         # WARNING: this file is generated from the nix.* options in
         # your NixOS configuration, typically
         # /etc/nixos/configuration.nix.  Do not edit it!
         build-users-group = nixbld
-        build-max-jobs = ${toString (cfg.maxJobs)}
-        build-cores = ${toString (cfg.buildCores)}
-        build-use-sandbox = ${if (builtins.isBool cfg.useSandbox) then boolToString cfg.useSandbox else cfg.useSandbox}
-        build-sandbox-paths = ${toString cfg.sandboxPaths} /bin/sh=${sh} $(echo $extraPaths)
-        binary-caches = ${toString cfg.binaryCaches}
-        trusted-binary-caches = ${toString cfg.trustedBinaryCaches}
-        binary-cache-public-keys = ${toString cfg.binaryCachePublicKeys}
+        ${if isNix20 then "max-jobs" else "build-max-jobs"} = ${toString (cfg.maxJobs)}
+        ${if isNix20 then "cores" else "build-cores"} = ${toString (cfg.buildCores)}
+        ${if isNix20 then "sandbox" else "build-use-sandbox"} = ${if (builtins.isBool cfg.useSandbox) then boolToString cfg.useSandbox else cfg.useSandbox}
+        ${if isNix20 then "extra-sandbox-paths" else "build-sandbox-paths"} = ${toString cfg.sandboxPaths} ${optionalString (!isNix20) "/bin/sh=${sh} $(echo $extraPaths)"}
+        ${if isNix20 then "substituters" else "binary-caches"} = ${toString cfg.binaryCaches}
+        ${if isNix20 then "trusted-substituters" else "trusted-binary-caches"} = ${toString cfg.trustedBinaryCaches}
+        ${if isNix20 then "trusted-public-keys" else "binary-cache-public-keys"} = ${toString cfg.binaryCachePublicKeys}
         auto-optimise-store = ${boolToString cfg.autoOptimiseStore}
-        ${optionalString cfg.requireSignedBinaryCaches ''
-          signed-binary-caches = *
+        ${if isNix20 then ''
+          require-sigs = ${if cfg.requireSignedBinaryCaches then "true" else "false"}
+        '' else ''
+          signed-binary-caches = ${if cfg.requireSignedBinaryCaches then "*" else ""}
         ''}
         trusted-users = ${toString cfg.trustedUsers}
         allowed-users = ${toString cfg.allowedUsers}
+        ${optionalString (isNix20 && !cfg.distributedBuilds) ''
+          builders =
+        ''}
         $extraOptions
         END
       '';
@@ -377,8 +385,9 @@ in
     systemd.sockets.nix-daemon.wantedBy = [ "sockets.target" ];
 
     systemd.services.nix-daemon =
-      { path = [ nix pkgs.openssl.bin pkgs.utillinux config.programs.ssh.package ]
-          ++ optionals cfg.distributedBuilds [ pkgs.gzip ];
+      { path = [ nix pkgs.utillinux ]
+          ++ optionals cfg.distributedBuilds [ config.programs.ssh.package pkgs.gzip ]
+          ++ optionals (!isNix20) [ pkgs.openssl.bin ];
 
         environment = cfg.envVars
           // { CURL_CA_BUNDLE = "/etc/ssl/certs/ca-certificates.crt"; }
@@ -396,10 +405,9 @@ in
       };
 
     nix.envVars =
-      { NIX_CONF_DIR = "/etc/nix";
-      }
+      optionalAttrs (!isNix20) {
+        NIX_CONF_DIR = "/etc/nix";
 
-      // optionalAttrs (!isNix112) {
         # Enable the copy-from-other-stores substituter, which allows
         # builds to be sped up by copying build results from remote
         # Nix stores.  To do this, mount the remote file system on a
@@ -407,12 +415,8 @@ in
         NIX_OTHER_STORES = "/run/nix/remote-stores/*/nix";
       }
 
-      // optionalAttrs cfg.distributedBuilds {
-        NIX_BUILD_HOOK =
-          if isNix112 then
-            "${nix}/libexec/nix/build-remote"
-          else
-            "${nix}/libexec/nix/build-remote.pl";
+      // optionalAttrs (cfg.distributedBuilds && !isNix20) {
+        NIX_BUILD_HOOK = "${nix}/libexec/nix/build-remote.pl";
       };
 
     # Set up the environment variables for running Nix.
@@ -420,7 +424,7 @@ in
       { NIX_PATH = concatStringsSep ":" cfg.nixPath;
       };
 
-    environment.extraInit =
+    environment.extraInit = optionalString (!isNix20)
       ''
         # Set up secure multi-user builds: non-root users build through the
         # Nix daemon.
diff --git a/nixos/modules/services/monitoring/netdata.nix b/nixos/modules/services/monitoring/netdata.nix
index e1fde4fc9500..d23b329eeb25 100644
--- a/nixos/modules/services/monitoring/netdata.nix
+++ b/nixos/modules/services/monitoring/netdata.nix
@@ -5,18 +5,25 @@ with lib;
 let
   cfg = config.services.netdata;
 
-  configFile = pkgs.writeText "netdata.conf" cfg.configText;
+  wrappedPlugins = pkgs.runCommand "wrapped-plugins" {} ''
+    mkdir -p $out/libexec/netdata/plugins.d
+    ln -s /run/wrappers/bin/apps.plugin $out/libexec/netdata/plugins.d/apps.plugin
+  '';
+
+  localConfig = {
+    global = {
+      "plugins directory" = "${wrappedPlugins}/libexec/netdata/plugins.d ${pkgs.netdata}/libexec/netdata/plugins.d";
+    };
+  };
+  mkConfig = generators.toINI {} (recursiveUpdate localConfig cfg.config);
+  configFile = pkgs.writeText "netdata.conf" (if cfg.configText != null then cfg.configText else mkConfig);
 
   defaultUser = "netdata";
 
 in {
   options = {
     services.netdata = {
-      enable = mkOption {
-        default = false;
-        type = types.bool;
-        description = "Whether to enable netdata monitoring.";
-      };
+      enable = mkEnableOption "netdata";
 
       user = mkOption {
         type = types.str;
@@ -31,9 +38,9 @@ in {
       };
 
       configText = mkOption {
-        type = types.lines;
-        default = "";
-        description = "netdata.conf configuration.";
+        type = types.nullOr types.lines;
+        description = "Verbatim netdata.conf, cannot be combined with config.";
+        default = null;
         example = ''
           [global]
           debug log = syslog
@@ -42,11 +49,29 @@ in {
         '';
       };
 
+      config = mkOption {
+        type = types.attrsOf types.attrs;
+        default = {};
+        description = "netdata.conf configuration as nix attributes. cannot be combined with configText.";
+        example = literalExample ''
+          global = {
+            "debug log" = "syslog";
+            "access log" = "syslog";
+            "error log" = "syslog";
+          };
+        '';
+        };
+      };
     };
-  };
 
   config = mkIf cfg.enable {
+    assertions =
+      [ { assertion = cfg.config != {} -> cfg.configText == null ;
+          message = "Cannot specify both config and configText";
+        }
+      ];
     systemd.services.netdata = {
+      path = with pkgs; [ gawk curl ];
       description = "Real time performance monitoring";
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
@@ -66,6 +91,15 @@ in {
       };
     };
 
+    security.wrappers."apps.plugin" = {
+      source = "${pkgs.netdata}/libexec/netdata/plugins.d/apps.plugin";
+      capabilities = "cap_dac_read_search,cap_sys_ptrace+ep";
+      owner = cfg.user;
+      group = cfg.group;
+      permissions = "u+rx,g+rx,o-rwx";
+    };
+
+
     users.extraUsers = optional (cfg.user == defaultUser) {
       name = defaultUser;
     };
diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix
index 09cd9cb22ca8..b23266e8d43a 100644
--- a/nixos/modules/services/network-filesystems/samba.nix
+++ b/nixos/modules/services/network-filesystems/samba.nix
@@ -54,10 +54,12 @@ let
       };
 
       serviceConfig = {
-        ExecStart = "${samba}/sbin/${appName} ${args}";
+        ExecStart = "${samba}/sbin/${appName} --foreground --no-process-group ${args}";
         ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
         LimitNOFILE = 16384;
+        PIDFile = "/run/${appName}.pid";
         Type = "notify";
+        NotifyAccess = "all"; #may not do anything...
       };
 
       restartTriggers = [ configFile ];
@@ -231,11 +233,12 @@ in
             after = [ "samba-setup.service" "network.target" ];
             wantedBy = [ "multi-user.target" ];
           };
-
+          # Refer to https://github.com/samba-team/samba/tree/master/packaging/systemd
+          # for correct use with systemd
           services = {
-            "samba-smbd" = daemonService "smbd" "-F";
-            "samba-nmbd" = mkIf cfg.enableNmbd (daemonService "nmbd" "-F");
-            "samba-winbindd" = mkIf cfg.enableWinbindd (daemonService "winbindd" "-F");
+            "samba-smbd" = daemonService "smbd" "";
+            "samba-nmbd" = mkIf cfg.enableNmbd (daemonService "nmbd" "");
+            "samba-winbindd" = mkIf cfg.enableWinbindd (daemonService "winbindd" "");
             "samba-setup" = {
               description = "Samba Setup Task";
               script = setupScript;
diff --git a/nixos/modules/services/networking/aria2.nix b/nixos/modules/services/networking/aria2.nix
index ad4ac9bf45e3..df9c92db2e54 100644
--- a/nixos/modules/services/networking/aria2.nix
+++ b/nixos/modules/services/networking/aria2.nix
@@ -10,9 +10,9 @@ let
   settingsDir = "${homeDir}";
   sessionFile = "${homeDir}/aria2.session";
   downloadDir = "${homeDir}/Downloads";
-  
+
   rangesToStringList = map (x: builtins.toString x.from +"-"+ builtins.toString x.to);
-  
+
   settingsFile = pkgs.writeText "aria2.conf"
   ''
     dir=${cfg.downloadDir}
@@ -110,12 +110,12 @@ in
         mkdir -m 0770 -p "${homeDir}"
         chown aria2:aria2 "${homeDir}"
         if [[ ! -d "${config.services.aria2.downloadDir}" ]]
-        then 
+        then
           mkdir -m 0770 -p "${config.services.aria2.downloadDir}"
           chown aria2:aria2 "${config.services.aria2.downloadDir}"
         fi
         if [[ ! -e "${sessionFile}" ]]
-        then 
+        then
           touch "${sessionFile}"
           chown aria2:aria2 "${sessionFile}"
         fi
@@ -132,4 +132,4 @@ in
       };
     };
   };
-}
\ No newline at end of file
+}
diff --git a/nixos/modules/services/networking/kresd.nix b/nixos/modules/services/networking/kresd.nix
index 011a9b2f58ea..d0c19c4ecb71 100644
--- a/nixos/modules/services/networking/kresd.nix
+++ b/nixos/modules/services/networking/kresd.nix
@@ -43,7 +43,7 @@ in
       type = with types; listOf str;
       default = [ "::1" "127.0.0.1" ];
       description = ''
-        What addresses the server should listen on.
+        What addresses the server should listen on. (UDP+TCP 53)
       '';
     };
     # TODO: perhaps options for more common stuff like cache size or forwarding
@@ -99,9 +99,9 @@ in
         Restart = "on-failure";
       };
 
+      # Trust anchor goes from dns-root-data by default.
       script = ''
-        exec '${package}/bin/kresd' --config '${configFile}' \
-          -k '${pkgs.dns-root-data}/root.key'
+        exec '${package}/bin/kresd' --config '${configFile}' --forks=1
       '';
 
       requires = [ "kresd.socket" ];
diff --git a/nixos/modules/services/networking/openvpn.nix b/nixos/modules/services/networking/openvpn.nix
index 3fbf5a9f0227..7a96b673c51e 100644
--- a/nixos/modules/services/networking/openvpn.nix
+++ b/nixos/modules/services/networking/openvpn.nix
@@ -50,6 +50,11 @@ let
               "up ${pkgs.writeScript "openvpn-${name}-up" upScript}"}
           ${optionalString (cfg.down != "" || cfg.updateResolvConf)
               "down ${pkgs.writeScript "openvpn-${name}-down" downScript}"}
+          ${optionalString (cfg.authUserPass != null)
+              "auth-user-pass ${pkgs.writeText "openvpn-credentials-${name}" ''
+                ${cfg.authUserPass.username}
+                ${cfg.authUserPass.password}
+              ''}"}
         '';
 
     in {
@@ -161,6 +166,29 @@ in
             '';
           };
 
+          authUserPass = mkOption {
+            default = null;
+            description = ''
+              This option can be used to store the username / password credentials
+              with the "auth-user-pass" authentication method.
+
+              WARNING: Using this option will put the credentials WORLD-READABLE in the Nix store!
+            '';
+            type = types.nullOr (types.submodule {
+
+              options = {
+                username = mkOption {
+                  description = "The username to store inside the credentials file.";
+                  type = types.string;
+                };
+
+                password = mkOption {
+                  description = "The password to store inside the credentials file.";
+                  type = types.string;
+                };
+              };
+            });
+          };
         };
 
       });
diff --git a/nixos/modules/services/networking/resilio.nix b/nixos/modules/services/networking/resilio.nix
index 6d2b7bdbca1b..d1c4101f80bd 100644
--- a/nixos/modules/services/networking/resilio.nix
+++ b/nixos/modules/services/networking/resilio.nix
@@ -17,7 +17,7 @@ let
 
     search_lan = entry.searchLAN;
     use_sync_trash = entry.useSyncTrash;
-    known_hosts = knownHosts;
+    known_hosts = entry.knownHosts;
   }) cfg.sharedFolders;
 
   configFile = pkgs.writeText "config.json" (builtins.toJSON ({
diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix
index aa9c0fa1c09f..d9b12d278160 100644
--- a/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixos/modules/services/networking/ssh/sshd.nix
@@ -21,7 +21,7 @@ let
           daemon reads in addition to the the user's authorized_keys file.
           You can combine the <literal>keys</literal> and
           <literal>keyFiles</literal> options.
-          Warning: If you are using <literal>NixOps</literal> then don't use this 
+          Warning: If you are using <literal>NixOps</literal> then don't use this
           option since it will replace the key required for deployment via ssh.
         '';
       };
@@ -137,6 +137,14 @@ in
         '';
       };
 
+      openFirewall = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Whether to automatically open the specified ports in the firewall.
+        '';
+      };
+
       listenAddresses = mkOption {
         type = with types; listOf (submodule {
           options = {
@@ -302,7 +310,7 @@ in
 
       };
 
-    networking.firewall.allowedTCPPorts = cfg.ports;
+    networking.firewall.allowedTCPPorts = if cfg.openFirewall then cfg.ports else [];
 
     security.pam.services.sshd =
       { startSession = true;
diff --git a/nixos/modules/services/networking/stunnel.nix b/nixos/modules/services/networking/stunnel.nix
new file mode 100644
index 000000000000..89a14966eca7
--- /dev/null
+++ b/nixos/modules/services/networking/stunnel.nix
@@ -0,0 +1,221 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.stunnel;
+  yesNo = val: if val then "yes" else "no";
+
+  verifyChainPathAssert = n: c: {
+    assertion = c.verifyHostname == null || (c.verifyChain || c.verifyPeer);
+    message =  "stunnel: \"${n}\" client configuration - hostname verification " +
+      "is not possible without either verifyChain or verifyPeer enabled";
+  };
+
+  serverConfig = {
+    options = {
+      accept = mkOption {
+        type = types.int;
+        description = "On which port stunnel should listen for incoming TLS connections.";
+      };
+
+      connect = mkOption {
+        type = types.int;
+        description = "To which port the decrypted connection should be forwarded.";
+      };
+
+      cert = mkOption {
+        type = types.path;
+        description = "File containing both the private and public keys.";
+      };
+    };
+  };
+
+  clientConfig = {
+    options = {
+      accept = mkOption {
+        type = types.string;
+        description = "IP:Port on which connections should be accepted.";
+      };
+
+      connect = mkOption {
+        type = types.string;
+        description = "IP:Port destination to connect to.";
+      };
+
+      verifyChain = mkOption {
+        type = types.bool;
+        default = true;
+        description = "Check if the provided certificate has a valid certificate chain (against CAPath).";
+      };
+
+      verifyPeer = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Check if the provided certificate is contained in CAPath.";
+      };
+
+      CAPath = mkOption {
+        type = types.path;
+        default = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
+        description = "Path to a file containing certificates to validate against.";
+      };
+
+      verifyHostname = mkOption {
+        type = with types; nullOr string;
+        default = null;
+        description = "If set, stunnel checks if the provided certificate is valid for the given hostname.";
+      };
+    };
+  };
+
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.stunnel = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to enable the stunnel TLS tunneling service.";
+      };
+
+      user = mkOption {
+        type = with types; nullOr string;
+        default = "nobody";
+        description = "The user under which stunnel runs.";
+      };
+
+      group = mkOption {
+        type = with types; nullOr string;
+        default = "nogroup";
+        description = "The group under which stunnel runs.";
+      };
+
+      logLevel = mkOption {
+        type = types.enum [ "emerg" "alert" "crit" "err" "warning" "notice" "info" "debug" ];
+        default = "info";
+        description = "Verbosity of stunnel output.";
+      };
+
+      fipsMode = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Enable FIPS 140-2 mode required for compliance.";
+      };
+
+      enableInsecureSSLv3 = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Enable support for the insecure SSLv3 protocol.";
+      };
+
+
+      servers = mkOption {
+        description = "Define the server configuations.";
+        type = with types; attrsOf (submodule serverConfig);
+        example = {
+          fancyWebserver = {
+            enable = true;
+            accept = 443;
+            connect = 8080;
+            cert = "/path/to/pem/file";
+          };
+        };
+        default = { };
+      };
+
+      clients = mkOption {
+        description = "Define the client configurations.";
+        type = with types; attrsOf (submodule clientConfig);
+        example = {
+          foobar = {
+            accept = "0.0.0.0:8080";
+            connect = "nixos.org:443";
+            verifyChain = false;
+          };
+        };
+        default = { };
+      };
+    };
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    assertions = concatLists [
+      (singleton {
+        assertion = (length (attrValues cfg.servers) != 0) || ((length (attrValues cfg.clients)) != 0);
+        message = "stunnel: At least one server- or client-configuration has to be present.";
+      })
+
+      (mapAttrsToList verifyChainPathAssert cfg.clients)
+    ];
+
+    environment.systemPackages = [ pkgs.stunnel ];
+
+    environment.etc."stunnel.cfg".text = ''
+      ${ if cfg.user != null then "setuid = ${cfg.user}" else "" }
+      ${ if cfg.group != null then "setgid = ${cfg.group}" else "" }
+
+      debug = ${cfg.logLevel}
+
+      ${ optionalString cfg.fipsMode "fips = yes" }
+      ${ optionalString cfg.enableInsecureSSLv3 "options = -NO_SSLv3" }
+
+      ; ----- SERVER CONFIGURATIONS -----
+      ${ lib.concatStringsSep "\n"
+           (lib.mapAttrsToList
+             (n: v: ''
+               [${n}]
+               accept = ${toString v.accept}
+               connect = ${toString v.connect}
+               cert = ${v.cert}
+
+             '')
+           cfg.servers)
+      }
+
+      ; ----- CLIENT CONFIGURATIONS -----
+      ${ lib.concatStringsSep "\n"
+           (lib.mapAttrsToList
+             (n: v: ''
+               [${n}]
+               client = yes
+               accept = ${v.accept}
+               connect = ${v.connect}
+               verifyChain = ${yesNo v.verifyChain}
+               verifyPeer = ${yesNo v.verifyPeer}
+               ${optionalString (v.CAPath != null) "CApath = ${v.CAPath}"}
+               ${optionalString (v.verifyHostname != null) "checkHost = ${v.verifyHostname}"}
+               OCSPaia = yes
+
+             '')
+           cfg.clients)
+      }
+    '';
+
+    systemd.services.stunnel = {
+      description = "stunnel TLS tunneling service";
+      after = [ "network.target" ];
+      wants = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+      restartTriggers = [ config.environment.etc."stunnel.cfg".source ];
+      serviceConfig = {
+        ExecStart = "${pkgs.stunnel}/bin/stunnel ${config.environment.etc."stunnel.cfg".source}";
+        Type = "forking";
+      };
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/web-servers/mighttpd2.nix b/nixos/modules/services/web-servers/mighttpd2.nix
new file mode 100644
index 000000000000..a888f623616e
--- /dev/null
+++ b/nixos/modules/services/web-servers/mighttpd2.nix
@@ -0,0 +1,132 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.mighttpd2;
+  configFile = pkgs.writeText "mighty-config" cfg.config;
+  routingFile = pkgs.writeText "mighty-routing" cfg.routing;
+in {
+  options.services.mighttpd2 = {
+    enable = mkEnableOption "Mighttpd2 web server";
+
+    config = mkOption {
+      default = "";
+      example = ''
+        # Example configuration for Mighttpd 2
+        Port: 80
+        # IP address or "*"
+        Host: *
+        Debug_Mode: Yes # Yes or No
+        # If available, "nobody" is much more secure for User:.
+        User: root
+        # If available, "nobody" is much more secure for Group:.
+        Group: root
+        Pid_File: /var/run/mighty.pid
+        Logging: Yes # Yes or No
+        Log_File: /var/log/mighty # The directory must be writable by User:
+        Log_File_Size: 16777216 # bytes
+        Log_Backup_Number: 10
+        Index_File: index.html
+        Index_Cgi: index.cgi
+        Status_File_Dir: /usr/local/share/mighty/status
+        Connection_Timeout: 30 # seconds
+        Fd_Cache_Duration: 10 # seconds
+        # Server_Name: Mighttpd/3.x.y
+        Tls_Port: 443
+        Tls_Cert_File: cert.pem # should change this with an absolute path
+        # should change this with comma-separated absolute paths
+        Tls_Chain_Files: chain.pem
+        # Currently, Tls_Key_File must not be encrypted.
+        Tls_Key_File: privkey.pem # should change this with an absolute path
+        Service: 0 # 0 is HTTP only, 1 is HTTPS only, 2 is both
+      '';
+      type = types.lines;
+      description = ''
+        Verbatim config file to use
+        (see http://www.mew.org/~kazu/proj/mighttpd/en/config.html)
+      '';
+    };
+
+    routing = mkOption {
+      default = "";
+      example = ''
+        # Example routing for Mighttpd 2
+
+        # Domain lists
+        [localhost www.example.com]
+
+        # Entries are looked up in the specified order
+        # All paths must end with "/"
+
+        # A path to CGI scripts should be specified with "=>"
+        /~alice/cgi-bin/ => /home/alice/public_html/cgi-bin/
+
+        # A path to static files should be specified with "->"
+        /~alice/         -> /home/alice/public_html/
+        /cgi-bin/        => /export/cgi-bin/
+
+        # Reverse proxy rules should be specified with ">>"
+        # /path >> host:port/path2
+        # Either "host" or ":port" can be committed, but not both.
+        /app/cal/        >> example.net/calendar/
+        # Yesod app in the same server
+        /app/wiki/       >> 127.0.0.1:3000/
+
+        /                -> /export/www/
+      '';
+      type = types.lines;
+      description = ''
+        Verbatim routing file to use
+        (see http://www.mew.org/~kazu/proj/mighttpd/en/config.html)
+      '';
+    };
+
+    cores = mkOption {
+      default = null;
+      type = types.nullOr types.int;
+      description = ''
+        How many cores to use.
+        If null it will be determined automatically
+      '';
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+    assertions =
+      [ { assertion = cfg.routing != "";
+          message = "You need at least one rule in mighttpd2.routing";
+        }
+      ];
+    systemd.services.mighttpd2 = {
+      description = "Mighttpd2 web server";
+      after = [ "network-online.target" ];
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        ExecStart = ''
+          ${pkgs.haskellPackages.mighttpd2}/bin/mighty \
+            ${configFile} \
+            ${routingFile} \
+            +RTS -N${optionalString (cfg.cores != null) "${cfg.cores}"}
+        '';
+        Type = "simple";
+        User = "mighttpd2";
+        Group = "mighttpd2";
+        Restart = "on-failure";
+        AmbientCapabilities = "cap_net_bind_service";
+        CapabilityBoundingSet = "cap_net_bind_service";
+      };
+    };
+
+    users.extraUsers.mighttpd2 = {
+      group = "mighttpd2";
+      uid = config.ids.uids.mighttpd2;
+      isSystemUser = true;
+    };
+
+    users.extraGroups.mighttpd2.gid = config.ids.gids.mighttpd2;
+  };
+
+  meta.maintainers = with lib.maintainers; [ fgaz ];
+}
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index 2951e63e863e..100fabf902f8 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -15,6 +15,9 @@ let
     } // (optionalAttrs vhostConfig.enableACME {
       sslCertificate = "/var/lib/acme/${serverName}/fullchain.pem";
       sslCertificateKey = "/var/lib/acme/${serverName}/key.pem";
+    }) // (optionalAttrs (vhostConfig.useACMEHost != null) {
+      sslCertificate = "/var/lib/acme/${vhostConfig.useACMEHost}/fullchain.pem";
+      sslCertificateKey = "/var/lib/acme/${vhostConfig.useACMEHost}/key.pem";
     })
   ) cfg.virtualHosts;
   enableIPv6 = config.networking.enableIPv6;
@@ -174,7 +177,7 @@ let
 
         redirectListen = filter (x: !x.ssl) defaultListen;
 
-        acmeLocation = ''
+        acmeLocation = optionalString (vhost.enableACME || vhost.useACMEHost != null) ''
           location /.well-known/acme-challenge {
             ${optionalString (vhost.acmeFallbackHost != null) "try_files $uri @acme-fallback;"}
             root ${vhost.acmeRoot};
@@ -194,7 +197,7 @@ let
             ${concatMapStringsSep "\n" listenString redirectListen}
 
             server_name ${vhost.serverName} ${concatStringsSep " " vhost.serverAliases};
-            ${optionalString vhost.enableACME acmeLocation}
+            ${acmeLocation}
             location / {
               return 301 https://$host$request_uri;
             }
@@ -204,7 +207,7 @@ let
         server {
           ${concatMapStringsSep "\n" listenString hostListen}
           server_name ${vhost.serverName} ${concatStringsSep " " vhost.serverAliases};
-          ${optionalString vhost.enableACME acmeLocation}
+          ${acmeLocation}
           ${optionalString (vhost.root != null) "root ${vhost.root};"}
           ${optionalString (vhost.globalRedirect != null) ''
             return 301 http${optionalString hasSSL "s"}://${vhost.globalRedirect}$request_uri;
@@ -555,6 +558,14 @@ in
           are mutually exclusive.
         '';
       }
+
+      {
+        assertion = all (conf: !(conf.enableACME && conf.useACMEHost != null)) (attrValues virtualHosts);
+        message = ''
+          Options services.nginx.service.virtualHosts.<name>.enableACME and
+          services.nginx.virtualHosts.<name>.useACMEHost are mutually exclusive.
+        '';
+      }
     ];
 
     systemd.services.nginx = {
@@ -580,7 +591,7 @@ in
     security.acme.certs = filterAttrs (n: v: v != {}) (
       let
         vhostsConfigs = mapAttrsToList (vhostName: vhostConfig: vhostConfig) virtualHosts;
-        acmeEnabledVhosts = filter (vhostConfig: vhostConfig.enableACME) vhostsConfigs;
+        acmeEnabledVhosts = filter (vhostConfig: vhostConfig.enableACME && vhostConfig.useACMEHost == null) vhostsConfigs;
         acmePairs = map (vhostConfig: { name = vhostConfig.serverName; value = {
             user = cfg.user;
             group = lib.mkDefault cfg.group;
diff --git a/nixos/modules/services/web-servers/nginx/vhost-options.nix b/nixos/modules/services/web-servers/nginx/vhost-options.nix
index 29f08cc4f307..bf18108a1a3c 100644
--- a/nixos/modules/services/web-servers/nginx/vhost-options.nix
+++ b/nixos/modules/services/web-servers/nginx/vhost-options.nix
@@ -48,7 +48,21 @@ with lib;
     enableACME = mkOption {
       type = types.bool;
       default = false;
-      description = "Whether to ask Let's Encrypt to sign a certificate for this vhost.";
+      description = ''
+        Whether to ask Let's Encrypt to sign a certificate for this vhost.
+        Alternately, you can use an existing certificate through <option>useACMEHost</option>.
+      '';
+    };
+
+    useACMEHost = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        A host of an existing Let's Encrypt certificate to use.
+        This is useful if you have many subdomains and want to avoid hitting the
+        <link xlink:href="https://letsencrypt.org/docs/rate-limits/">rate limit</link>.
+        Alternately, you can generate a certificate through <option>enableACME</option>.
+      '';
     };
 
     acmeRoot = mkOption {
diff --git a/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixos/modules/services/x11/desktop-managers/plasma5.nix
index 17a2cde3a65d..4c76ce0bb195 100644
--- a/nixos/modules/services/x11/desktop-managers/plasma5.nix
+++ b/nixos/modules/services/x11/desktop-managers/plasma5.nix
@@ -47,6 +47,18 @@ in
             ${getBin config.hardware.pulseaudio.package}/bin/pactl load-module module-device-manager "do_routing=1"
           ''}
 
+          if [ -f "$HOME/.config/kdeglobals" ]
+          then
+              # Remove extraneous font style names.
+              # See also: https://phabricator.kde.org/D9070
+              ${getBin pkgs.gnused}/bin/sed -i "$HOME/.config/kdeglobals" \
+                  -e '/^fixed=/ s/,Regular$//' \
+                  -e '/^font=/ s/,Regular$//' \
+                  -e '/^menuFont=/ s/,Regular$//' \
+                  -e '/^smallestReadableFont=/ s/,Regular$//' \
+                  -e '/^toolBarFont=/ s/,Regular$//'
+          fi
+
           exec "${getBin plasma5.plasma-workspace}/bin/startkde"
         '';
       };
diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix
index 9d5d03638e04..c0c9d7ea47f7 100644
--- a/nixos/modules/services/x11/desktop-managers/xfce.nix
+++ b/nixos/modules/services/x11/desktop-managers/xfce.nix
@@ -3,9 +3,7 @@
 with lib;
 
 let
-  xcfg = config.services.xserver;
-  pcfg = config.hardware.pulseaudio;
-  cfg = xcfg.desktopManager.xfce;
+  cfg = config.services.xserver.desktopManager.xfce;
 in
 
 {
@@ -52,82 +50,93 @@ in
         description = "Application used by XFCE to lock the screen.";
       };
     };
-
   };
 
+  config = mkIf cfg.enable {
+    environment.systemPackages = with pkgs.xfce // pkgs; [
+      # Get GTK+ themes and gtk-update-icon-cache
+      gtk2.out
+
+      # Supplies some abstract icons such as:
+      # utilities-terminal, accessories-text-editor
+      gnome3.defaultIconTheme
+
+      hicolor_icon_theme
+      tango-icon-theme
+      xfce4-icon-theme
+
+      desktop_file_utils
+      shared_mime_info
+
+      # Needed by Xfce's xinitrc script
+      # TODO: replace with command -v
+      which
+
+      exo
+      garcon
+      gtk-xfce-engine
+      gvfs
+      libxfce4ui
+      tumbler
+      xfconf
+
+      mousepad
+      ristretto
+      xfce4-appfinder
+      xfce4-screenshooter
+      xfce4-session
+      xfce4-settings
+      xfce4-terminal
+
+      (thunar.override { thunarPlugins = cfg.thunarPlugins; })
+      thunar-volman # TODO: drop
+    ] ++ (if config.hardware.pulseaudio.enable
+          then [ xfce4-mixer-pulse xfce4-volumed-pulse ]
+	  else [ xfce4-mixer xfce4-volumed ])
+      # TODO: NetworkManager doesn't belong here
+      ++ optionals config.networking.networkmanager.enable [ networkmanagerapplet ]
+      ++ optionals config.powerManagement.enable [ xfce4-power-manager ]
+      ++ optionals cfg.enableXfwm [ xfwm4 ]
+      ++ optionals (!cfg.noDesktop) [
+        xfce4-panel
+        xfce4-notifyd
+        xfdesktop
+      ];
+
+    environment.pathsToLink = [
+      "/share/xfce4"
+      "/share/themes"
+      "/share/mime"
+      "/share/desktop-directories"
+      "/share/gtksourceview-2.0"
+    ];
+
+    environment.variables = {
+      GDK_PIXBUF_MODULE_FILE = "${pkgs.librsvg.out}/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache";
+      GIO_EXTRA_MODULES = [ "${pkgs.xfce.gvfs}/lib/gio/modules" ];
+    };
 
-  config = mkIf (xcfg.enable && cfg.enable) {
-
-    services.xserver.desktopManager.session = singleton
-      { name = "xfce";
-        bgSupport = true;
-        start =
-          ''
-            ${cfg.extraSessionCommands}
+    services.xserver.desktopManager.session = [{
+      name = "xfce";
+      bgSupport = true;
+      start = ''
+        ${cfg.extraSessionCommands}
 
-            # Set GTK_PATH so that GTK+ can find the theme engines.
-            export GTK_PATH="${config.system.path}/lib/gtk-2.0:${config.system.path}/lib/gtk-3.0"
+        # Set GTK_PATH so that GTK+ can find the theme engines.
+        export GTK_PATH="${config.system.path}/lib/gtk-2.0:${config.system.path}/lib/gtk-3.0"
 
-            # Set GTK_DATA_PREFIX so that GTK+ can find the Xfce themes.
-            export GTK_DATA_PREFIX=${config.system.path}
+        # Set GTK_DATA_PREFIX so that GTK+ can find the Xfce themes.
+        export GTK_DATA_PREFIX=${config.system.path}
 
-            ${pkgs.stdenv.shell} ${pkgs.xfce.xinitrc} &
-            waitPID=$!
-          '';
-      };
+        ${pkgs.stdenv.shell} ${pkgs.xfce.xinitrc} &
+        waitPID=$!
+      '';
+    }];
 
     services.xserver.updateDbusEnvironment = true;
 
-    environment.systemPackages =
-      [ pkgs.gtk2.out # To get GTK+'s themes and gtk-update-icon-cache
-        pkgs.hicolor_icon_theme
-        pkgs.tango-icon-theme
-        pkgs.shared_mime_info
-        pkgs.which # Needed by the xfce's xinitrc script.
-        pkgs."${cfg.screenLock}"
-        pkgs.xfce.exo
-        pkgs.xfce.gtk_xfce_engine
-        pkgs.xfce.mousepad
-        pkgs.xfce.ristretto
-        pkgs.xfce.terminal
-       (pkgs.xfce.thunar.override { thunarPlugins = cfg.thunarPlugins; })
-        pkgs.xfce.xfce4icontheme
-        pkgs.xfce.xfce4session
-        pkgs.xfce.xfce4settings
-       (if pcfg.enable then pkgs.xfce.xfce4mixer_pulse else pkgs.xfce.xfce4mixer)
-       (if pcfg.enable then pkgs.xfce.xfce4volumed_pulse else pkgs.xfce.xfce4volumed)
-        pkgs.xfce.xfce4-screenshooter
-        pkgs.xfce.xfconf
-        # This supplies some "abstract" icons such as
-        # "utilities-terminal" and "accessories-text-editor".
-        pkgs.gnome3.defaultIconTheme
-        pkgs.desktop_file_utils
-        pkgs.xfce.libxfce4ui
-        pkgs.xfce.garcon
-        pkgs.xfce.thunar_volman
-        pkgs.xfce.gvfs
-        pkgs.xfce.xfce4_appfinder
-        pkgs.xfce.tumbler       # found via dbus
-      ]
-      ++ optional cfg.enableXfwm pkgs.xfce.xfwm4
-      ++ optional config.powerManagement.enable pkgs.xfce.xfce4_power_manager
-      ++ optional config.networking.networkmanager.enable pkgs.networkmanagerapplet
-      ++ optionals (!cfg.noDesktop)
-         [ pkgs.xfce.xfce4panel
-           pkgs.xfce.xfdesktop
-	   pkgs.xfce.xfce4notifyd  # found via dbus
-         ];
-
-    environment.pathsToLink =
-      [ "/share/xfce4" "/share/themes" "/share/mime" "/share/desktop-directories" "/share/gtksourceview-2.0" ];
-
-    environment.variables.GIO_EXTRA_MODULES = [ "${pkgs.xfce.gvfs}/lib/gio/modules" ];
-    environment.variables.GDK_PIXBUF_MODULE_FILE = "${pkgs.librsvg.out}/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache";
-
     # Enable helpful DBus services.
     services.udisks2.enable = true;
     services.upower.enable = config.powerManagement.enable;
-
   };
-
 }
diff --git a/nixos/modules/services/x11/window-managers/2bwm.nix b/nixos/modules/services/x11/window-managers/2bwm.nix
index e3f5ec7dbe67..fdbdf35b0f5a 100644
--- a/nixos/modules/services/x11/window-managers/2bwm.nix
+++ b/nixos/modules/services/x11/window-managers/2bwm.nix
@@ -25,12 +25,12 @@ in
       { name = "2bwm";
         start =
           ''
-            ${pkgs."2bwm"}/bin/2bwm &
+            ${pkgs._2bwm}/bin/2bwm &
             waitPID=$!
           '';
       };
 
-    environment.systemPackages = [ pkgs."2bwm" ];
+    environment.systemPackages = [ pkgs._2bwm ];
 
   };
 
diff --git a/nixos/modules/system/boot/initrd-network.nix b/nixos/modules/system/boot/initrd-network.nix
index 6e226c190609..4a6e1c7e56e5 100644
--- a/nixos/modules/system/boot/initrd-network.nix
+++ b/nixos/modules/system/boot/initrd-network.nix
@@ -40,6 +40,10 @@ in
         kernel documentation</link>.  Otherwise, if
         <option>networking.useDHCP</option> is enabled, an IP address
         is acquired using DHCP.
+
+        You should add the module(s) required for your network card to
+        boot.initrd.availableKernelModules. lspci -v -s &lt;ethernet controller&gt;
+        will tell you which.
       '';
     };
 
diff --git a/nixos/modules/system/boot/kernel.nix b/nixos/modules/system/boot/kernel.nix
index 90074a1ba77b..d21908f84537 100644
--- a/nixos/modules/system/boot/kernel.nix
+++ b/nixos/modules/system/boot/kernel.nix
@@ -206,12 +206,14 @@ in
         "xhci_hcd"
         "xhci_pci"
         "usbhid"
-        "hid_generic" "hid_lenovo" "hid_apple" "hid_roccat" "hid_logitech_hidpp"
+        "hid_generic" "hid_lenovo" "hid_apple" "hid_roccat"
+        "hid_logitech_hidpp" "hid_logitech_dj"
 
-        # Misc. keyboard stuff.
+      ] ++ optionals (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) [
+        # Misc. x86 keyboard stuff.
         "pcips2" "atkbd" "i8042"
 
-        # Needed by the stage 2 init script.
+        # x86 RTC needed by the stage 2 init script.
         "rtc_cmos"
       ];
 
diff --git a/nixos/modules/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix
index 1f424f84c6e0..63d07832d105 100644
--- a/nixos/modules/tasks/network-interfaces-scripted.nix
+++ b/nixos/modules/tasks/network-interfaces-scripted.nix
@@ -230,9 +230,7 @@ let
               RemainAfterExit = true;
             };
             script = ''
-              ip tuntap add dev "${i.name}" \
-              ${optionalString (i.virtualType != null) "mode ${i.virtualType}"} \
-              user "${i.virtualOwner}"
+              ip tuntap add dev "${i.name}" mode "${i.virtualType}" user "${i.virtualOwner}"
             '';
             postStop = ''
               ip link del ${i.name} || true
diff --git a/nixos/modules/tasks/network-interfaces-systemd.nix b/nixos/modules/tasks/network-interfaces-systemd.nix
index a365a01bfb1e..5d72ad0f1bde 100644
--- a/nixos/modules/tasks/network-interfaces-systemd.nix
+++ b/nixos/modules/tasks/network-interfaces-systemd.nix
@@ -74,21 +74,17 @@ in
         networks."99-main" = genericNetwork mkDefault;
       }
       (mkMerge (flip map interfaces (i: {
-        netdevs = mkIf i.virtual (
-          let
-            devType = if i.virtualType != null then i.virtualType
-              else (if hasPrefix "tun" i.name then "tun" else "tap");
-          in {
-            "40-${i.name}" = {
-              netdevConfig = {
-                Name = i.name;
-                Kind = devType;
-              };
-              "${devType}Config" = optionalAttrs (i.virtualOwner != null) {
-                User = i.virtualOwner;
-              };
+        netdevs = mkIf i.virtual ({
+          "40-${i.name}" = {
+            netdevConfig = {
+              Name = i.name;
+              Kind = i.virtualType;
             };
-          });
+            "${i.virtualType}Config" = optionalAttrs (i.virtualOwner != null) {
+              User = i.virtualOwner;
+            };
+          };
+        });
         networks."40-${i.name}" = mkMerge [ (genericNetwork mkDefault) {
           name = mkDefault i.name;
           DHCP = mkForce (dhcpStr
diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix
index b7e85e402aa9..f4851988d63d 100644
--- a/nixos/modules/tasks/network-interfaces.nix
+++ b/nixos/modules/tasks/network-interfaces.nix
@@ -273,11 +273,13 @@ let
       };
 
       virtualType = mkOption {
-        default = null;
-        type = with types; nullOr (enum [ "tun" "tap" ]);
+        default = if hasPrefix "tun" name then "tun" else "tap";
+        defaultText = literalExample ''if hasPrefix "tun" name then "tun" else "tap"'';
+        type = with types; enum [ "tun" "tap" ];
         description = ''
-          The explicit type of interface to create. Accepts tun or tap strings.
-          Also accepts null to implicitly detect the type of device.
+          The type of interface to create.
+          The default is TUN for an interface name starting
+          with "tun", otherwise TAP.
         '';
       };
 
diff --git a/nixos/modules/testing/test-instrumentation.nix b/nixos/modules/testing/test-instrumentation.nix
index 9b4136223c0f..41dec2af9ed4 100644
--- a/nixos/modules/testing/test-instrumentation.nix
+++ b/nixos/modules/testing/test-instrumentation.nix
@@ -4,13 +4,10 @@
 { config, lib, pkgs, ... }:
 
 with lib;
+with import ../../lib/qemu-flags.nix { inherit pkgs; };
 
 let
   kernel = config.boot.kernelPackages.kernel;
-  # FIXME: figure out a common place for this instead of copy pasting
-  serialDevice = if pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64 then "ttyS0"
-        else if pkgs.stdenv.isArm || pkgs.stdenv.isAarch64 then "ttyAMA0"
-        else throw "Unknown QEMU serial device for system '${pkgs.stdenv.system}'";
 in
 
 {
@@ -28,8 +25,8 @@ in
 
     systemd.services.backdoor =
       { wantedBy = [ "multi-user.target" ];
-        requires = [ "dev-hvc0.device" "dev-${serialDevice}.device" ];
-        after = [ "dev-hvc0.device" "dev-${serialDevice}.device" ];
+        requires = [ "dev-hvc0.device" "dev-${qemuSerialDevice}.device" ];
+        after = [ "dev-hvc0.device" "dev-${qemuSerialDevice}.device" ];
         script =
           ''
             export USER=root
@@ -46,7 +43,7 @@ in
 
             cd /tmp
             exec < /dev/hvc0 > /dev/hvc0
-            while ! exec 2> /dev/${serialDevice}; do sleep 0.1; done
+            while ! exec 2> /dev/${qemuSerialDevice}; do sleep 0.1; done
             echo "connecting to host..." >&2
             stty -F /dev/hvc0 raw -echo # prevent nl -> cr/nl conversion
             echo
@@ -55,10 +52,10 @@ in
         serviceConfig.KillSignal = "SIGHUP";
       };
 
-    # Prevent agetty from being instantiated on ${serialDevice}, since it
-    # interferes with the backdoor (writes to ${serialDevice} will randomly fail
+    # Prevent agetty from being instantiated on the serial device, since it
+    # interferes with the backdoor (writes to it will randomly fail
     # with EIO).  Likewise for hvc0.
-    systemd.services."serial-getty@${serialDevice}".enable = false;
+    systemd.services."serial-getty@${qemuSerialDevice}".enable = false;
     systemd.services."serial-getty@hvc0".enable = false;
 
     boot.initrd.preDeviceCommands =
@@ -94,7 +91,7 @@ in
     # Panic if an error occurs in stage 1 (rather than waiting for
     # user intervention).
     boot.kernelParams =
-      [ "console=${serialDevice}" "panic=1" "boot.panic_on_fail" ];
+      [ "console=${qemuSerialDevice}" "panic=1" "boot.panic_on_fail" ];
 
     # `xwininfo' is used by the test driver to query open windows.
     environment.systemPackages = [ pkgs.xorg.xwininfo ];
diff --git a/nixos/modules/virtualisation/container-config.nix b/nixos/modules/virtualisation/container-config.nix
index b4f9d8b6fc17..5e368acd6d8b 100644
--- a/nixos/modules/virtualisation/container-config.nix
+++ b/nixos/modules/virtualisation/container-config.nix
@@ -11,7 +11,7 @@ with lib;
     services.udisks2.enable = mkDefault false;
     powerManagement.enable = mkDefault false;
 
-    networking.useHostResolvConf = true;
+    networking.useHostResolvConf = mkDefault true;
 
     # Containers should be light-weight, so start sshd on demand.
     services.openssh.startWhenNeeded = mkDefault true;
diff --git a/nixos/modules/virtualisation/google-compute-image.nix b/nixos/modules/virtualisation/google-compute-image.nix
index 75717e08ab2a..2fb38059b261 100644
--- a/nixos/modules/virtualisation/google-compute-image.nix
+++ b/nixos/modules/virtualisation/google-compute-image.nix
@@ -212,7 +212,7 @@ in
           echo "Obtaining SSH keys..."
           mkdir -m 0700 -p /root/.ssh
           AUTH_KEYS=$(${mktemp})
-          ${wget} -O $AUTH_KEYS http://metadata.google.internal/computeMetadata/v1/project/attributes/sshKeys
+          ${wget} -O $AUTH_KEYS --header="Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/attributes/sshKeys
           if [ -s $AUTH_KEYS ]; then
 
             # Read in key one by one, split in case Google decided
diff --git a/nixos/modules/virtualisation/libvirtd.nix b/nixos/modules/virtualisation/libvirtd.nix
index 64465ae18522..a369b7ddbe1d 100644
--- a/nixos/modules/virtualisation/libvirtd.nix
+++ b/nixos/modules/virtualisation/libvirtd.nix
@@ -128,6 +128,7 @@ in {
           dmidecode
           dnsmasq
           ebtables
+          cfg.qemuPackage # libvirtd requires qemu-img to manage disk images
         ]
         ++ optional vswitch.enable vswitch.package;
 
diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix
index 26f7945a4eda..13d0eb7de5c2 100644
--- a/nixos/modules/virtualisation/qemu-vm.nix
+++ b/nixos/modules/virtualisation/qemu-vm.nix
@@ -10,21 +10,11 @@
 { config, lib, pkgs, ... }:
 
 with lib;
+with import ../../lib/qemu-flags.nix { inherit pkgs; };
 
 let
 
   qemu = config.system.build.qemu or pkgs.qemu_test;
-  qemuKvm = {
-    "i686-linux" = "${qemu}/bin/qemu-kvm";
-    "x86_64-linux" = "${qemu}/bin/qemu-kvm -cpu kvm64";
-    "armv7l-linux" = "${qemu}/bin/qemu-system-arm -enable-kvm -machine virt -cpu host";
-    "aarch64-linux" = "${qemu}/bin/qemu-system-aarch64 -enable-kvm -machine virt,gic-version=host -cpu host";
-  }.${pkgs.stdenv.system};
-
-  # FIXME: figure out a common place for this instead of copy pasting
-  serialDevice = if pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64 then "ttyS0"
-        else if pkgs.stdenv.isArm || pkgs.stdenv.isAarch64 then "ttyAMA0"
-        else throw "Unknown QEMU serial device for system '${pkgs.stdenv.system}'";
 
   vmName =
     if config.networking.hostName == ""
@@ -34,7 +24,7 @@ let
   cfg = config.virtualisation;
 
   qemuGraphics = if cfg.graphics then "" else "-nographic";
-  kernelConsole = if cfg.graphics then "" else "console=${serialDevice}";
+  kernelConsole = if cfg.graphics then "" else "console=${qemuSerialDevice}";
   ttys = [ "tty1" "tty2" "tty3" "tty4" "tty5" "tty6" ];
 
   # Shell script to start the VM.
@@ -83,7 +73,7 @@ let
       '')}
 
       # Start QEMU.
-      exec ${qemuKvm} \
+      exec ${qemuBinary qemu} \
           -name ${vmName} \
           -m ${toString config.virtualisation.memorySize} \
           -smp ${toString config.virtualisation.cores} \
diff --git a/nixos/modules/virtualisation/virtualbox-image.nix b/nixos/modules/virtualisation/virtualbox-image.nix
index 00381c426d23..a544403e6bed 100644
--- a/nixos/modules/virtualisation/virtualbox-image.nix
+++ b/nixos/modules/virtualisation/virtualbox-image.nix
@@ -25,7 +25,7 @@ in {
       name = "nixos-ova-${config.system.nixosLabel}-${pkgs.stdenv.system}";
 
       inherit pkgs lib config;
-      partitioned = true;
+      partitionTableType = "legacy";
       diskSize = cfg.baseImageSize;
 
       postVM =