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/hardware/opengl.nix4
-rw-r--r--nixos/modules/hardware/video/nvidia.nix2
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix2
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix2
-rw-r--r--nixos/modules/installer/cd-dvd/sd-image-aarch64.nix20
-rw-r--r--nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix15
-rw-r--r--nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix15
-rw-r--r--nixos/modules/installer/cd-dvd/sd-image.nix94
-rw-r--r--nixos/modules/installer/tools/nixos-generate-config.pl28
-rw-r--r--nixos/modules/misc/documentation.nix8
-rw-r--r--nixos/modules/misc/ids.nix4
-rw-r--r--nixos/modules/misc/nixops-autoluks.nix1
-rw-r--r--nixos/modules/misc/version.nix2
-rw-r--r--nixos/modules/module-list.nix1
-rw-r--r--nixos/modules/rename.nix1
-rw-r--r--nixos/modules/services/audio/mopidy.nix10
-rw-r--r--nixos/modules/services/audio/slimserver.nix6
-rw-r--r--nixos/modules/services/audio/snapserver.nix1
-rw-r--r--nixos/modules/services/backup/duplicati.nix16
-rw-r--r--nixos/modules/services/cluster/kubernetes/default.nix7
-rw-r--r--nixos/modules/services/cluster/kubernetes/kubelet.nix7
-rw-r--r--nixos/modules/services/cluster/kubernetes/pki.nix1
-rw-r--r--nixos/modules/services/computing/boinc/client.nix9
-rw-r--r--nixos/modules/services/databases/cassandra.nix2
-rw-r--r--nixos/modules/services/databases/firebird.nix14
-rw-r--r--nixos/modules/services/databases/foundationdb.nix22
-rw-r--r--nixos/modules/services/databases/foundationdb.xml38
-rw-r--r--nixos/modules/services/databases/hbase.nix17
-rw-r--r--nixos/modules/services/databases/mysql.nix16
-rw-r--r--nixos/modules/services/databases/postgresql.xml4
-rw-r--r--nixos/modules/services/desktops/deepin/deepin.nix2
-rw-r--r--nixos/modules/services/desktops/flatpak.xml22
-rw-r--r--nixos/modules/services/editors/emacs.xml10
-rw-r--r--nixos/modules/services/hardware/triggerhappy.nix2
-rw-r--r--nixos/modules/services/hardware/udev.nix2
-rw-r--r--nixos/modules/services/logging/graylog.nix12
-rw-r--r--nixos/modules/services/logging/heartbeat.nix6
-rw-r--r--nixos/modules/services/mail/dspam.nix13
-rw-r--r--nixos/modules/services/mail/opendkim.nix7
-rw-r--r--nixos/modules/services/mail/rspamd.nix1
-rw-r--r--nixos/modules/services/misc/apache-kafka.nix9
-rw-r--r--nixos/modules/services/misc/couchpotato.nix7
-rw-r--r--nixos/modules/services/misc/gitea.nix17
-rw-r--r--nixos/modules/services/misc/gitlab.xml12
-rw-r--r--nixos/modules/services/misc/gollum.nix15
-rw-r--r--nixos/modules/services/misc/lidarr.nix9
-rw-r--r--nixos/modules/services/misc/nix-daemon.nix5
-rw-r--r--nixos/modules/services/misc/octoprint.nix7
-rw-r--r--nixos/modules/services/misc/taskserver/doc.xml2
-rw-r--r--nixos/modules/services/misc/zoneminder.nix23
-rw-r--r--nixos/modules/services/monitoring/alerta.nix11
-rw-r--r--nixos/modules/services/monitoring/grafana-reporter.nix2
-rw-r--r--nixos/modules/services/monitoring/kapacitor.nix11
-rw-r--r--nixos/modules/services/monitoring/netdata.nix1
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters.xml110
-rw-r--r--nixos/modules/services/monitoring/prometheus/exporters/node.nix3
-rw-r--r--nixos/modules/services/monitoring/riemann-dash.nix8
-rw-r--r--nixos/modules/services/monitoring/riemann-tools.nix1
-rw-r--r--nixos/modules/services/monitoring/scollector.nix1
-rw-r--r--nixos/modules/services/network-filesystems/samba.nix8
-rw-r--r--nixos/modules/services/networking/aria2.nix14
-rw-r--r--nixos/modules/services/networking/autossh.nix1
-rw-r--r--nixos/modules/services/networking/avahi-daemon.nix344
-rw-r--r--nixos/modules/services/networking/bitcoind.nix2
-rw-r--r--nixos/modules/services/networking/charybdis.nix9
-rw-r--r--nixos/modules/services/networking/ddclient.nix2
-rw-r--r--nixos/modules/services/networking/dnscrypt-proxy.xml8
-rw-r--r--nixos/modules/services/networking/hostapd.nix14
-rw-r--r--nixos/modules/services/networking/minidlna.nix8
-rw-r--r--nixos/modules/services/networking/quassel.nix10
-rw-r--r--nixos/modules/services/networking/smokeping.nix22
-rw-r--r--nixos/modules/services/networking/squid.nix3
-rw-r--r--nixos/modules/services/networking/teamspeak3.nix10
-rw-r--r--nixos/modules/services/networking/unifi.nix11
-rw-r--r--nixos/modules/services/networking/zeronet.nix13
-rw-r--r--nixos/modules/services/system/kerberos/default.nix2
-rw-r--r--nixos/modules/services/system/kerberos/heimdal.nix2
-rw-r--r--nixos/modules/services/system/kerberos/mit.nix2
-rw-r--r--nixos/modules/services/system/localtime.nix31
-rw-r--r--nixos/modules/services/web-apps/atlassian/confluence.nix18
-rw-r--r--nixos/modules/services/web-apps/atlassian/crowd.nix17
-rw-r--r--nixos/modules/services/web-apps/atlassian/jira.nix18
-rw-r--r--nixos/modules/services/web-apps/frab.nix10
-rw-r--r--nixos/modules/services/web-apps/limesurvey.nix2
-rw-r--r--nixos/modules/services/web-apps/matomo-doc.xml22
-rw-r--r--nixos/modules/services/web-apps/nextcloud.nix2
-rw-r--r--nixos/modules/services/web-apps/tt-rss.nix1
-rw-r--r--nixos/modules/services/web-servers/lighttpd/cgit.nix4
-rw-r--r--nixos/modules/services/web-servers/nginx/default.nix11
-rw-r--r--nixos/modules/services/x11/desktop-managers/enlightenment.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/pantheon.nix2
-rw-r--r--nixos/modules/services/x11/desktop-managers/xterm.nix4
-rw-r--r--nixos/modules/services/x11/xserver.nix2
-rw-r--r--nixos/modules/system/boot/kernel.nix2
-rw-r--r--nixos/modules/system/boot/kernel_config.nix1
-rw-r--r--nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py4
-rw-r--r--nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix12
-rw-r--r--nixos/modules/tasks/filesystems/zfs.nix4
-rw-r--r--nixos/modules/virtualisation/anbox.nix7
-rw-r--r--nixos/modules/virtualisation/cloudstack-config.nix2
-rw-r--r--nixos/modules/virtualisation/containers.nix2
-rw-r--r--nixos/modules/virtualisation/docker-containers.nix2
-rw-r--r--nixos/modules/virtualisation/google-compute-config.nix1
-rw-r--r--nixos/modules/virtualisation/kvmgt.nix18
-rw-r--r--nixos/modules/virtualisation/libvirtd.nix104
105 files changed, 777 insertions, 713 deletions
diff --git a/nixos/modules/hardware/opengl.nix b/nixos/modules/hardware/opengl.nix
index 6b7b8069fd4..2defab51bc3 100644
--- a/nixos/modules/hardware/opengl.nix
+++ b/nixos/modules/hardware/opengl.nix
@@ -11,9 +11,9 @@ let
   videoDrivers = config.services.xserver.videoDrivers;
 
   makePackage = p: pkgs.buildEnv {
-    name = "mesa-drivers+txc-${p.mesa_drivers.version}";
+    name = "mesa-drivers+txc-${p.mesa.version}";
     paths =
-      [ p.mesa_drivers
+      [ p.mesa.drivers
         (if cfg.s3tcSupport then p.libtxc_dxtn else p.libtxc_dxtn_s2tc)
       ];
   };
diff --git a/nixos/modules/hardware/video/nvidia.nix b/nixos/modules/hardware/video/nvidia.nix
index 9f2360f41c6..a5740929a31 100644
--- a/nixos/modules/hardware/video/nvidia.nix
+++ b/nixos/modules/hardware/video/nvidia.nix
@@ -1,6 +1,6 @@
 # This module provides the proprietary NVIDIA X11 / OpenGL drivers.
 
-{ stdenv, config, lib, pkgs, ... }:
+{ config, lib, pkgs, ... }:
 
 with lib;
 
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix b/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix
index 917b3758d38..f65239a5bc0 100644
--- a/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix
+++ b/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix
@@ -1,7 +1,7 @@
 # This module contains the basic configuration for building a graphical NixOS
 # installation CD.
 
-{ config, lib, pkgs, ... }:
+{ lib, pkgs, ... }:
 
 with lib;
 
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix b/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix
index 42b5ec88227..0b813bbf37b 100644
--- a/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix
+++ b/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix
@@ -1,7 +1,7 @@
 # This module defines a NixOS installation CD that contains X11 and
 # GNOME 3.
 
-{ config, lib, pkgs, ... }:
+{ lib, ... }:
 
 with lib;
 
diff --git a/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix b/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix
index 5f7194e92a3..a9241870fa7 100644
--- a/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix
+++ b/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix
@@ -26,8 +26,15 @@ in
   # Also increase the amount of CMA to ensure the virtual console on the RPi3 works.
   boot.kernelParams = ["cma=32M" "console=ttyS0,115200n8" "console=ttyAMA0,115200n8" "console=tty0"];
 
+  boot.initrd.availableKernelModules = [
+    # Allows early (earlier) modesetting for the Raspberry Pi
+    "vc4" "bcm2835_dma" "i2c_bcm2835"
+    # Allows early (earlier) modesetting for Allwinner SoCs
+    "sun4i_drm" "sun8i_drm_hdmi" "sun8i_mixer"
+  ];
+
   sdImage = {
-    populateBootCommands = let
+    populateFirmwareCommands = let
       configTxt = pkgs.writeText "config.txt" ''
         kernel=u-boot-rpi3.bin
 
@@ -43,10 +50,13 @@ in
         avoid_warnings=1
       '';
       in ''
-        (cd ${pkgs.raspberrypifw}/share/raspberrypi/boot && cp bootcode.bin fixup*.dat start*.elf $NIX_BUILD_TOP/boot/)
-        cp ${pkgs.ubootRaspberryPi3_64bit}/u-boot.bin boot/u-boot-rpi3.bin
-        cp ${configTxt} boot/config.txt
-        ${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./boot
+        (cd ${pkgs.raspberrypifw}/share/raspberrypi/boot && cp bootcode.bin fixup*.dat start*.elf $NIX_BUILD_TOP/firmware/)
+        cp ${pkgs.ubootRaspberryPi3_64bit}/u-boot.bin firmware/u-boot-rpi3.bin
+        cp ${configTxt} firmware/config.txt
       '';
+    populateRootCommands = ''
+      mkdir -p ./files/boot
+      ${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./files/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 71448f74c36..dab09241531 100644
--- a/nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix
+++ b/nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix
@@ -29,7 +29,7 @@ in
   boot.kernelParams = ["console=ttyS0,115200n8" "console=ttymxc0,115200n8" "console=ttyAMA0,115200n8" "console=ttyO0,115200n8" "console=ttySAC2,115200n8" "console=tty0"];
 
   sdImage = {
-    populateBootCommands = let
+    populateFirmwareCommands = let
       configTxt = pkgs.writeText "config.txt" ''
         # Prevent the firmware from smashing the framebuffer setup done by the mainline kernel
         # when attempting to show low-voltage or overtemperature warnings.
@@ -46,11 +46,14 @@ in
         enable_uart=1
       '';
       in ''
-        (cd ${pkgs.raspberrypifw}/share/raspberrypi/boot && cp bootcode.bin fixup*.dat start*.elf $NIX_BUILD_TOP/boot/)
-        cp ${pkgs.ubootRaspberryPi2}/u-boot.bin boot/u-boot-rpi2.bin
-        cp ${pkgs.ubootRaspberryPi3_32bit}/u-boot.bin boot/u-boot-rpi3.bin
-        cp ${configTxt} boot/config.txt
-        ${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./boot
+        (cd ${pkgs.raspberrypifw}/share/raspberrypi/boot && cp bootcode.bin fixup*.dat start*.elf $NIX_BUILD_TOP/firmware/)
+        cp ${pkgs.ubootRaspberryPi2}/u-boot.bin firmware/u-boot-rpi2.bin
+        cp ${pkgs.ubootRaspberryPi3_32bit}/u-boot.bin firmware/u-boot-rpi3.bin
+        cp ${configTxt} firmware/config.txt
       '';
+    populateRootCommands = ''
+      mkdir -p ./files/boot
+      ${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./files/boot
+    '';
   };
 }
diff --git a/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix b/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix
index 96e06670694..8c9090471dc 100644
--- a/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix
+++ b/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix
@@ -22,7 +22,7 @@ in
   boot.kernelPackages = pkgs.linuxPackages_rpi;
 
   sdImage = {
-    populateBootCommands = let
+    populateFirmwareCommands = let
       configTxt = pkgs.writeText "config.txt" ''
         # Prevent the firmware from smashing the framebuffer setup done by the mainline kernel
         # when attempting to show low-voltage or overtemperature warnings.
@@ -35,11 +35,14 @@ in
         kernel=u-boot-rpi1.bin
       '';
       in ''
-        (cd ${pkgs.raspberrypifw}/share/raspberrypi/boot && cp bootcode.bin fixup*.dat start*.elf $NIX_BUILD_TOP/boot/)
-        cp ${pkgs.ubootRaspberryPiZero}/u-boot.bin boot/u-boot-rpi0.bin
-        cp ${pkgs.ubootRaspberryPi}/u-boot.bin boot/u-boot-rpi1.bin
-        cp ${configTxt} boot/config.txt
-        ${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./boot
+        (cd ${pkgs.raspberrypifw}/share/raspberrypi/boot && cp bootcode.bin fixup*.dat start*.elf $NIX_BUILD_TOP/firmware/)
+        cp ${pkgs.ubootRaspberryPiZero}/u-boot.bin firmware/u-boot-rpi0.bin
+        cp ${pkgs.ubootRaspberryPi}/u-boot.bin firmware/u-boot-rpi1.bin
+        cp ${configTxt} firmware/config.txt
       '';
+    populateRootCommands = ''
+      mkdir -p ./files/boot
+      ${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./files/boot
+    '';
   };
 }
diff --git a/nixos/modules/installer/cd-dvd/sd-image.nix b/nixos/modules/installer/cd-dvd/sd-image.nix
index 69746a8e979..0c407b19936 100644
--- a/nixos/modules/installer/cd-dvd/sd-image.nix
+++ b/nixos/modules/installer/cd-dvd/sd-image.nix
@@ -1,8 +1,12 @@
 # This module creates a bootable SD card image containing the given NixOS
-# configuration. The generated image is MBR partitioned, with a FAT /boot
-# partition, and ext4 root partition. The generated image is sized to fit
-# its contents, and a boot script automatically resizes the root partition
-# to fit the device on the first boot.
+# configuration. The generated image is MBR partitioned, with a FAT
+# /boot/firmware partition, and ext4 root partition. The generated image
+# is sized to fit its contents, and a boot script automatically resizes
+# the root partition to fit the device on the first boot.
+#
+# The firmware partition is built with expectation to hold the Raspberry
+# Pi firmware and bootloader, and be removed and replaced with a firmware
+# build for the target SoC for other board families.
 #
 # The derivation for the SD image will be placed in
 # config.system.build.sdImage
@@ -14,12 +18,18 @@ with lib;
 let
   rootfsImage = pkgs.callPackage ../../../lib/make-ext4-fs.nix ({
     inherit (config.sdImage) storePaths;
+    populateImageCommands = config.sdImage.populateRootCommands;
     volumeLabel = "NIXOS_SD";
   } // optionalAttrs (config.sdImage.rootPartitionUUID != null) {
     uuid = config.sdImage.rootPartitionUUID;
   });
 in
 {
+  imports = [
+    (mkRemovedOptionModule [ "sdImage" "bootPartitionID" ] "The FAT partition for SD image now only holds the Raspberry Pi firmware files. Use firmwarePartitionID to configure that partition's ID.")
+    (mkRemovedOptionModule [ "sdImage" "bootSize" ] "The boot files for SD image have been moved to the main ext4 partition. The FAT partition now only holds the Raspberry Pi firmware files. Changing its size may not be required.")
+  ];
+
   options.sdImage = {
     imageName = mkOption {
       default = "${config.sdImage.imageBaseName}-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}.img";
@@ -43,12 +53,12 @@ in
       '';
     };
 
-    bootPartitionID = mkOption {
+    firmwarePartitionID = mkOption {
       type = types.string;
       default = "0x2178694e";
       description = ''
-        Volume ID for the /boot partition on the SD card. This value must be a
-        32-bit hexadecimal number.
+        Volume ID for the /boot/firmware partition on the SD card. This value
+        must be a 32-bit hexadecimal number.
       '';
     };
 
@@ -61,29 +71,44 @@ in
       '';
     };
 
-    bootSize = mkOption {
+    firmwareSize = mkOption {
       type = types.int;
-      default = 120;
+      # As of 2019-05-31 the Raspberry pi firmware + u-bot takes ~13MiB
+      default = 20;
+      description = ''
+        Size of the /boot/firmware partition, in megabytes.
+      '';
+    };
+
+    populateFirmwareCommands = mkOption {
+      example = literalExample "'' cp \${pkgs.myBootLoader}/u-boot.bin firmware/ ''";
       description = ''
-        Size of the /boot partition, in megabytes.
+        Shell commands to populate the ./firmware directory.
+        All files in that directory are copied to the
+        /boot/firmware partition on the SD image.
       '';
     };
 
-    populateBootCommands = mkOption {
-      example = literalExample "'' cp \${pkgs.myBootLoader}/u-boot.bin boot/ ''";
+    populateRootCommands = mkOption {
+      example = literalExample "''\${extlinux-conf-builder} -t 3 -c \${config.system.build.toplevel} -d ./files/boot''";
       description = ''
-        Shell commands to populate the ./boot directory.
+        Shell commands to populate the ./files directory.
         All files in that directory are copied to the
-        /boot partition on the SD image.
+        root (/) partition on the SD image. Use this to
+        populate the ./files/boot (/boot) directory.
       '';
     };
   };
 
   config = {
     fileSystems = {
-      "/boot" = {
-        device = "/dev/disk/by-label/NIXOS_BOOT";
+      "/boot/firmware" = {
+        device = "/dev/disk/by-label/FIRMWARE";
         fsType = "vfat";
+        # Alternatively, this could be removed from the configuration.
+        # The filesystem is not needed at runtime, it could be treated
+        # as an opaque blob instead of a discrete FAT32 filesystem.
+        options = [ "nofail" "noauto" ];
       };
       "/" = {
         device = "/dev/disk/by-label/NIXOS_SD";
@@ -105,39 +130,44 @@ in
         echo "${pkgs.stdenv.buildPlatform.system}" > $out/nix-support/system
         echo "file sd-image $img" >> $out/nix-support/hydra-build-products
 
-        # Create the image file sized to fit /boot and /, plus 20M of slack
+        # Gap in front of the first partition, in MiB
+        gap=8
+
+        # Create the image file sized to fit /boot/firmware and /, plus slack for the gap.
         rootSizeBlocks=$(du -B 512 --apparent-size ${rootfsImage} | awk '{ print $1 }')
-        bootSizeBlocks=$((${toString config.sdImage.bootSize} * 1024 * 1024 / 512))
-        imageSize=$((rootSizeBlocks * 512 + bootSizeBlocks * 512 + 20 * 1024 * 1024))
+        firmwareSizeBlocks=$((${toString config.sdImage.firmwareSize} * 1024 * 1024 / 512))
+        imageSize=$((rootSizeBlocks * 512 + firmwareSizeBlocks * 512 + gap * 1024 * 1024))
         truncate -s $imageSize $img
 
         # type=b is 'W95 FAT32', type=83 is 'Linux'.
+        # The "bootable" partition is where u-boot will look file for the bootloader
+        # information (dtbs, extlinux.conf file).
         sfdisk $img <<EOF
             label: dos
-            label-id: ${config.sdImage.bootPartitionID}
+            label-id: ${config.sdImage.firmwarePartitionID}
 
-            start=8M, size=$bootSizeBlocks, type=b, bootable
-            start=${toString (8 + config.sdImage.bootSize)}M, type=83
+            start=''${gap}M, size=$firmwareSizeBlocks, type=b
+            start=$((gap + ${toString config.sdImage.firmwareSize}))M, type=83, bootable
         EOF
 
         # Copy the rootfs into the SD image
         eval $(partx $img -o START,SECTORS --nr 2 --pairs)
         dd conv=notrunc if=${rootfsImage} of=$img seek=$START count=$SECTORS
 
-        # Create a FAT32 /boot partition of suitable size into bootpart.img
+        # Create a FAT32 /boot/firmware partition of suitable size into firmware_part.img
         eval $(partx $img -o START,SECTORS --nr 1 --pairs)
-        truncate -s $((SECTORS * 512)) bootpart.img
-        faketime "1970-01-01 00:00:00" mkfs.vfat -i ${config.sdImage.bootPartitionID} -n NIXOS_BOOT bootpart.img
+        truncate -s $((SECTORS * 512)) firmware_part.img
+        faketime "1970-01-01 00:00:00" mkfs.vfat -i ${config.sdImage.firmwarePartitionID} -n FIRMWARE firmware_part.img
 
-        # Populate the files intended for /boot
-        mkdir boot
-        ${config.sdImage.populateBootCommands}
+        # Populate the files intended for /boot/firmware
+        mkdir firmware
+        ${config.sdImage.populateFirmwareCommands}
 
-        # Copy the populated /boot into the SD image
-        (cd boot; mcopy -psvm -i ../bootpart.img ./* ::)
+        # Copy the populated /boot/firmware into the SD image
+        (cd firmware; mcopy -psvm -i ../firmware_part.img ./* ::)
         # Verify the FAT partition before copying it.
-        fsck.vfat -vn bootpart.img
-        dd conv=notrunc if=bootpart.img of=$img seek=$START count=$SECTORS
+        fsck.vfat -vn firmware_part.img
+        dd conv=notrunc if=firmware_part.img of=$img seek=$START count=$SECTORS
       '';
     }) {};
 
diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl
index 0ccdac30d91..c09def1fcea 100644
--- a/nixos/modules/installer/tools/nixos-generate-config.pl
+++ b/nixos/modules/installer/tools/nixos-generate-config.pl
@@ -264,6 +264,11 @@ if (scalar @bcacheDevices > 0) {
     push @initrdAvailableKernelModules, "bcache";
 }
 
+# Prevent unbootable systems if LVM snapshots are present at boot time.
+if (`lsblk -o TYPE` =~ "lvm") {
+    push @initrdKernelModules, "dm-snapshot";
+}
+
 my $virt = `systemd-detect-virt`;
 chomp $virt;
 
@@ -324,10 +329,19 @@ my @swapDevices;
 if (@swaps) {
     shift @swaps;
     foreach my $swap (@swaps) {
-        $swap =~ /^(\S+)\s/;
-        next unless -e $1;
-        my $dev = findStableDevPath $1;
-        push @swapDevices, "{ device = \"$dev\"; }";
+        my @fields = split ' ', $swap;
+        my $swapFilename = $fields[0];
+        my $swapType = $fields[1];
+        next unless -e $swapFilename;
+        my $dev = findStableDevPath $swapFilename;
+        if ($swapType =~ "partition") {
+            push @swapDevices, "{ device = \"$dev\"; }";
+        } elsif ($swapType =~ "file") {
+            # swap *files* are more likely specified in configuration.nix, so
+            # ignore them here.
+        } else {
+            die "Unsupported swap type: $swapType\n";
+        }
     }
 }
 
@@ -427,6 +441,10 @@ EOF
         }
     }
 
+    # Don't emit tmpfs entry for /tmp, because it most likely comes from the
+    # boot.tmpOnTmpfs option in configuration.nix (managed declaratively).
+    next if ($mountPoint eq "/tmp" && $fsType eq "tmpfs");
+
     # Emit the filesystem.
     $fileSystems .= <<EOF;
   fileSystems.\"$mountPoint\" =
@@ -517,6 +535,7 @@ sub multiLineList {
 }
 
 my $initrdAvailableKernelModules = toNixStringList(uniq @initrdAvailableKernelModules);
+my $initrdKernelModules = toNixStringList(uniq @initrdKernelModules);
 my $kernelModules = toNixStringList(uniq @kernelModules);
 my $modulePackages = toNixList(uniq @modulePackages);
 
@@ -536,6 +555,7 @@ my $hwConfig = <<EOF;
   imports =${\multiLineList("    ", @imports)};
 
   boot.initrd.availableKernelModules = [$initrdAvailableKernelModules ];
+  boot.initrd.kernelModules = [$initrdKernelModules ];
   boot.kernelModules = [$kernelModules ];
   boot.extraModulePackages = [$modulePackages ];
 $fsAndSwap
diff --git a/nixos/modules/misc/documentation.nix b/nixos/modules/misc/documentation.nix
index 834ac0de912..deecb005270 100644
--- a/nixos/modules/misc/documentation.nix
+++ b/nixos/modules/misc/documentation.nix
@@ -49,11 +49,7 @@ let
       if [ -z "$browser" ]; then
         browser="$(type -P xdg-open || true)"
         if [ -z "$browser" ]; then
-          browser="$(type -P w3m || true)"
-          if [ -z "$browser" ]; then
-            echo "$0: unable to start a web browser; please set \$BROWSER"
-            exit 1
-          fi
+          browser="${pkgs.w3m-nographics}/bin/w3m"
         fi
       fi
       exec "$browser" ${manual.manualHTMLIndex}
@@ -187,8 +183,6 @@ in
     })
 
     (mkIf cfg.doc.enable {
-      # TODO(@oxij): put it here and remove from profiles?
-      # environment.systemPackages = [ pkgs.w3m ]; # w3m-nox?
       environment.pathsToLink = [ "/share/doc" ];
       environment.extraOutputsToInstall = [ "doc" ] ++ optional cfg.dev.enable "devdoc";
     })
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index f1118f472e4..14ba5a573b1 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -44,7 +44,7 @@
       vsftpd = 7;
       ftp = 8;
       bitlbee = 9;
-      avahi = 10;
+      #avahi = 10; # removed 2019-05-22
       nagios = 11;
       atd = 12;
       postfix = 13;
@@ -358,7 +358,7 @@
       vsftpd = 7;
       ftp = 8;
       bitlbee = 9;
-      avahi = 10;
+      #avahi = 10; # removed 2019-05-22
       #nagios = 11; # unused
       atd = 12;
       postfix = 13;
diff --git a/nixos/modules/misc/nixops-autoluks.nix b/nixos/modules/misc/nixops-autoluks.nix
index 2153c6f975a..20c143286af 100644
--- a/nixos/modules/misc/nixops-autoluks.nix
+++ b/nixos/modules/misc/nixops-autoluks.nix
@@ -1,7 +1,6 @@
 { config, options, lib, ... }:
 let
   path = [ "deployment" "autoLuks" ];
-  hasAutoLuksOption = lib.hasAttrByPath path options;
   hasAutoLuksConfig = lib.hasAttrByPath path config && (lib.attrByPath path {} config) != {};
 
   inherit (config.nixops) enableDeprecatedAutoLuks;
diff --git a/nixos/modules/misc/version.nix b/nixos/modules/misc/version.nix
index c9b374b6d7b..3ae60cb7916 100644
--- a/nixos/modules/misc/version.nix
+++ b/nixos/modules/misc/version.nix
@@ -1,4 +1,4 @@
-{ options, config, lib, pkgs, ... }:
+{ config, lib, pkgs, ... }:
 
 with lib;
 
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 50e3078d977..6b8c8255c4d 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -50,6 +50,7 @@
   ./hardware/logitech.nix
   ./hardware/mcelog.nix
   ./hardware/network/b43.nix
+  ./hardware/network/intel-2200bg.nix
   ./hardware/nitrokey.nix
   ./hardware/opengl.nix
   ./hardware/pcmcia.nix
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index 7792c1eca9f..5be7b25da74 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -213,6 +213,7 @@ with lib;
     (mkRemovedOptionModule [ "boot" "zfs" "enableLegacyCrypto" ] "The corresponding package was removed from nixpkgs.")
     (mkRemovedOptionModule [ "services" "winstone" ] "The corresponding package was removed from nixpkgs.")
     (mkRemovedOptionModule [ "services" "mysql" "pidDir" ] "Don't wait for pidfiles, describe dependencies through systemd")
+    (mkRemovedOptionModule [ "services" "mysql" "rootPassword" ] "Use socket authentication or set the password outside of the nix store.")
 
     # ZSH
     (mkRenamedOptionModule [ "programs" "zsh" "enableSyntaxHighlighting" ] [ "programs" "zsh" "syntaxHighlighting" "enable" ])
diff --git a/nixos/modules/services/audio/mopidy.nix b/nixos/modules/services/audio/mopidy.nix
index e2f4ec39f94..a534b692f17 100644
--- a/nixos/modules/services/audio/mopidy.nix
+++ b/nixos/modules/services/audio/mopidy.nix
@@ -70,25 +70,25 @@ in {
 
   config = mkIf cfg.enable {
 
+    systemd.tmpfiles.rules = [
+      "d '${cfg.dataDir}' - mopidy mopidy - -"
+    ];
+
     systemd.services.mopidy = {
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" "sound.target" ];
       description = "mopidy music player daemon";
-      preStart = "mkdir -p ${cfg.dataDir} && chown -R mopidy:mopidy  ${cfg.dataDir}";
       serviceConfig = {
         ExecStart = "${mopidyEnv}/bin/mopidy --config ${concatStringsSep ":" ([mopidyConf] ++ cfg.extraConfigFiles)}";
         User = "mopidy";
-        PermissionsStartOnly = true;
       };
     };
 
     systemd.services.mopidy-scan = {
       description = "mopidy local files scanner";
-      preStart = "mkdir -p ${cfg.dataDir} && chown -R mopidy:mopidy  ${cfg.dataDir}";
       serviceConfig = {
         ExecStart = "${mopidyEnv}/bin/mopidy --config ${concatStringsSep ":" ([mopidyConf] ++ cfg.extraConfigFiles)} local scan";
         User = "mopidy";
-        PermissionsStartOnly = true;
         Type = "oneshot";
       };
     };
@@ -98,7 +98,7 @@ in {
       group = "mopidy";
       extraGroups = [ "audio" ];
       description = "Mopidy daemon user";
-      home = "${cfg.dataDir}";
+      home = cfg.dataDir;
     };
 
     users.groups.mopidy.gid = gid;
diff --git a/nixos/modules/services/audio/slimserver.nix b/nixos/modules/services/audio/slimserver.nix
index 640403d2c97..8f94a2b4940 100644
--- a/nixos/modules/services/audio/slimserver.nix
+++ b/nixos/modules/services/audio/slimserver.nix
@@ -42,15 +42,17 @@ in {
 
   config = mkIf cfg.enable {
 
+    systemd.tmpfiles.rules = [
+      "d '${cfg.dataDir}' - slimserver slimserver - -"
+    ];
+
     systemd.services.slimserver = {
       after = [ "network.target" ];
       description = "Slim Server for Logitech Squeezebox Players";
       wantedBy = [ "multi-user.target" ];
 
-      preStart = "mkdir -p ${cfg.dataDir} && chown -R slimserver:slimserver ${cfg.dataDir}";
       serviceConfig = {
         User = "slimserver";
-        PermissionsStartOnly = true;
         # Issue 40589: Disable broken image/video support (audio still works!)
         ExecStart = "${cfg.package}/slimserver.pl --logdir ${cfg.dataDir}/logs --prefsdir ${cfg.dataDir}/prefs --cachedir ${cfg.dataDir}/cache --noimage --novideo";
       };
diff --git a/nixos/modules/services/audio/snapserver.nix b/nixos/modules/services/audio/snapserver.nix
index f709dd7fe16..b0b9264e816 100644
--- a/nixos/modules/services/audio/snapserver.nix
+++ b/nixos/modules/services/audio/snapserver.nix
@@ -4,7 +4,6 @@ with lib;
 
 let
 
-  package = "snapcast";
   name = "snapserver";
 
   cfg = config.services.snapserver;
diff --git a/nixos/modules/services/backup/duplicati.nix b/nixos/modules/services/backup/duplicati.nix
index 80287f30b81..0ff720c5897 100644
--- a/nixos/modules/services/backup/duplicati.nix
+++ b/nixos/modules/services/backup/duplicati.nix
@@ -19,13 +19,22 @@ in
       };
 
       interface = mkOption {
-        default = "lo";
+        default = "127.0.0.1";
         type = types.str;
         description = ''
           Listening interface for the web UI
           Set it to "any" to listen on all available interfaces
         '';
       };
+
+      user = mkOption {
+        default = "duplicati";
+        type = types.str;
+        description = ''
+          Duplicati runs as it's own user. It will only be able to backup world-readable files.
+          Run as root with special care.
+        '';
+      };
     };
   };
 
@@ -37,14 +46,15 @@ in
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
       serviceConfig = {
-        User = "duplicati";
+        User = cfg.user;
         Group = "duplicati";
+        StateDirectory = "duplicati";
         ExecStart = "${pkgs.duplicati}/bin/duplicati-server --webservice-interface=${cfg.interface} --webservice-port=${toString cfg.port} --server-datafolder=/var/lib/duplicati";
         Restart = "on-failure";
       };
     };
 
-    users.users.duplicati = {
+    users.users.duplicati = lib.optionalAttrs (cfg.user == "duplicati") {
       uid = config.ids.uids.duplicati;
       home = "/var/lib/duplicati";
       createHome = true;
diff --git a/nixos/modules/services/cluster/kubernetes/default.nix b/nixos/modules/services/cluster/kubernetes/default.nix
index 5e46bfc4240..143b41f57f6 100644
--- a/nixos/modules/services/cluster/kubernetes/default.nix
+++ b/nixos/modules/services/cluster/kubernetes/default.nix
@@ -72,13 +72,6 @@ let
       default = null;
     };
   };
-
-  kubeConfigDefaults = {
-    server = mkDefault cfg.kubeconfig.server;
-    caFile = mkDefault cfg.kubeconfig.caFile;
-    certFile = mkDefault cfg.kubeconfig.certFile;
-    keyFile = mkDefault cfg.kubeconfig.keyFile;
-  };
 in {
 
   ###### interface
diff --git a/nixos/modules/services/cluster/kubernetes/kubelet.nix b/nixos/modules/services/cluster/kubernetes/kubelet.nix
index ccc8a16e788..4c5df96bcc6 100644
--- a/nixos/modules/services/cluster/kubernetes/kubelet.nix
+++ b/nixos/modules/services/cluster/kubernetes/kubelet.nix
@@ -28,13 +28,6 @@ let
 
   kubeconfig = top.lib.mkKubeConfig "kubelet" cfg.kubeconfig;
 
-  manifests = pkgs.buildEnv {
-    name = "kubernetes-manifests";
-    paths = mapAttrsToList (name: manifest:
-      pkgs.writeTextDir "${name}.json" (builtins.toJSON manifest)
-    ) cfg.manifests;
-  };
-
   manifestPath = "kubernetes/manifests";
 
   taintOptions = with lib.types; { name, ... }: {
diff --git a/nixos/modules/services/cluster/kubernetes/pki.nix b/nixos/modules/services/cluster/kubernetes/pki.nix
index e68660e8bdd..47384ae50a0 100644
--- a/nixos/modules/services/cluster/kubernetes/pki.nix
+++ b/nixos/modules/services/cluster/kubernetes/pki.nix
@@ -118,7 +118,6 @@ in
     cfsslCertPathPrefix = "${config.services.cfssl.dataDir}/cfssl";
     cfsslCert = "${cfsslCertPathPrefix}.pem";
     cfsslKey = "${cfsslCertPathPrefix}-key.pem";
-    cfsslPort = toString config.services.cfssl.port;
 
     certmgrPaths = [
       top.caFile
diff --git a/nixos/modules/services/computing/boinc/client.nix b/nixos/modules/services/computing/boinc/client.nix
index 8abe3c5b8c9..7022751b3f0 100644
--- a/nixos/modules/services/computing/boinc/client.nix
+++ b/nixos/modules/services/computing/boinc/client.nix
@@ -105,19 +105,18 @@ in
         isSystemUser = true;
       };
 
+      systemd.tmpfiles.rules = [
+        "d '${cfg.dataDir}' - boinc - - -"
+      ];
+
       systemd.services.boinc = {
         description = "BOINC Client";
         after = ["network.target" "local-fs.target"];
         wantedBy = ["multi-user.target"];
-        preStart = ''
-          mkdir -p ${cfg.dataDir}
-          chown boinc ${cfg.dataDir}
-        '';
         script = ''
           ${fhsEnvExecutable} --dir ${cfg.dataDir} --redirectio ${allowRemoteGuiRpcFlag}
         '';
         serviceConfig = {
-          PermissionsStartOnly = true; # preStart must be run as root
           User = "boinc";
           Nice = 10;
         };
diff --git a/nixos/modules/services/databases/cassandra.nix b/nixos/modules/services/databases/cassandra.nix
index e2ea9fcda6b..a9da3a3c562 100644
--- a/nixos/modules/services/databases/cassandra.nix
+++ b/nixos/modules/services/databases/cassandra.nix
@@ -71,7 +71,7 @@ in {
     '';
     clusterName = mkOption {
       type = types.str;
-      default = "NixOS Test Cluster";
+      default = "Test Cluster";
       description = ''
         The name of the cluster.
         This setting prevents nodes in one logical cluster from joining
diff --git a/nixos/modules/services/databases/firebird.nix b/nixos/modules/services/databases/firebird.nix
index cc81b440450..042c9841df5 100644
--- a/nixos/modules/services/databases/firebird.nix
+++ b/nixos/modules/services/databases/firebird.nix
@@ -95,6 +95,11 @@ in
 
     environment.systemPackages = [cfg.package];
 
+    systemd.tmpfiles.rules = [
+      "d '${dataDir}' 0700 ${cfg.user} - - -"
+      "d '${systemDir}' 0700 ${cfg.user} - - -"
+    ];
+
     systemd.services.firebird =
       { description = "Firebird Super-Server";
 
@@ -104,21 +109,16 @@ in
         # is a better way
         preStart =
           ''
-            mkdir -m 0700 -p \
-              "${dataDir}" \
-              "${systemDir}" \
-              /var/log/firebird
-
             if ! test -e "${systemDir}/security2.fdb"; then
                 cp ${firebird}/security2.fdb "${systemDir}"
             fi
 
-            chown -R ${cfg.user} "${dataDir}" "${systemDir}" /var/log/firebird
             chmod -R 700         "${dataDir}" "${systemDir}" /var/log/firebird
           '';
 
-        serviceConfig.PermissionsStartOnly = true; # preStart must be run as root
         serviceConfig.User = cfg.user;
+        serviceConfig.LogsDirectory = "firebird";
+        serviceConfig.LogsDirectoryMode = "0700";
         serviceConfig.ExecStart = ''${firebird}/bin/fbserver -d'';
 
         # TODO think about shutdown
diff --git a/nixos/modules/services/databases/foundationdb.nix b/nixos/modules/services/databases/foundationdb.nix
index 490c5e9d005..6182da5e7d6 100644
--- a/nixos/modules/services/databases/foundationdb.nix
+++ b/nixos/modules/services/databases/foundationdb.nix
@@ -359,6 +359,13 @@ in
         }
       ];
 
+    systemd.tmpfiles.rules = [
+      "d /etc/foundationdb 0755 ${cfg.user} ${cfg.group} - -"
+      "d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -"
+      "d '${cfg.logDir}' 0770 ${cfg.user} ${cfg.group} - -"
+      "F '${cfg.pidFile}' - ${cfg.user} ${cfg.group} - -"
+    ];
+
     systemd.services.foundationdb = {
       description             = "FoundationDB Service";
 
@@ -396,25 +403,12 @@ in
       path = [ pkg pkgs.coreutils ];
 
       preStart = ''
-        rm -f ${cfg.pidfile}   && \
-          touch ${cfg.pidfile} && \
-          chown -R ${cfg.user}:${cfg.group} ${cfg.pidfile}
-
-        for x in "${cfg.logDir}" "${cfg.dataDir}"; do
-          [ ! -d "$x" ] && mkdir -m 0770 -vp "$x";
-          chown -R ${cfg.user}:${cfg.group} "$x";
-        done
-
-        [ ! -d /etc/foundationdb ] && \
-          mkdir -m 0775 -vp /etc/foundationdb && \
-          chown -R ${cfg.user}:${cfg.group} "/etc/foundationdb"
-
         if [ ! -f /etc/foundationdb/fdb.cluster ]; then
             cf=/etc/foundationdb/fdb.cluster
             desc=$(tr -dc A-Za-z0-9 </dev/urandom 2>/dev/null | head -c8)
             rand=$(tr -dc A-Za-z0-9 </dev/urandom 2>/dev/null | head -c8)
             echo ''${desc}:''${rand}@${initialIpAddr}:${builtins.toString cfg.listenPortStart} > $cf
-            chmod 0664 $cf && chown -R ${cfg.user}:${cfg.group} $cf
+            chmod 0664 $cf
             touch "${cfg.dataDir}/.first_startup"
         fi
       '';
diff --git a/nixos/modules/services/databases/foundationdb.xml b/nixos/modules/services/databases/foundationdb.xml
index bf4b644c9b8..b0b1ebeab45 100644
--- a/nixos/modules/services/databases/foundationdb.xml
+++ b/nixos/modules/services/databases/foundationdb.xml
@@ -47,14 +47,14 @@ services.foundationdb.package = pkgs.foundationdb52; # FoundationDB 5.2.x
    After running <command>nixos-rebuild</command>, you can verify whether
    FoundationDB is running by executing <command>fdbcli</command> (which is
    added to <option>environment.systemPackages</option>):
-<programlisting>
-$ sudo -u foundationdb fdbcli
+<screen>
+<prompt>$ </prompt>sudo -u foundationdb fdbcli
 Using cluster file `/etc/foundationdb/fdb.cluster'.
 
 The database is available.
 
 Welcome to the fdbcli. For help, type `help'.
-fdb> status
+<prompt>fdb> </prompt>status
 
 Using cluster file `/etc/foundationdb/fdb.cluster'.
 
@@ -72,8 +72,8 @@ Cluster:
 
 ...
 
-fdb>
-</programlisting>
+<prompt>fdb></prompt>
+</screen>
   </para>
 
   <para>
@@ -82,8 +82,8 @@ fdb>
    cluster status, as a quick example. (This example uses
    <command>nix-shell</command> shebang support to automatically supply the
    necessary Python modules).
-<programlisting>
-a@link> cat fdb-status.py
+<screen>
+<prompt>a@link> </prompt>cat fdb-status.py
 #! /usr/bin/env nix-shell
 #! nix-shell -i python -p python pythonPackages.foundationdb52
 
@@ -103,11 +103,11 @@ def main():
 
 if __name__ == "__main__":
     main()
-a@link> chmod +x fdb-status.py
-a@link> ./fdb-status.py
+<prompt>a@link> </prompt>chmod +x fdb-status.py
+<prompt>a@link> </prompt>./fdb-status.py
 FoundationDB available: True
-a@link>
-</programlisting>
+<prompt>a@link></prompt>
+</screen>
   </para>
 
   <para>
@@ -266,10 +266,10 @@ services.foundationdb.dataDir = "/data/fdb";
    <emphasis>every</emphasis> node a coordinator automatically:
   </para>
 
-<programlisting>
-fdbcli> configure double ssd
-fdbcli> coordinators auto
-</programlisting>
+<screen>
+<prompt>fdbcli> </prompt>configure double ssd
+<prompt>fdbcli> </prompt>coordinators auto
+</screen>
 
   <para>
    This will transparently update all the servers within seconds, and
@@ -386,10 +386,10 @@ services.foundationdb.extraReadWritePaths = [ "/opt/fdb-backups" ];
    You can now perform a backup:
   </para>
 
-<programlisting>
-$ sudo -u foundationdb fdbbackup start  -t default -d file:///opt/fdb-backups
-$ sudo -u foundationdb fdbbackup status -t default
-</programlisting>
+<screen>
+<prompt>$ </prompt>sudo -u foundationdb fdbbackup start  -t default -d file:///opt/fdb-backups
+<prompt>$ </prompt>sudo -u foundationdb fdbbackup status -t default
+</screen>
  </section>
  <section xml:id="module-services-foundationdb-limitations">
   <title>Known limitations</title>
diff --git a/nixos/modules/services/databases/hbase.nix b/nixos/modules/services/databases/hbase.nix
index 52f2d95b4e0..589c8cf5ec8 100644
--- a/nixos/modules/services/databases/hbase.nix
+++ b/nixos/modules/services/databases/hbase.nix
@@ -94,6 +94,11 @@ in {
 
   config = mkIf config.services.hbase.enable {
 
+    systemd.tmpfiles.rules = [
+      "d '${cfg.dataDir}' - ${cfg.user} ${cfg.group} - -"
+      "d '${cfg.logDir}' - ${cfg.user} ${cfg.group} - -"
+    ];
+
     systemd.services.hbase = {
       description = "HBase Server";
       wantedBy = [ "multi-user.target" ];
@@ -103,19 +108,7 @@ in {
         HBASE_LOG_DIR = cfg.logDir;
       };
 
-      preStart =
-        ''
-        mkdir -p ${cfg.dataDir};
-        mkdir -p ${cfg.logDir};
-
-        if [ "$(id -u)" = 0 ]; then
-          chown ${cfg.user}:${cfg.group} ${cfg.dataDir}
-          chown ${cfg.user}:${cfg.group} ${cfg.logDir}
-        fi
-        '';
-
       serviceConfig = {
-        PermissionsStartOnly = true;
         User = cfg.user;
         Group = cfg.group;
         ExecStart = "${cfg.package}/bin/hbase --config ${configDir} master start";
diff --git a/nixos/modules/services/databases/mysql.nix b/nixos/modules/services/databases/mysql.nix
index 66d55b650a4..02f40683313 100644
--- a/nixos/modules/services/databases/mysql.nix
+++ b/nixos/modules/services/databases/mysql.nix
@@ -204,12 +204,6 @@ in
         '';
       };
 
-      # FIXME: remove this option; it's a really bad idea.
-      rootPassword = mkOption {
-        default = null;
-        description = "Path to a file containing the root password, modified on the first startup. Not specifying a root password will leave the root password empty.";
-      };
-
       replication = {
         role = mkOption {
           type = types.enum [ "master" "slave" "none" ];
@@ -400,16 +394,6 @@ in
                     cat ${toString cfg.initialScript} | ${mysql}/bin/mysql -u root -N
                   ''}
 
-                ${optionalString (cfg.rootPassword != null)
-                  ''
-                    # Change root password
-
-                    ( echo "use mysql;"
-                      echo "update user set Password=password('$(cat ${cfg.rootPassword})') where User='root';"
-                      echo "flush privileges;"
-                    ) | ${mysql}/bin/mysql -u root -N
-                  ''}
-
               rm /tmp/mysql_init
             fi
 
diff --git a/nixos/modules/services/databases/postgresql.xml b/nixos/modules/services/databases/postgresql.xml
index 14f4d4909bc..00bb02dcc5b 100644
--- a/nixos/modules/services/databases/postgresql.xml
+++ b/nixos/modules/services/databases/postgresql.xml
@@ -42,11 +42,11 @@
 whether PostgreSQL works by running <command>psql</command>:
 
 <screen>
-$ psql
+<prompt>$ </prompt>psql
 psql (9.2.9)
 Type "help" for help.
 
-alice=>
+<prompt>alice=></prompt>
 </screen>
 -->
 
diff --git a/nixos/modules/services/desktops/deepin/deepin.nix b/nixos/modules/services/desktops/deepin/deepin.nix
index d9d5d539e42..1e46ad83299 100644
--- a/nixos/modules/services/desktops/deepin/deepin.nix
+++ b/nixos/modules/services/desktops/deepin/deepin.nix
@@ -35,6 +35,7 @@
         pkgs.deepin.dde-calendar
         pkgs.deepin.dde-daemon
         pkgs.deepin.dde-dock
+        pkgs.deepin.dde-launcher
         pkgs.deepin.dde-file-manager
         pkgs.deepin.dde-session-ui
         pkgs.deepin.deepin-anything
@@ -47,6 +48,7 @@
         pkgs.deepin.dde-calendar
         pkgs.deepin.dde-daemon
         pkgs.deepin.dde-dock
+        pkgs.deepin.dde-launcher
         pkgs.deepin.dde-file-manager
         pkgs.deepin.dde-session-ui
         pkgs.deepin.deepin-anything
diff --git a/nixos/modules/services/desktops/flatpak.xml b/nixos/modules/services/desktops/flatpak.xml
index 8045d5fa14f..fb27bd1f62b 100644
--- a/nixos/modules/services/desktops/flatpak.xml
+++ b/nixos/modules/services/desktops/flatpak.xml
@@ -21,7 +21,7 @@
   <filename>configuration.nix</filename>:
 <programlisting>
   <xref linkend="opt-services.flatpak.enable"/> = true;
-  </programlisting>
+</programlisting>
  </para>
  <para>
   For the sandboxed apps to work correctly, desktop integration portals need to
@@ -30,27 +30,27 @@
   <filename>configuration.nix</filename>:
 <programlisting>
   <xref linkend="opt-services.flatpak.extraPortals"/> = [ pkgs.xdg-desktop-portal-gtk ];
-  </programlisting>
+</programlisting>
  </para>
  <para>
   Then, you will need to add a repository, for example,
   <link xlink:href="https://github.com/flatpak/flatpak/wiki">Flathub</link>,
   either using the following commands:
-<programlisting>
-  flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
-  flatpak update
-  </programlisting>
+<screen>
+<prompt>$ </prompt>flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
+<prompt>$ </prompt>flatpak update
+</screen>
   or by opening the
   <link xlink:href="https://flathub.org/repo/flathub.flatpakrepo">repository
   file</link> in GNOME Software.
  </para>
  <para>
   Finally, you can search and install programs:
-<programlisting>
-  flatpak search bustle
-  flatpak install flathub org.freedesktop.Bustle
-  flatpak run org.freedesktop.Bustle
-  </programlisting>
+<screen>
+<prompt>$ </prompt>flatpak search bustle
+<prompt>$ </prompt>flatpak install flathub org.freedesktop.Bustle
+<prompt>$ </prompt>flatpak run org.freedesktop.Bustle
+</screen>
   Again, GNOME Software offers graphical interface for these tasks.
  </para>
 </chapter>
diff --git a/nixos/modules/services/editors/emacs.xml b/nixos/modules/services/editors/emacs.xml
index 1ac53c818a7..88d7c4e1daf 100644
--- a/nixos/modules/services/editors/emacs.xml
+++ b/nixos/modules/services/editors/emacs.xml
@@ -238,8 +238,8 @@ in
    <para>
     You can check that it works by executing this in a terminal:
 <screen>
-$ nix-build emacs.nix
-$ ./result/bin/emacs -q
+<prompt>$ </prompt>nix-build emacs.nix
+<prompt>$ </prompt>./result/bin/emacs -q
 </screen>
     and then typing <literal>M-x package-initialize</literal>. Check that you
     can use all the packages you want in this Emacs instance. For example, try
@@ -403,9 +403,9 @@ in [...]
    <para>
     To start the daemon, execute the following:
 <screen>
-$ nixos-rebuild switch  # to activate the new configuration.nix
-$ systemctl --user daemon-reload        # to force systemd reload
-$ systemctl --user start emacs.service  # to start the Emacs daemon
+<prompt>$ </prompt>nixos-rebuild switch  # to activate the new configuration.nix
+<prompt>$ </prompt>systemctl --user daemon-reload        # to force systemd reload
+<prompt>$ </prompt>systemctl --user start emacs.service  # to start the Emacs daemon
 </screen>
     The server should now be ready to serve Emacs clients.
    </para>
diff --git a/nixos/modules/services/hardware/triggerhappy.nix b/nixos/modules/services/hardware/triggerhappy.nix
index bffe7353b10..a500cb4fc36 100644
--- a/nixos/modules/services/hardware/triggerhappy.nix
+++ b/nixos/modules/services/hardware/triggerhappy.nix
@@ -17,7 +17,7 @@ let
     ${cfg.extraConfig}
   '';
 
-  bindingCfg = { config, ... }: {
+  bindingCfg = { ... }: {
     options = {
 
       keys = mkOption {
diff --git a/nixos/modules/services/hardware/udev.nix b/nixos/modules/services/hardware/udev.nix
index cb2f1e6621a..83ab93bd7cf 100644
--- a/nixos/modules/services/hardware/udev.nix
+++ b/nixos/modules/services/hardware/udev.nix
@@ -85,7 +85,7 @@ let
       for i in $import_progs $run_progs; do
         if [[ ! -x $i ]]; then
           echo "FAIL"
-          echo "$i is called in udev rules but not installed by udev"
+          echo "$i is called in udev rules but is not executable or does not exist"
           exit 1
         fi
       done
diff --git a/nixos/modules/services/logging/graylog.nix b/nixos/modules/services/logging/graylog.nix
index 74a7b3c9b47..ee566825498 100644
--- a/nixos/modules/services/logging/graylog.nix
+++ b/nixos/modules/services/logging/graylog.nix
@@ -134,6 +134,10 @@ in
       };
     };
 
+    systemd.tmpfiles.rules = [
+      "d '${cfg.messageJournalDir}' - ${cfg.user} - - -"
+    ];
+
     systemd.services.graylog = with pkgs; {
       description = "Graylog Server";
       wantedBy = [ "multi-user.target" ];
@@ -143,8 +147,6 @@ in
       };
       path = [ pkgs.jre_headless pkgs.which pkgs.procps ];
       preStart = ''
-        mkdir -p /var/lib/graylog -m 755
-
         rm -rf /var/lib/graylog/plugins || true
         mkdir -p /var/lib/graylog/plugins -m 755
 
@@ -154,14 +156,10 @@ in
         for includedplugin in `ls ${cfg.package}/plugin/`; do
           ln -s ${cfg.package}/plugin/$includedplugin /var/lib/graylog/plugins/$includedplugin || true
         done
-        chown -R ${cfg.user} /var/lib/graylog
-
-        mkdir -p ${cfg.messageJournalDir} -m 755
-        chown -R ${cfg.user} ${cfg.messageJournalDir}
       '';
       serviceConfig = {
         User="${cfg.user}";
-        PermissionsStartOnly=true;
+        StateDirectory = "graylog";
         ExecStart = "${cfg.package}/bin/graylogctl run";
       };
     };
diff --git a/nixos/modules/services/logging/heartbeat.nix b/nixos/modules/services/logging/heartbeat.nix
index b595ac07bf5..56fb4deabda 100644
--- a/nixos/modules/services/logging/heartbeat.nix
+++ b/nixos/modules/services/logging/heartbeat.nix
@@ -54,16 +54,18 @@ in
 
   config = mkIf cfg.enable {
 
+    systemd.tmpfiles.rules = [
+      "d '${cfg.stateDir}' - nobody nogroup - -"
+    ];
+
     systemd.services.heartbeat = with pkgs; {
       description = "heartbeat log shipper";
       wantedBy = [ "multi-user.target" ];
       preStart = ''
         mkdir -p "${cfg.stateDir}"/{data,logs}
-        chown nobody:nogroup "${cfg.stateDir}"/{data,logs}
       '';
       serviceConfig = {
         User = "nobody";
-        PermissionsStartOnly = true;
         AmbientCapabilities = "cap_net_raw";
         ExecStart = "${pkgs.heartbeat}/bin/heartbeat -c \"${heartbeatYml}\" -path.data \"${cfg.stateDir}/data\" -path.logs \"${cfg.stateDir}/logs\"";
       };
diff --git a/nixos/modules/services/mail/dspam.nix b/nixos/modules/services/mail/dspam.nix
index 167b5aeccc8..72b8c4c08b9 100644
--- a/nixos/modules/services/mail/dspam.nix
+++ b/nixos/modules/services/mail/dspam.nix
@@ -113,19 +113,14 @@ in {
           Group = cfg.group;
           RuntimeDirectory = optional (cfg.domainSocket == defaultSock) "dspam";
           RuntimeDirectoryMode = optional (cfg.domainSocket == defaultSock) "0750";
-          PermissionsStartOnly = true;
+          StateDirectory = "dspam";
+          StateDirectoryMode = "0750";
+          LogsDirectory = "dspam";
+          LogsDirectoryMode = "0750";
           # DSPAM segfaults on just about every error
           Restart = "on-abort";
           RestartSec = "1s";
         };
-
-        preStart = ''
-          mkdir -m750 -p /var/lib/dspam
-          chown -R "${cfg.user}:${cfg.group}" /var/lib/dspam
-
-          mkdir -m750 -p /var/log/dspam
-          chown -R "${cfg.user}:${cfg.group}" /var/log/dspam
-        '';
       };
     }
 
diff --git a/nixos/modules/services/mail/opendkim.nix b/nixos/modules/services/mail/opendkim.nix
index 7855efb46c7..253823cbaf9 100644
--- a/nixos/modules/services/mail/opendkim.nix
+++ b/nixos/modules/services/mail/opendkim.nix
@@ -101,13 +101,16 @@ in {
 
     environment.systemPackages = [ pkgs.opendkim ];
 
+    systemd.tmpfiles.rules = [
+      "d '${cfg.keyPath}' - ${cfg.user} ${cfg.group} - -"
+    ];
+
     systemd.services.opendkim = {
       description = "OpenDKIM signing and verification daemon";
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
 
       preStart = ''
-        mkdir -p "${cfg.keyPath}"
         cd "${cfg.keyPath}"
         if ! test -f ${cfg.selector}.private; then
           ${pkgs.opendkim}/bin/opendkim-genkey -s ${cfg.selector} -d all-domains-generic-key
@@ -116,7 +119,6 @@ in {
           cat ${cfg.selector}.txt
           echo "-------------------------------------------------------------"
         fi
-        chown ${cfg.user}:${cfg.group} ${cfg.selector}.private
       '';
 
       serviceConfig = {
@@ -124,7 +126,6 @@ in {
         User = cfg.user;
         Group = cfg.group;
         RuntimeDirectory = optional (cfg.socket == defaultSock) "opendkim";
-        PermissionsStartOnly = true;
       };
     };
 
diff --git a/nixos/modules/services/mail/rspamd.nix b/nixos/modules/services/mail/rspamd.nix
index c9ba8678021..5541b8b79b7 100644
--- a/nixos/modules/services/mail/rspamd.nix
+++ b/nixos/modules/services/mail/rspamd.nix
@@ -5,7 +5,6 @@ with lib;
 let
 
   cfg = config.services.rspamd;
-  opts = options.services.rspamd;
   postfixCfg = config.services.postfix;
 
   bindSocketOpts = {options, config, ... }: {
diff --git a/nixos/modules/services/misc/apache-kafka.nix b/nixos/modules/services/misc/apache-kafka.nix
index 363ac4411e1..9eeae955699 100644
--- a/nixos/modules/services/misc/apache-kafka.nix
+++ b/nixos/modules/services/misc/apache-kafka.nix
@@ -131,6 +131,8 @@ in {
       home = head cfg.logDirs;
     };
 
+    systemd.tmpfiles.rules = map (logDir: "d '${logDir} 0700 apache-kafka - - -") cfg.logDirs;
+
     systemd.services.apache-kafka = {
       description = "Apache Kafka Daemon";
       wantedBy = [ "multi-user.target" ];
@@ -145,15 +147,8 @@ in {
             ${serverConfig}
         '';
         User = "apache-kafka";
-        PermissionsStartOnly = true;
         SuccessExitStatus = "0 143";
       };
-      preStart = ''
-        mkdir -m 0700 -p ${concatStringsSep " " cfg.logDirs}
-        if [ "$(id -u)" = 0 ]; then
-           chown apache-kafka ${concatStringsSep " " cfg.logDirs};
-        fi
-      '';
     };
 
   };
diff --git a/nixos/modules/services/misc/couchpotato.nix b/nixos/modules/services/misc/couchpotato.nix
index 70aa895f76d..528af486b41 100644
--- a/nixos/modules/services/misc/couchpotato.nix
+++ b/nixos/modules/services/misc/couchpotato.nix
@@ -19,16 +19,11 @@ in
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
 
-      preStart = ''
-        mkdir -p /var/lib/couchpotato
-        chown -R couchpotato:couchpotato /var/lib/couchpotato
-      '';
-
       serviceConfig = {
         Type = "simple";
         User = "couchpotato";
         Group = "couchpotato";
-        PermissionsStartOnly = "true";
+        StateDirectory = "couchpotato";
         ExecStart = "${pkgs.couchpotato}/bin/couchpotato";
         Restart = "on-failure";
       };
diff --git a/nixos/modules/services/misc/gitea.nix b/nixos/modules/services/misc/gitea.nix
index 7daa2dd0d4c..5a964e672ed 100644
--- a/nixos/modules/services/misc/gitea.nix
+++ b/nixos/modules/services/misc/gitea.nix
@@ -38,6 +38,7 @@ let
     HTTP_PORT = ${toString cfg.httpPort}
     ROOT_URL = ${cfg.rootUrl}
     STATIC_ROOT_PATH = ${cfg.staticRootPath}
+    LFS_JWT_SECRET = #jwtsecret#
 
     [session]
     COOKIE_NAME = session
@@ -307,6 +308,7 @@ in
     systemd.tmpfiles.rules = [
       "d '${cfg.stateDir}' - ${cfg.user} gitea - -"
       "d '${cfg.stateDir}/conf' - ${cfg.user} gitea - -"
+      "d '${cfg.stateDir}/custom' - ${cfg.user} gitea - -"
       "d '${cfg.stateDir}/custom/conf' - ${cfg.user} gitea - -"
       "d '${cfg.repositoryRoot}' - ${cfg.user} gitea - -"
       "Z '${cfg.stateDir}' - ${cfg.user} gitea - -"
@@ -325,21 +327,28 @@ in
       preStart = let
         runConfig = "${cfg.stateDir}/custom/conf/app.ini";
         secretKey = "${cfg.stateDir}/custom/conf/secret_key";
+        jwtSecret = "${cfg.stateDir}/custom/conf/jwt_secret";
       in ''
         # copy custom configuration and generate a random secret key if needed
         ${optionalString (cfg.useWizard == false) ''
           cp -f ${configFile} ${runConfig}
 
           if [ ! -e ${secretKey} ]; then
-              head -c 16 /dev/urandom | base64 > ${secretKey}
+              ${gitea.bin}/bin/gitea generate secret SECRET_KEY > ${secretKey}
           fi
 
-          KEY=$(head -n1 ${secretKey})
-          DBPASS=$(head -n1 ${cfg.database.passwordFile})
+          if [ ! -e ${jwtSecret} ]; then
+              ${gitea.bin}/bin/gitea generate secret LFS_JWT_SECRET > ${jwtSecret}
+          fi
+
+          KEY="$(head -n1 ${secretKey})"
+          DBPASS="$(head -n1 ${cfg.database.passwordFile})"
+          JWTSECRET="$(head -n1 ${jwtSecret})"
           sed -e "s,#secretkey#,$KEY,g" \
               -e "s,#dbpass#,$DBPASS,g" \
+              -e "s,#jwtsecet#,$JWTSECET,g" \
               -i ${runConfig}
-          chmod 640 ${runConfig} ${secretKey}
+          chmod 640 ${runConfig} ${secretKey} ${jwtSecret}
         ''}
 
         # update all hooks' binary paths
diff --git a/nixos/modules/services/misc/gitlab.xml b/nixos/modules/services/misc/gitlab.xml
index ab99d7bd3a6..5ff570a442f 100644
--- a/nixos/modules/services/misc/gitlab.xml
+++ b/nixos/modules/services/misc/gitlab.xml
@@ -138,13 +138,13 @@ services.gitlab = {
 
   <para>
    For example, to backup a Gitlab instance:
-<programlisting>
-$ sudo -u git -H gitlab-rake gitlab:backup:create
-</programlisting>
+<screen>
+<prompt>$ </prompt>sudo -u git -H gitlab-rake gitlab:backup:create
+</screen>
    A list of all availabe rake tasks can be obtained by running:
-<programlisting>
-$ sudo -u git -H gitlab-rake -T
-</programlisting>
+<screen>
+<prompt>$ </prompt>sudo -u git -H gitlab-rake -T
+</screen>
   </para>
  </section>
 </chapter>
diff --git a/nixos/modules/services/misc/gollum.nix b/nixos/modules/services/misc/gollum.nix
index d1823bc6d4d..7653b415bf0 100644
--- a/nixos/modules/services/misc/gollum.nix
+++ b/nixos/modules/services/misc/gollum.nix
@@ -75,27 +75,24 @@ in
 
     users.groups.gollum = { };
 
+    systemd.tmpfiles.rules = [
+      "d '${cfg.stateDir}' - ${config.users.users.gollum.name} ${config.users.groups.gollum.name} - -"
+    ];
+
     systemd.services.gollum = {
       description = "Gollum wiki";
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
       path = [ pkgs.git ];
 
-      preStart = let
-          userName = config.users.users.gollum.name;
-          groupName = config.users.groups.gollum.name;
-        in ''
-        # All of this is safe to be run on an existing repo
-        mkdir -p ${cfg.stateDir}
+      preStart = ''
+        # This is safe to be run on an existing repo
         git init ${cfg.stateDir}
-        chmod 755 ${cfg.stateDir}
-        chown -R ${userName}:${groupName} ${cfg.stateDir}
       '';
 
       serviceConfig = {
         User = config.users.users.gollum.name;
         Group = config.users.groups.gollum.name;
-        PermissionsStartOnly = true;
         ExecStart = ''
           ${pkgs.gollum}/bin/gollum \
             --port ${toString cfg.port} \
diff --git a/nixos/modules/services/misc/lidarr.nix b/nixos/modules/services/misc/lidarr.nix
index f466402abfc..92108ec5508 100644
--- a/nixos/modules/services/misc/lidarr.nix
+++ b/nixos/modules/services/misc/lidarr.nix
@@ -9,6 +9,13 @@ in
   options = {
     services.lidarr = {
       enable = mkEnableOption "Lidarr";
+
+      package = mkOption {
+        type = types.package;
+        default = pkgs.lidarr;
+        defaultText = "pkgs.lidarr";
+        description = "The Lidarr package to use";
+      };
     };
   };
 
@@ -22,7 +29,7 @@ in
         Type = "simple";
         User = "lidarr";
         Group = "lidarr";
-        ExecStart = "${pkgs.lidarr}/bin/Lidarr";
+        ExecStart = "${cfg.package}/bin/Lidarr";
         Restart = "on-failure";
 
         StateDirectory = "lidarr";
diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix
index 8db3c44246f..d8f90f1539c 100644
--- a/nixos/modules/services/misc/nix-daemon.nix
+++ b/nixos/modules/services/misc/nix-daemon.nix
@@ -272,10 +272,12 @@ in
 
       binaryCaches = mkOption {
         type = types.listOf types.str;
-        default = [ https://cache.nixos.org/ ];
         description = ''
           List of binary cache URLs used to obtain pre-built binaries
           of Nix packages.
+
+          By default https://cache.nixos.org/ is added,
+          to override it use <literal>lib.mkForce []</literal>.
         '';
       };
 
@@ -386,6 +388,7 @@ in
   config = {
 
     nix.binaryCachePublicKeys = [ "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" ];
+    nix.binaryCaches = [ "https://cache.nixos.org/" ];
 
     environment.etc."nix/nix.conf".source = nixConf;
 
diff --git a/nixos/modules/services/misc/octoprint.nix b/nixos/modules/services/misc/octoprint.nix
index 52ae25201c3..8950010773c 100644
--- a/nixos/modules/services/misc/octoprint.nix
+++ b/nixos/modules/services/misc/octoprint.nix
@@ -97,6 +97,10 @@ in
         gid = config.ids.gids.octoprint;
       });
 
+    systemd.tmpfiles.rules = [
+      "d '${cfg.stateDir}' - ${cfg.user} ${cfg.group} - -"
+    ];
+
     systemd.services.octoprint = {
       description = "OctoPrint, web interface for 3D printers";
       wantedBy = [ "multi-user.target" ];
@@ -105,7 +109,6 @@ in
       environment.PYTHONPATH = makeSearchPathOutput "lib" pkgs.python.sitePackages [ pluginsEnv ];
 
       preStart = ''
-        mkdir -p "${cfg.stateDir}"
         if [ -e "${cfg.stateDir}/config.yaml" ]; then
           ${pkgs.yaml-merge}/bin/yaml-merge "${cfg.stateDir}/config.yaml" "${cfgUpdate}" > "${cfg.stateDir}/config.yaml.tmp"
           mv "${cfg.stateDir}/config.yaml.tmp" "${cfg.stateDir}/config.yaml"
@@ -113,14 +116,12 @@ in
           cp "${cfgUpdate}" "${cfg.stateDir}/config.yaml"
           chmod 600 "${cfg.stateDir}/config.yaml"
         fi
-        chown -R ${cfg.user}:${cfg.group} "${cfg.stateDir}"
       '';
 
       serviceConfig = {
         ExecStart = "${pkgs.octoprint}/bin/octoprint serve -b ${cfg.stateDir}";
         User = cfg.user;
         Group = cfg.group;
-        PermissionsStartOnly = true;
       };
     };
 
diff --git a/nixos/modules/services/misc/taskserver/doc.xml b/nixos/modules/services/misc/taskserver/doc.xml
index 5eac8d9ef78..5656bb85b37 100644
--- a/nixos/modules/services/misc/taskserver/doc.xml
+++ b/nixos/modules/services/misc/taskserver/doc.xml
@@ -105,7 +105,7 @@
    Now in order to import the <literal>alice</literal> user to another machine
    <literal>alicebox</literal>, all we need to do is something like this:
 <screen>
-$ ssh server nixos-taskserver user export my-company alice | sh
+<prompt>$ </prompt>ssh server nixos-taskserver user export my-company alice | sh
 </screen>
    Of course, if no SSH daemon is available on the server you can also copy
    &amp; paste it directly into a shell.
diff --git a/nixos/modules/services/misc/zoneminder.nix b/nixos/modules/services/misc/zoneminder.nix
index 82d49cdedec..b0ee961c77f 100644
--- a/nixos/modules/services/misc/zoneminder.nix
+++ b/nixos/modules/services/misc/zoneminder.nix
@@ -50,7 +50,7 @@ let
     ZM_DB_TYPE=mysql
     ZM_DB_HOST=${cfg.database.host}
     ZM_DB_NAME=${cfg.database.name}
-    ZM_DB_USER=${if cfg.database.createLocally then user else cfg.database.username}
+    ZM_DB_USER=${cfg.database.username}
     ZM_DB_PASS=${cfg.database.password}
 
     # Web
@@ -155,6 +155,7 @@ in {
           default = "zmpass";
           description = ''
             Username for accessing the database.
+            Not used if <literal>createLocally</literal> is set.
           '';
         };
       };
@@ -189,6 +190,12 @@ in {
 
   config = lib.mkIf cfg.enable {
 
+    assertions = [
+      { assertion = cfg.database.createLocally -> cfg.database.username == user;
+        message = "services.zoneminder.database.username must be set to ${user} if services.zoneminder.database.createLocally is set true";
+      }
+    ];
+
     environment.etc = {
       "zoneminder/60-defaults.conf".source = defaultsFile;
       "zoneminder/80-nixos.conf".source    = configFile;
@@ -204,10 +211,9 @@ in {
       };
 
       mysql = lib.mkIf cfg.database.createLocally {
+        enable = true;
+        package = lib.mkDefault pkgs.mariadb;
         ensureDatabases = [ cfg.database.name ];
-        initialDatabases = [{
-          inherit (cfg.database) name; schema = "${pkg}/share/zoneminder/db/zm_create.sql";
-        }];
         ensureUsers = [{
           name = cfg.database.username;
           ensurePermissions = { "${cfg.database.name}.*" = "ALL PRIVILEGES"; };
@@ -315,11 +321,16 @@ in {
           procps
           psmisc
         ];
-        after = [ "mysql.service" "nginx.service" ];
+        after = [ "nginx.service" ] ++ lib.optional cfg.database.createLocally "mysql.service";
         wantedBy = [ "multi-user.target" ];
         restartTriggers = [ defaultsFile configFile ];
-        preStart = lib.mkIf useCustomDir ''
+        preStart = lib.optionalString useCustomDir ''
           install -dm775 -o ${user} -g ${group} ${cfg.storageDir}/{${lib.concatStringsSep "," libDirs}}
+        '' + lib.optionalString cfg.database.createLocally ''
+          if ! test -e "/var/lib/${dirName}/db-created"; then
+            ${config.services.mysql.package}/bin/mysql < ${pkg}/share/zoneminder/db/zm_create.sql
+            touch "/var/lib/${dirName}/db-created"
+          fi
         '';
         serviceConfig = {
           User = user;
diff --git a/nixos/modules/services/monitoring/alerta.nix b/nixos/modules/services/monitoring/alerta.nix
index 8f4258e26de..34f2d41706a 100644
--- a/nixos/modules/services/monitoring/alerta.nix
+++ b/nixos/modules/services/monitoring/alerta.nix
@@ -1,4 +1,4 @@
-{ options, config, lib, pkgs, ... }:
+{ config, lib, pkgs, ... }:
 
 with lib;
 
@@ -83,6 +83,10 @@ in
   };
 
   config = mkIf cfg.enable {
+    systemd.tmpfiles.rules = [
+      "d '${cfg.logDir}' - alerta alerta - -"
+    ];
+
     systemd.services.alerta = {
       description = "Alerta Monitoring System";
       wantedBy = [ "multi-user.target" ];
@@ -94,12 +98,7 @@ in
         ExecStart = "${pkgs.python36Packages.alerta-server}/bin/alertad run --port ${toString cfg.port} --host ${cfg.bind}";
         User = "alerta";
         Group = "alerta";
-        PermissionsStartOnly = true;
       };
-      preStart = ''
-        mkdir -p ${cfg.logDir}
-        chown alerta:alerta ${cfg.logDir}
-      '';
     };
 
     environment.systemPackages = [ pkgs.python36Packages.alerta ];
diff --git a/nixos/modules/services/monitoring/grafana-reporter.nix b/nixos/modules/services/monitoring/grafana-reporter.nix
index 827cf6322cf..b5a78e4583e 100644
--- a/nixos/modules/services/monitoring/grafana-reporter.nix
+++ b/nixos/modules/services/monitoring/grafana-reporter.nix
@@ -1,4 +1,4 @@
-{ options, config, lib, pkgs, ... }:
+{ config, lib, pkgs, ... }:
 
 with lib;
 
diff --git a/nixos/modules/services/monitoring/kapacitor.nix b/nixos/modules/services/monitoring/kapacitor.nix
index a4bdfa8f805..0f236d25c9e 100644
--- a/nixos/modules/services/monitoring/kapacitor.nix
+++ b/nixos/modules/services/monitoring/kapacitor.nix
@@ -1,4 +1,4 @@
-{ options, config, lib, pkgs, ... }:
+{ config, lib, pkgs, ... }:
 
 with lib;
 
@@ -163,6 +163,10 @@ in
   config = mkIf cfg.enable {
     environment.systemPackages = [ pkgs.kapacitor ];
 
+    systemd.tmpfiles.rules = [
+      "d '${cfg.dataDir}' - ${cfg.user} ${cfg.group} - -"
+    ];
+
     systemd.services.kapacitor = {
       description = "Kapacitor Real-Time Stream Processing Engine";
       wantedBy = [ "multi-user.target" ];
@@ -171,12 +175,7 @@ in
         ExecStart = "${pkgs.kapacitor}/bin/kapacitord -config ${kapacitorConf}";
         User = "kapacitor";
         Group = "kapacitor";
-        PermissionsStartOnly = true;
       };
-      preStart = ''
-        mkdir -p ${cfg.dataDir}
-        chown ${cfg.user}:${cfg.group} ${cfg.dataDir}
-      '';
     };
 
     users.users.kapacitor = {
diff --git a/nixos/modules/services/monitoring/netdata.nix b/nixos/modules/services/monitoring/netdata.nix
index a49555cf677..12a0961c406 100644
--- a/nixos/modules/services/monitoring/netdata.nix
+++ b/nixos/modules/services/monitoring/netdata.nix
@@ -143,7 +143,6 @@ in {
         User = cfg.user;
         Group = cfg.group;
         Environment="PYTHONPATH=${pkgs.netdata}/libexec/netdata/python.d/python_modules";
-        PermissionsStartOnly = true;
         ExecStart = "${pkgs.netdata}/bin/netdata -D -c ${configFile}";
         TimeoutStopSec = 60;
       };
diff --git a/nixos/modules/services/monitoring/prometheus/exporters.xml b/nixos/modules/services/monitoring/prometheus/exporters.xml
index 7a0a1bdf2c1..81ac998729b 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters.xml
+++ b/nixos/modules/services/monitoring/prometheus/exporters.xml
@@ -112,65 +112,65 @@
      directory, which will be called postfix.nix and contains all exporter
      specific options and configuration:
 <programlisting>
-        # nixpgs/nixos/modules/services/prometheus/exporters/postfix.nix
-        { config, lib, pkgs }:
+# nixpgs/nixos/modules/services/prometheus/exporters/postfix.nix
+{ config, lib, pkgs }:
 
-        with lib;
+with lib;
 
-        let
-          # for convenience we define cfg here
-          cfg = config.services.prometheus.exporters.postfix;
-        in
-        {
-          port = 9154; # The postfix exporter listens on this port by default
+let
+  # for convenience we define cfg here
+  cfg = config.services.prometheus.exporters.postfix;
+in
+{
+  port = 9154; # The postfix exporter listens on this port by default
 
-          # `extraOpts` is an attribute set which contains additional options
-          # (and optional overrides for default options).
-          # Note that this attribute is optional.
-          extraOpts = {
-            telemetryPath = mkOption {
-              type = types.str;
-              default = "/metrics";
-              description = ''
-                Path under which to expose metrics.
-              '';
-            };
-            logfilePath = mkOption {
-              type = types.path;
-              default = /var/log/postfix_exporter_input.log;
-              example = /var/log/mail.log;
-              description = ''
-                Path where Postfix writes log entries.
-                This file will be truncated by this exporter!
-              '';
-            };
-            showqPath = mkOption {
-              type = types.path;
-              default = /var/spool/postfix/public/showq;
-              example = /var/lib/postfix/queue/public/showq;
-              description = ''
-                Path at which Postfix places its showq socket.
-              '';
-            };
-          };
+  # `extraOpts` is an attribute set which contains additional options
+  # (and optional overrides for default options).
+  # Note that this attribute is optional.
+  extraOpts = {
+    telemetryPath = mkOption {
+      type = types.str;
+      default = "/metrics";
+      description = ''
+        Path under which to expose metrics.
+      '';
+    };
+    logfilePath = mkOption {
+      type = types.path;
+      default = /var/log/postfix_exporter_input.log;
+      example = /var/log/mail.log;
+      description = ''
+        Path where Postfix writes log entries.
+        This file will be truncated by this exporter!
+      '';
+    };
+    showqPath = mkOption {
+      type = types.path;
+      default = /var/spool/postfix/public/showq;
+      example = /var/lib/postfix/queue/public/showq;
+      description = ''
+        Path at which Postfix places its showq socket.
+      '';
+    };
+  };
 
-          # `serviceOpts` is an attribute set which contains configuration
-          # for the exporter's systemd service. One of
-          # `serviceOpts.script` and `serviceOpts.serviceConfig.ExecStart`
-          # has to be specified here. This will be merged with the default
-          # service confiuration.
-          serviceOpts = {
-            serviceConfig = {
-              ExecStart = ''
-                ${pkgs.prometheus-postfix-exporter}/bin/postfix_exporter \
-                  --web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
-                  --web.telemetry-path ${cfg.telemetryPath} \
-                  ${concatStringsSep " \\\n  " cfg.extraFlags}
-              '';
-            };
-          };
-        }
-      </programlisting>
+  # `serviceOpts` is an attribute set which contains configuration
+  # for the exporter's systemd service. One of
+  # `serviceOpts.script` and `serviceOpts.serviceConfig.ExecStart`
+  # has to be specified here. This will be merged with the default
+  # service confiuration.
+  serviceOpts = {
+    serviceConfig = {
+      ExecStart = ''
+        ${pkgs.prometheus-postfix-exporter}/bin/postfix_exporter \
+          --web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
+          --web.telemetry-path ${cfg.telemetryPath} \
+          ${concatStringsSep " \\\n  " cfg.extraFlags}
+      '';
+    };
+  };
+}
+</programlisting>
     </para>
    </listitem>
    <listitem>
diff --git a/nixos/modules/services/monitoring/prometheus/exporters/node.nix b/nixos/modules/services/monitoring/prometheus/exporters/node.nix
index ee7bf39f199..8c4128f9b63 100644
--- a/nixos/modules/services/monitoring/prometheus/exporters/node.nix
+++ b/nixos/modules/services/monitoring/prometheus/exporters/node.nix
@@ -32,8 +32,7 @@ in
         ${pkgs.prometheus-node-exporter}/bin/node_exporter \
           ${concatMapStringsSep " " (x: "--collector." + x) cfg.enabledCollectors} \
           ${concatMapStringsSep " " (x: "--no-collector." + x) cfg.disabledCollectors} \
-          --web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
-          ${concatStringsSep " \\\n  " cfg.extraFlags}
+          --web.listen-address ${cfg.listenAddress}:${toString cfg.port} ${concatStringsSep " " cfg.extraFlags}
       '';
     };
   };
diff --git a/nixos/modules/services/monitoring/riemann-dash.nix b/nixos/modules/services/monitoring/riemann-dash.nix
index 7eb4d888b0c..16eb8300850 100644
--- a/nixos/modules/services/monitoring/riemann-dash.nix
+++ b/nixos/modules/services/monitoring/riemann-dash.nix
@@ -59,18 +59,20 @@ in {
       group = "riemanndash";
     };
 
+    systemd.tmpfiles.rules = [
+      "d '${cfg.dataDir}' - riemanndash riemanndash - -"
+    ];
+
     systemd.services.riemann-dash = {
       wantedBy = [ "multi-user.target" ];
       wants = [ "riemann.service" ];
       after = [ "riemann.service" ];
       preStart = ''
-        mkdir -p ${cfg.dataDir}/config
-        chown -R riemanndash:riemanndash ${cfg.dataDir}
+        mkdir -p '${cfg.dataDir}/config'
       '';
       serviceConfig = {
         User = "riemanndash";
         ExecStart = "${launcher}/bin/riemann-dash";
-        PermissionsStartOnly = true;
       };
     };
 
diff --git a/nixos/modules/services/monitoring/riemann-tools.nix b/nixos/modules/services/monitoring/riemann-tools.nix
index 4e8832dadc5..9c400a1e3e4 100644
--- a/nixos/modules/services/monitoring/riemann-tools.nix
+++ b/nixos/modules/services/monitoring/riemann-tools.nix
@@ -54,7 +54,6 @@ in {
       serviceConfig = {
         User = "riemanntools";
         ExecStart = "${healthLauncher}/bin/riemann-health";
-        PermissionsStartOnly = true;
       };
     };
 
diff --git a/nixos/modules/services/monitoring/scollector.nix b/nixos/modules/services/monitoring/scollector.nix
index fbded746a5f..dc0899c7e68 100644
--- a/nixos/modules/services/monitoring/scollector.nix
+++ b/nixos/modules/services/monitoring/scollector.nix
@@ -116,7 +116,6 @@ in {
       path = [ pkgs.coreutils pkgs.iproute ];
 
       serviceConfig = {
-        PermissionsStartOnly = true;
         User = cfg.user;
         Group = cfg.group;
         ExecStart = "${cfg.package.bin}/bin/scollector -conf=${conf} ${lib.concatStringsSep " " cfg.extraOpts}";
diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix
index 10dc5831121..69368441c62 100644
--- a/nixos/modules/services/network-filesystems/samba.nix
+++ b/nixos/modules/services/network-filesystems/samba.nix
@@ -86,10 +86,10 @@ in
 
           <note>
             <para>If you use the firewall consider adding the following:</para>
-            <programlisting>
-              networking.firewall.allowedTCPPorts = [ 139 445 ];
-              networking.firewall.allowedUDPPorts = [ 137 138 ];
-            </programlisting>
+          <programlisting>
+            networking.firewall.allowedTCPPorts = [ 139 445 ];
+            networking.firewall.allowedUDPPorts = [ 137 138 ];
+          </programlisting>
           </note>
         '';
       };
diff --git a/nixos/modules/services/networking/aria2.nix b/nixos/modules/services/networking/aria2.nix
index 98eb0086101..53829bf1886 100644
--- a/nixos/modules/services/networking/aria2.nix
+++ b/nixos/modules/services/networking/aria2.nix
@@ -102,22 +102,19 @@ in
 
     users.groups.aria2.gid = config.ids.gids.aria2;
 
+    systemd.tmpfiles.rules = [
+      "d '${homeDir}' 0770 aria2 aria2 - -"
+      "d '${config.services.aria2.downloadDir}' 0770 aria2 aria2 - -"
+    ];
+
     systemd.services.aria2 = {
       description = "aria2 Service";
       after = [ "local-fs.target" "network.target" ];
       wantedBy = [ "multi-user.target" ];
       preStart = ''
-        mkdir -m 0770 -p "${homeDir}"
-        chown aria2:aria2 "${homeDir}"
-        if [[ ! -d "${config.services.aria2.downloadDir}" ]]
-        then
-          mkdir -m 0770 -p "${config.services.aria2.downloadDir}"
-          chown aria2:aria2 "${config.services.aria2.downloadDir}"
-        fi
         if [[ ! -e "${sessionFile}" ]]
         then
           touch "${sessionFile}"
-          chown aria2:aria2 "${sessionFile}"
         fi
         cp -f "${settingsFile}" "${settingsDir}/aria2.conf"
       '';
@@ -128,7 +125,6 @@ in
         ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
         User = "aria2";
         Group = "aria2";
-        PermissionsStartOnly = true;
       };
     };
   };
diff --git a/nixos/modules/services/networking/autossh.nix b/nixos/modules/services/networking/autossh.nix
index 9ea17469870..a098a155e99 100644
--- a/nixos/modules/services/networking/autossh.nix
+++ b/nixos/modules/services/networking/autossh.nix
@@ -99,7 +99,6 @@ in
 
               serviceConfig = {
                   User = "${s.user}";
-                  PermissionsStartOnly = true;
                   # AutoSSH may exit with 0 code if the SSH session was
                   # gracefully terminated by either local or remote side.
                   Restart = "on-success";
diff --git a/nixos/modules/services/networking/avahi-daemon.nix b/nixos/modules/services/networking/avahi-daemon.nix
index 4c91a0c415b..ddcfe3d77e2 100644
--- a/nixos/modules/services/networking/avahi-daemon.nix
+++ b/nixos/modules/services/networking/avahi-daemon.nix
@@ -1,10 +1,8 @@
-# Avahi daemon.
 { config, lib, pkgs, ... }:
 
 with lib;
 
 let
-
   cfg = config.services.avahi;
 
   yesNo = yes : if yes then "yes" else "no";
@@ -39,215 +37,245 @@ let
     enable-reflector=${yesNo reflector}
     ${extraConfig}
   '';
-
 in
-
 {
+  options.services.avahi = {
+    enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Whether to run the Avahi daemon, which allows Avahi clients
+        to use Avahi's service discovery facilities and also allows
+        the local machine to advertise its presence and services
+        (through the mDNS responder implemented by `avahi-daemon').
+      '';
+    };
 
-  ###### interface
+    hostName = mkOption {
+      type = types.str;
+      default = config.networking.hostName;
+      defaultText = literalExample "config.networking.hostName";
+      description = ''
+        Host name advertised on the LAN. If not set, avahi will use the value
+        of <option>config.networking.hostName</option>.
+      '';
+    };
 
-  options = {
+    domainName = mkOption {
+      type = types.str;
+      default = "local";
+      description = ''
+        Domain name for all advertisements.
+      '';
+    };
 
-    services.avahi = {
+    browseDomains = mkOption {
+      type = types.listOf types.str;
+      default = [ ];
+      example = [ "0pointer.de" "zeroconf.org" ];
+      description = ''
+        List of non-local DNS domains to be browsed.
+      '';
+    };
 
-      enable = mkOption {
-        default = false;
-        description = ''
-          Whether to run the Avahi daemon, which allows Avahi clients
-          to use Avahi's service discovery facilities and also allows
-          the local machine to advertise its presence and services
-          (through the mDNS responder implemented by `avahi-daemon').
-        '';
-      };
+    ipv4 = mkOption {
+      type = types.bool;
+      default = true;
+      description = "Whether to use IPv4.";
+    };
 
-      hostName = mkOption {
-        type = types.str;
-        description = ''
-          Host name advertised on the LAN. If not set, avahi will use the value
-          of config.networking.hostName.
-        '';
-      };
+    ipv6 = mkOption {
+      type = types.bool;
+      default = false;
+      description = "Whether to use IPv6.";
+    };
 
-      domainName = mkOption {
-        type = types.str;
-        default = "local";
-        description = ''
-          Domain name for all advertisements.
-        '';
-      };
+    interfaces = mkOption {
+      type = types.nullOr (types.listOf types.str);
+      default = null;
+      description = ''
+        List of network interfaces that should be used by the <command>avahi-daemon</command>.
+        Other interfaces will be ignored. If <literal>null</literal>, all local interfaces
+        except loopback and point-to-point will be used.
+      '';
+    };
 
-      browseDomains = mkOption {
-        default = [ ];
-        example = [ "0pointer.de" "zeroconf.org" ];
-        description = ''
-          List of non-local DNS domains to be browsed.
-        '';
-      };
+    openFirewall = mkOption {
+      type = types.bool;
+      default = true;
+      description = ''
+        Whether to open the firewall for UDP port 5353.
+      '';
+    };
 
-      ipv4 = mkOption {
-        default = true;
-        description = ''Whether to use IPv4'';
-      };
+    allowPointToPoint = mkOption {
+      type = types.bool;
+      default = false;
+      description= ''
+        Whether to use POINTTOPOINT interfaces. Might make mDNS unreliable due to usually large
+        latencies with such links and opens a potential security hole by allowing mDNS access from Internet
+        connections.
+      '';
+    };
 
-      ipv6 = mkOption {
-        default = false;
-        description = ''Whether to use IPv6'';
-      };
+    wideArea = mkOption {
+      type = types.bool;
+      default = true;
+      description = "Whether to enable wide-area service discovery.";
+    };
 
-      interfaces = mkOption {
-        type = types.nullOr (types.listOf types.str);
-        default = null;
-        description = ''
-          List of network interfaces that should be used by the <command>avahi-daemon</command>.
-          Other interfaces will be ignored. If <literal>null</literal> all local interfaces
-          except loopback and point-to-point will be used.
-        '';
-      };
+    reflector = mkOption {
+      type = types.bool;
+      default = false;
+      description = "Reflect incoming mDNS requests to all allowed network interfaces.";
+    };
 
-      allowPointToPoint = mkOption {
-        default = false;
-        description= ''
-          Whether to use POINTTOPOINT interfaces. Might make mDNS unreliable due to usually large
-          latencies with such links and opens a potential security hole by allowing mDNS access from Internet
-          connections. Use with care and YMMV!
-        '';
-      };
+    extraServiceFiles = mkOption {
+      type = with types; attrsOf (either str path);
+      default = {};
+      example = literalExample ''
+        {
+          ssh = "''${pkgs.avahi}/etc/avahi/services/ssh.service";
+          smb = '''
+            <?xml version="1.0" standalone='no'?><!--*-nxml-*-->
+            <!DOCTYPE service-group SYSTEM "avahi-service.dtd">
+            <service-group>
+              <name replace-wildcards="yes">%h</name>
+              <service>
+                <type>_smb._tcp</type>
+                <port>445</port>
+              </service>
+            </service-group>
+          ''';
+        }
+      '';
+      description = ''
+        Specify custom service definitions which are placed in the avahi service directory.
+        See the <citerefentry><refentrytitle>avahi.service</refentrytitle>
+        <manvolnum>5</manvolnum></citerefentry> manpage for detailed information.
+      '';
+    };
 
-      wideArea = mkOption {
-        default = true;
-        description = ''Whether to enable wide-area service discovery.'';
+    publish = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to allow publishing in general.";
       };
 
-      reflector = mkOption {
+      userServices = mkOption {
+        type = types.bool;
         default = false;
-        description = ''Reflect incoming mDNS requests to all allowed network interfaces.'';
+        description = "Whether to publish user services. Will set <literal>addresses=true</literal>.";
       };
 
-      publish = {
-        enable = mkOption {
-          default = false;
-          description = ''Whether to allow publishing in general.'';
-        };
-
-        userServices = mkOption {
-          default = false;
-          description = ''Whether to publish user services. Will set <literal>addresses=true</literal>.'';
-        };
-
-        addresses = mkOption {
-          default = false;
-          description = ''Whether to register mDNS address records for all local IP addresses.'';
-        };
-
-        hinfo = mkOption {
-          default = false;
-          description = ''
-            Whether to register an mDNS HINFO record which contains information about the
-            local operating system and CPU.
-          '';
-        };
-
-        workstation = mkOption {
-          default = false;
-          description = ''Whether to register a service of type "_workstation._tcp" on the local LAN.'';
-        };
-
-        domain = mkOption {
-          default = false;
-          description = ''Whether to announce the locally used domain name for browsing by other hosts.'';
-        };
-
+      addresses = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to register mDNS address records for all local IP addresses.";
       };
 
-      nssmdns = mkOption {
+      hinfo = mkOption {
+        type = types.bool;
         default = false;
         description = ''
-          Whether to enable the mDNS NSS (Name Service Switch) plug-in.
-          Enabling it allows applications to resolve names in the `.local'
-          domain by transparently querying the Avahi daemon.
+          Whether to register a mDNS HINFO record which contains information about the
+          local operating system and CPU.
         '';
       };
 
-      cacheEntriesMax = mkOption {
-        default = null;
-        type = types.nullOr types.int;
+      workstation = mkOption {
+        type = types.bool;
+        default = false;
         description = ''
-          Number of resource records to be cached per interface. Use 0 to
-          disable caching. Avahi daemon defaults to 4096 if not set.
+          Whether to register a service of type "_workstation._tcp" on the local LAN.
         '';
       };
 
-      extraConfig = mkOption {
-        default = "";
-        type = types.lines;
-        description = ''
-          Extra config to append to avahi-daemon.conf.
-        '';
+      domain = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to announce the locally used domain name for browsing by other hosts.";
       };
-
     };
 
-  };
+    nssmdns = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Whether to enable the mDNS NSS (Name Service Switch) plug-in.
+        Enabling it allows applications to resolve names in the `.local'
+        domain by transparently querying the Avahi daemon.
+      '';
+    };
 
+    cacheEntriesMax = mkOption {
+      type = types.nullOr types.int;
+      default = null;
+      description = ''
+        Number of resource records to be cached per interface. Use 0 to
+        disable caching. Avahi daemon defaults to 4096 if not set.
+      '';
+    };
 
-  ###### implementation
+    extraConfig = mkOption {
+      type = types.lines;
+      default = "";
+      description = ''
+        Extra config to append to avahi-daemon.conf.
+      '';
+    };
+  };
 
   config = mkIf cfg.enable {
+    users.users.avahi = {
+      description = "avahi-daemon privilege separation user";
+      home = "/var/empty";
+      group = "avahi";
+      isSystemUser = true;
+    };
 
-    services.avahi.hostName = mkDefault config.networking.hostName;
-
-    users.users = singleton
-      { name = "avahi";
-        uid = config.ids.uids.avahi;
-        description = "`avahi-daemon' privilege separation user";
-        home = "/var/empty";
-      };
-
-    users.groups = singleton
-      { name = "avahi";
-        gid = config.ids.gids.avahi;
-      };
+    users.groups.avahi = {};
 
     system.nssModules = optional cfg.nssmdns pkgs.nssmdns;
 
     environment.systemPackages = [ pkgs.avahi ];
 
-    systemd.sockets.avahi-daemon =
-      { description = "Avahi mDNS/DNS-SD Stack Activation Socket";
-        listenStreams = [ "/run/avahi-daemon/socket" ];
-        wantedBy = [ "sockets.target" ];
-      };
+    environment.etc = (mapAttrs' (n: v: nameValuePair
+      "avahi/services/${n}.service"
+      { ${if types.path.check v then "source" else "text"} = v; }
+    ) cfg.extraServiceFiles);
 
-    systemd.services.avahi-daemon =
-      { description = "Avahi mDNS/DNS-SD Stack";
-        wantedBy = [ "multi-user.target" ];
-        requires = [ "avahi-daemon.socket" ];
+    systemd.sockets.avahi-daemon = {
+      description = "Avahi mDNS/DNS-SD Stack Activation Socket";
+      listenStreams = [ "/run/avahi-daemon/socket" ];
+      wantedBy = [ "sockets.target" ];
+    };
 
-        serviceConfig."NotifyAccess" = "main";
-        serviceConfig."BusName" = "org.freedesktop.Avahi";
-        serviceConfig."Type" = "dbus";
+    systemd.tmpfiles.rules = [ "d /run/avahi-daemon - avahi avahi -" ];
 
-        path = [ pkgs.coreutils pkgs.avahi ];
+    systemd.services.avahi-daemon = {
+      description = "Avahi mDNS/DNS-SD Stack";
+      wantedBy = [ "multi-user.target" ];
+      requires = [ "avahi-daemon.socket" ];
 
-        preStart = "mkdir -p /run/avahi-daemon";
+      # Make NSS modules visible so that `avahi_nss_support ()' can
+      # return a sensible value.
+      environment.LD_LIBRARY_PATH = config.system.nssModules.path;
 
-        script =
-          ''
-            # Make NSS modules visible so that `avahi_nss_support ()' can
-            # return a sensible value.
-            export LD_LIBRARY_PATH="${config.system.nssModules.path}"
+      path = [ pkgs.coreutils pkgs.avahi ];
 
-            exec ${pkgs.avahi}/sbin/avahi-daemon --syslog -f "${avahiDaemonConf}"
-          '';
+      serviceConfig = {
+        NotifyAccess = "main";
+        BusName = "org.freedesktop.Avahi";
+        Type = "dbus";
+        ExecStart = "${pkgs.avahi}/sbin/avahi-daemon --syslog -f ${avahiDaemonConf}";
       };
+    };
 
     services.dbus.enable = true;
     services.dbus.packages = [ pkgs.avahi ];
 
-    # Enabling Avahi without exposing it in the firewall doesn't make
-    # sense.
-    networking.firewall.allowedUDPPorts = [ 5353 ];
-
+    networking.firewall.allowedUDPPorts = mkIf cfg.openFirewall [ 5353 ];
   };
-
 }
diff --git a/nixos/modules/services/networking/bitcoind.nix b/nixos/modules/services/networking/bitcoind.nix
index e9426556459..d3501636b41 100644
--- a/nixos/modules/services/networking/bitcoind.nix
+++ b/nixos/modules/services/networking/bitcoind.nix
@@ -28,7 +28,7 @@ let
     "-datadir=${cfg.dataDir}"
     "-pid=${pidFile}"
   ];
-  hexStr = types.strMatching "[0-9a-f]+";
+
   rpcUserOpts = { name, ... }: {
     options = {
       name = mkOption {
diff --git a/nixos/modules/services/networking/charybdis.nix b/nixos/modules/services/networking/charybdis.nix
index 3d02dc8d137..e3aba063f87 100644
--- a/nixos/modules/services/networking/charybdis.nix
+++ b/nixos/modules/services/networking/charybdis.nix
@@ -83,6 +83,10 @@ in
         gid = config.ids.gids.ircd;
       };
 
+      systemd.tmpfiles.rules = [
+        "d ${cfg.statedir} - ${cfg.user} ${cfg.group} - -"
+      ];
+
       systemd.services.charybdis = {
         description = "Charybdis IRC daemon";
         wantedBy = [ "multi-user.target" ];
@@ -93,12 +97,7 @@ in
           ExecStart   = "${charybdis}/bin/charybdis -foreground -logfile /dev/stdout -configfile ${configFile}";
           Group = cfg.group;
           User = cfg.user;
-          PermissionsStartOnly = true; # preStart needs to run with root permissions
         };
-        preStart = ''
-          ${coreutils}/bin/mkdir -p ${cfg.statedir}
-          ${coreutils}/bin/chown ${cfg.user}:${cfg.group} ${cfg.statedir}
-        '';
       };
 
     }
diff --git a/nixos/modules/services/networking/ddclient.nix b/nixos/modules/services/networking/ddclient.nix
index 9a2e13e9553..04ce5ca3a87 100644
--- a/nixos/modules/services/networking/ddclient.nix
+++ b/nixos/modules/services/networking/ddclient.nix
@@ -20,8 +20,8 @@ let
     wildcard=YES
     quiet=${boolToStr cfg.quiet}
     verbose=${boolToStr cfg.verbose}
-    ${lib.concatStringsSep "," cfg.domains}
     ${cfg.extraConfig}
+    ${lib.concatStringsSep "," cfg.domains}
   '';
 
 in
diff --git a/nixos/modules/services/networking/dnscrypt-proxy.xml b/nixos/modules/services/networking/dnscrypt-proxy.xml
index f90eef69848..afc7880392a 100644
--- a/nixos/modules/services/networking/dnscrypt-proxy.xml
+++ b/nixos/modules/services/networking/dnscrypt-proxy.xml
@@ -18,7 +18,7 @@
    To enable the client proxy, set
 <programlisting>
 <xref linkend="opt-services.dnscrypt-proxy.enable"/> = true;
-    </programlisting>
+</programlisting>
   </para>
 
   <para>
@@ -36,7 +36,7 @@
    the other client to it:
 <programlisting>
 <xref linkend="opt-services.dnscrypt-proxy.localPort"/> = 43;
-    </programlisting>
+</programlisting>
   </para>
 
   <sect2 xml:id="sec-dnscrypt-proxy-forwarder-dsnmasq">
@@ -47,7 +47,7 @@
   <xref linkend="opt-services.dnsmasq.enable"/> = true;
   <xref linkend="opt-services.dnsmasq.servers"/> = [ "127.0.0.1#43" ];
 }
-    </programlisting>
+</programlisting>
    </para>
   </sect2>
 
@@ -59,7 +59,7 @@
   <xref linkend="opt-services.unbound.enable"/> = true;
   <xref linkend="opt-services.unbound.forwardAddresses"/> = [ "127.0.0.1@43" ];
 }
-    </programlisting>
+</programlisting>
    </para>
   </sect2>
  </sect1>
diff --git a/nixos/modules/services/networking/hostapd.nix b/nixos/modules/services/networking/hostapd.nix
index 7add48308f8..54a5bed2563 100644
--- a/nixos/modules/services/networking/hostapd.nix
+++ b/nixos/modules/services/networking/hostapd.nix
@@ -30,10 +30,11 @@ let
     ctrl_interface=/run/hostapd
     ctrl_interface_group=${cfg.group}
 
-    ${if cfg.wpa then ''
+    ${optionalString cfg.wpa ''
       wpa=2
       wpa_passphrase=${cfg.wpaPassphrase}
-      '' else ""}
+    ''}
+    ${optionalString cfg.noScan "noscan=1"}
 
     ${cfg.extraConfig}
   '' ;
@@ -69,6 +70,14 @@ in
         '';
       };
 
+      noScan = mkOption {
+        default = false;
+        description = ''
+          Do not scan for overlapping BSSs in HT40+/- mode.
+          Caution: turning this on will violate regulatory requirements!
+        '';
+      };
+
       driver = mkOption {
         default = "nl80211";
         example = "hostapd";
@@ -162,6 +171,7 @@ in
         after = [ "sys-subsystem-net-devices-${escapedInterface}.device" ];
         bindsTo = [ "sys-subsystem-net-devices-${escapedInterface}.device" ];
         requiredBy = [ "network-link-${cfg.interface}.service" ];
+        wantedBy = [ "multi-user.target" ];
 
         serviceConfig =
           { ExecStart = "${pkgs.hostapd}/bin/hostapd ${configFile}";
diff --git a/nixos/modules/services/networking/minidlna.nix b/nixos/modules/services/networking/minidlna.nix
index 1858f03cac1..ed0c1044a57 100644
--- a/nixos/modules/services/networking/minidlna.nix
+++ b/nixos/modules/services/networking/minidlna.nix
@@ -98,16 +98,10 @@ in
         wantedBy = [ "multi-user.target" ];
         after = [ "network.target" "local-fs.target" ];
 
-        preStart =
-          ''
-            mkdir -p /var/cache/minidlna
-            chown -R minidlna:minidlna /var/cache/minidlna
-          '';
-
         serviceConfig =
           { User = "minidlna";
             Group = "minidlna";
-            PermissionsStartOnly = true;
+            CacheDirectory = "minidlna";
             RuntimeDirectory = "minidlna";
             PIDFile = "/run/minidlna/pid";
             ExecStart =
diff --git a/nixos/modules/services/networking/quassel.nix b/nixos/modules/services/networking/quassel.nix
index b223a48e055..b495b3948fb 100644
--- a/nixos/modules/services/networking/quassel.nix
+++ b/nixos/modules/services/networking/quassel.nix
@@ -104,6 +104,10 @@ in
         gid = config.ids.gids.quassel;
       }];
 
+    systemd.tmpfiles.rules = [
+      "d '${cfg.dataDir}' - ${user} - - -"
+    ];
+
     systemd.services.quassel =
       { description = "Quassel IRC client daemon";
 
@@ -111,11 +115,6 @@ in
         after = [ "network.target" ] ++ optional config.services.postgresql.enable "postgresql.service"
                                      ++ optional config.services.mysql.enable "mysql.service";
 
-        preStart = ''
-          mkdir -p ${cfg.dataDir}
-          chown ${user} ${cfg.dataDir}
-        '';
-
         serviceConfig =
         {
           ExecStart = concatStringsSep " " ([
@@ -126,7 +125,6 @@ in
           ] ++ optional cfg.requireSSL "--require-ssl"
             ++ optional (cfg.certificateFile != null) "--ssl-cert=${cfg.certificateFile}");
           User = user;
-          PermissionsStartOnly = true;
         };
       };
 
diff --git a/nixos/modules/services/networking/smokeping.nix b/nixos/modules/services/networking/smokeping.nix
index fab3ed5bb39..c41d0edaf17 100644
--- a/nixos/modules/services/networking/smokeping.nix
+++ b/nixos/modules/services/networking/smokeping.nix
@@ -101,17 +101,17 @@ in
         '';
         example = literalExample ''
           # near constant pings.
-					step     = 30
-					pings    = 20
-					# consfn mrhb steps total
-					AVERAGE  0.5   1  10080
-					AVERAGE  0.5  12  43200
-							MIN  0.5  12  43200
-							MAX  0.5  12  43200
-					AVERAGE  0.5 144   7200
-							MAX  0.5 144   7200
-							MIN  0.5 144   7200
-				'';
+          step     = 30
+          pings    = 20
+          # consfn mrhb steps total
+          AVERAGE  0.5   1  10080
+          AVERAGE  0.5  12  43200
+              MIN  0.5  12  43200
+              MAX  0.5  12  43200
+          AVERAGE  0.5 144   7200
+              MAX  0.5 144   7200
+              MIN  0.5 144   7200
+        '';
         description = ''Configure the ping frequency and retention of the rrd files.
           Once set, changing the interval will require deletion or migration of all
           the collected data.'';
diff --git a/nixos/modules/services/networking/squid.nix b/nixos/modules/services/networking/squid.nix
index b220c21b604..9d063b92aa1 100644
--- a/nixos/modules/services/networking/squid.nix
+++ b/nixos/modules/services/networking/squid.nix
@@ -159,11 +159,10 @@ in
       serviceConfig = {
         Type="forking";
         PIDFile="/run/squid.pid";
-        PermissionsStartOnly = true;
         ExecStart  = "${pkgs.squid}/bin/squid -YCs -f ${squidConfig}";
       };
     };
 
   };
 
-}
\ No newline at end of file
+}
diff --git a/nixos/modules/services/networking/teamspeak3.nix b/nixos/modules/services/networking/teamspeak3.nix
index 9ea9c83e37c..fadb32dcd77 100644
--- a/nixos/modules/services/networking/teamspeak3.nix
+++ b/nixos/modules/services/networking/teamspeak3.nix
@@ -111,16 +111,15 @@ in
       gid = config.ids.gids.teamspeak;
     };
 
+    systemd.tmpfiles.rules = [
+      "d '${cfg.logPath}' - ${user} ${group} - -"
+    ];
+
     systemd.services.teamspeak3-server = {
       description = "Teamspeak3 voice communication server daemon";
       after = [ "network.target" ];
       wantedBy = [ "multi-user.target" ];
 
-      preStart = ''
-        mkdir -p ${cfg.logPath}
-        chown ${user}:${group} ${cfg.logPath}
-      '';
-
       serviceConfig = {
         ExecStart = ''
           ${ts3}/bin/ts3server \
@@ -135,7 +134,6 @@ in
         WorkingDirectory = cfg.dataDir;
         User = user;
         Group = group;
-        PermissionsStartOnly = true;
       };
     };
   };
diff --git a/nixos/modules/services/networking/unifi.nix b/nixos/modules/services/networking/unifi.nix
index c82e0af2803..9057a1e12b3 100644
--- a/nixos/modules/services/networking/unifi.nix
+++ b/nixos/modules/services/networking/unifi.nix
@@ -146,6 +146,11 @@ in
         where = where;
       }) mountPoints;
 
+    systemd.tmpfiles.rules = [
+      "e '${stateDir}' 0700 unifi - - -"
+      "e '${stateDir}/data' 0700 unifi - - -"
+    ];
+
     systemd.services.unifi = {
       description = "UniFi controller daemon";
       wantedBy = [ "multi-user.target" ];
@@ -157,14 +162,9 @@ in
       environment.LD_LIBRARY_PATH = with pkgs.stdenv; "${cc.cc.lib}/lib";
 
       preStart = ''
-        # Ensure privacy of state and data.
-        chown unifi "${stateDir}" "${stateDir}/data"
-        chmod 0700 "${stateDir}" "${stateDir}/data"
-
         # Create the volatile webapps
         rm -rf "${stateDir}/webapps"
         mkdir -p "${stateDir}/webapps"
-        chown unifi "${stateDir}/webapps"
         ln -s "${cfg.unifiPackage}/webapps/ROOT" "${stateDir}/webapps/ROOT"
       '';
 
@@ -177,7 +177,6 @@ in
         ExecStart = "${(removeSuffix "\n" cmd)} start";
         ExecStop = "${(removeSuffix "\n" cmd)} stop";
         User = "unifi";
-        PermissionsStartOnly = true;
         UMask = "0077";
         WorkingDirectory = "${stateDir}";
       };
diff --git a/nixos/modules/services/networking/zeronet.nix b/nixos/modules/services/networking/zeronet.nix
index 611a51c74ce..f4988a90268 100644
--- a/nixos/modules/services/networking/zeronet.nix
+++ b/nixos/modules/services/networking/zeronet.nix
@@ -86,20 +86,17 @@ in with lib; {
       '';
     };
 
+    systemd.tmpfiles.rules = [
+      "d '${cfg.dataDir}' 750 zeronet zeronet - -"
+      "d '${cfg.logDir}' 750 zeronet zeronet - -"
+    ];
+
     systemd.services.zeronet = {
       description = "zeronet";
       after = [ "network.target" (optionalString cfg.tor "tor.service") ];
       wantedBy = [ "multi-user.target" ];
 
-      preStart = ''
-        # Ensure folder exists or create it and permissions are correct
-        mkdir -p ${escapeShellArg cfg.dataDir} ${escapeShellArg cfg.logDir}
-        chmod 750 ${escapeShellArg cfg.dataDir} ${escapeShellArg cfg.logDir}
-        chown zeronet:zeronet ${escapeShellArg cfg.dataDir} ${escapeShellArg cfg.logDir}
-      '';
-
       serviceConfig = {
-        PermissionsStartOnly = true;
         PrivateTmp = "yes";
         User = "zeronet";
         Group = "zeronet";
diff --git a/nixos/modules/services/system/kerberos/default.nix b/nixos/modules/services/system/kerberos/default.nix
index 26ac85de402..c55241c4cff 100644
--- a/nixos/modules/services/system/kerberos/default.nix
+++ b/nixos/modules/services/system/kerberos/default.nix
@@ -1,4 +1,4 @@
-{pkgs, config, lib, ...}:
+{config, lib, ...}:
 
 let
   inherit (lib) mkOption mkIf types length attrNames;
diff --git a/nixos/modules/services/system/kerberos/heimdal.nix b/nixos/modules/services/system/kerberos/heimdal.nix
index d0f470f836e..f0e56c7951a 100644
--- a/nixos/modules/services/system/kerberos/heimdal.nix
+++ b/nixos/modules/services/system/kerberos/heimdal.nix
@@ -2,7 +2,7 @@
 
 let
   inherit (lib) mkIf concatStringsSep concatMapStrings toList mapAttrs
-    mapAttrsToList attrValues;
+    mapAttrsToList;
   cfg = config.services.kerberos_server;
   kerberos = config.krb5.kerberos;
   stateDir = "/var/heimdal";
diff --git a/nixos/modules/services/system/kerberos/mit.nix b/nixos/modules/services/system/kerberos/mit.nix
index a53d9dd0c6b..25d7d51e808 100644
--- a/nixos/modules/services/system/kerberos/mit.nix
+++ b/nixos/modules/services/system/kerberos/mit.nix
@@ -2,7 +2,7 @@
 
 let
   inherit (lib) mkIf concatStrings concatStringsSep concatMapStrings toList
-    mapAttrs mapAttrsToList attrValues;
+    mapAttrs mapAttrsToList;
   cfg = config.services.kerberos_server;
   kerberos = config.krb5.kerberos;
   stateDir = "/var/lib/krb5kdc";
diff --git a/nixos/modules/services/system/localtime.nix b/nixos/modules/services/system/localtime.nix
index 8e9286b9407..04595fc82fb 100644
--- a/nixos/modules/services/system/localtime.nix
+++ b/nixos/modules/services/system/localtime.nix
@@ -28,33 +28,16 @@ in {
       };
     };
 
-    # so polkit will pick up the rules
-    environment.systemPackages = [ pkgs.localtime ];
-
-    users.users = [{
-      name = "localtimed";
-      description = "Taskserver user";
-    }];
+    # We use the 'out' output, since localtime has its 'bin' output
+    # first, so that is what we get if we use the derivation bare.
+    # Install the polkit rules.
+    environment.systemPackages = [ pkgs.localtime.out ];
+    # Install the systemd unit.
+    systemd.packages = [ pkgs.localtime.out ];
 
     systemd.services.localtime = {
-      description = "localtime service";
       wantedBy = [ "multi-user.target" ];
-      partOf = [ "geoclue.service "];
-
-      serviceConfig = {
-        Restart                 = "on-failure";
-        # TODO: make it work with dbus
-        #DynamicUser             = true;
-        Nice                    = 10;
-        User                    = "localtimed";
-        PrivateTmp              = "yes";
-        PrivateDevices          = true;
-        PrivateNetwork          = "yes";
-        NoNewPrivileges         = "yes";
-        ProtectSystem           = "strict";
-        ProtectHome             = true;
-        ExecStart               = "${pkgs.localtime}/bin/localtimed";
-      };
+      serviceConfig.Restart = "on-failure";
     };
   };
 }
diff --git a/nixos/modules/services/web-apps/atlassian/confluence.nix b/nixos/modules/services/web-apps/atlassian/confluence.nix
index 15744d90cc7..cf163271d27 100644
--- a/nixos/modules/services/web-apps/atlassian/confluence.nix
+++ b/nixos/modules/services/web-apps/atlassian/confluence.nix
@@ -149,6 +149,17 @@ in
 
     users.groups."${cfg.group}" = {};
 
+    systemd.tmpfiles.rules = [
+      "d '${cfg.home}' - ${cfg.user} - - -"
+      "d /run/confluence - - - - -"
+
+      "L+ /run/confluence/home - - - - ${cfg.home}"
+      "L+ /run/confluence/logs - - - - ${cfg.home}/logs"
+      "L+ /run/confluence/temp - - - - ${cfg.home}/temp"
+      "L+ /run/confluence/work - - - - ${cfg.home}/work"
+      "L+ /run/confluence/server.xml - - - - ${cfg.home}/server.xml"
+    ];
+
     systemd.services.confluence = {
       description = "Atlassian Confluence";
 
@@ -167,12 +178,6 @@ in
       preStart = ''
         mkdir -p ${cfg.home}/{logs,work,temp,deploy}
 
-        mkdir -p /run/confluence
-        ln -sf ${cfg.home}/{logs,work,temp,server.xml} /run/confluence
-        ln -sf ${cfg.home} /run/confluence/home
-
-        chown ${cfg.user} ${cfg.home}
-
         sed -e 's,port="8090",port="${toString cfg.listenPort}" address="${cfg.listenAddress}",' \
         '' + (lib.optionalString cfg.proxy.enable ''
           -e 's,protocol="org.apache.coyote.http11.Http11NioProtocol",protocol="org.apache.coyote.http11.Http11NioProtocol" proxyName="${cfg.proxy.name}" proxyPort="${toString cfg.proxy.port}" scheme="${cfg.proxy.scheme}",' \
@@ -184,7 +189,6 @@ in
         User = cfg.user;
         Group = cfg.group;
         PrivateTmp = true;
-        PermissionsStartOnly = true;
         ExecStart = "${pkg}/bin/start-confluence.sh -fg";
         ExecStop = "${pkg}/bin/stop-confluence.sh";
       };
diff --git a/nixos/modules/services/web-apps/atlassian/crowd.nix b/nixos/modules/services/web-apps/atlassian/crowd.nix
index c144b21bdaf..020ca8d89db 100644
--- a/nixos/modules/services/web-apps/atlassian/crowd.nix
+++ b/nixos/modules/services/web-apps/atlassian/crowd.nix
@@ -117,6 +117,16 @@ in
 
     users.groups."${cfg.group}" = {};
 
+    systemd.tmpfiles.rules = [
+      "d '${cfg.home}' - ${cfg.user} ${cfg.group} - -"
+      "d /run/atlassian-crowd - - - - -"
+
+      "L+ /run/atlassian-crowd/database - - - - ${cfg.home}/database"
+      "L+ /run/atlassian-crowd/logs - - - - ${cfg.home}/logs"
+      "L+ /run/atlassian-crowd/work - - - - ${cfg.home}/work"
+      "L+ /run/atlassian-crowd/server.xml - - - - ${cfg.home}/server.xml"
+    ];
+
     systemd.services.atlassian-crowd = {
       description = "Atlassian Crowd";
 
@@ -136,12 +146,6 @@ in
         rm -rf ${cfg.home}/work
         mkdir -p ${cfg.home}/{logs,database,work}
 
-        mkdir -p /run/atlassian-crowd
-        ln -sf ${cfg.home}/{database,logs,work,server.xml} /run/atlassian-crowd
-
-        chown ${cfg.user}:${cfg.group} ${cfg.home}
-        chown ${cfg.user}:${cfg.group} ${cfg.home}/{logs,database,work}
-
         sed -e 's,port="8095",port="${toString cfg.listenPort}" address="${cfg.listenAddress}",' \
         '' + (lib.optionalString cfg.proxy.enable ''
           -e 's,compression="on",compression="off" protocol="HTTP/1.1" proxyName="${cfg.proxy.name}" proxyPort="${toString cfg.proxy.port}" scheme="${cfg.proxy.scheme}" secure="${boolToString cfg.proxy.secure}",' \
@@ -153,7 +157,6 @@ in
         User = cfg.user;
         Group = cfg.group;
         PrivateTmp = true;
-        PermissionsStartOnly = true;
         ExecStart = "${pkg}/start_crowd.sh -fg";
       };
     };
diff --git a/nixos/modules/services/web-apps/atlassian/jira.nix b/nixos/modules/services/web-apps/atlassian/jira.nix
index 0b3a5722d6c..b0019e77ac2 100644
--- a/nixos/modules/services/web-apps/atlassian/jira.nix
+++ b/nixos/modules/services/web-apps/atlassian/jira.nix
@@ -155,6 +155,17 @@ in
 
     users.groups."${cfg.group}" = {};
 
+    systemd.tmpfiles.rules = [
+      "d '${cfg.home}' - ${cfg.user} - - -"
+      "d /run/atlassian-jira - - - - -"
+
+      "L+ /run/atlassian-jira/home - - - - ${cfg.home}"
+      "L+ /run/atlassian-jira/logs - - - - ${cfg.home}/logs"
+      "L+ /run/atlassian-jira/work - - - - ${cfg.home}/work"
+      "L+ /run/atlassian-jira/temp - - - - ${cfg.home}/temp"
+      "L+ /run/atlassian-jira/server.xml - - - - ${cfg.home}/server.xml"
+    ];
+
     systemd.services.atlassian-jira = {
       description = "Atlassian JIRA";
 
@@ -174,12 +185,6 @@ in
       preStart = ''
         mkdir -p ${cfg.home}/{logs,work,temp,deploy}
 
-        mkdir -p /run/atlassian-jira
-        ln -sf ${cfg.home}/{logs,work,temp,server.xml} /run/atlassian-jira
-        ln -sf ${cfg.home} /run/atlassian-jira/home
-
-        chown ${cfg.user} ${cfg.home}
-
         sed -e 's,port="8080",port="${toString cfg.listenPort}" address="${cfg.listenAddress}",' \
         '' + (lib.optionalString cfg.proxy.enable ''
           -e 's,protocol="HTTP/1.1",protocol="HTTP/1.1" proxyName="${cfg.proxy.name}" proxyPort="${toString cfg.proxy.port}" scheme="${cfg.proxy.scheme}" secure="${toString cfg.proxy.secure}",' \
@@ -191,7 +196,6 @@ in
         User = cfg.user;
         Group = cfg.group;
         PrivateTmp = true;
-        PermissionsStartOnly = true;
         ExecStart = "${pkg}/bin/start-jira.sh -fg";
         ExecStop = "${pkg}/bin/stop-jira.sh";
       };
diff --git a/nixos/modules/services/web-apps/frab.nix b/nixos/modules/services/web-apps/frab.nix
index fb95e024817..e885dc69b3c 100644
--- a/nixos/modules/services/web-apps/frab.nix
+++ b/nixos/modules/services/web-apps/frab.nix
@@ -182,16 +182,16 @@ in
 
     users.groups = [ { name = cfg.group; } ];
 
+    systemd.tmpfiles.rules = [
+      "d '${cfg.statePath}/system/attachments' - ${cfg.user} ${cfg.group} - -"
+    ];
+
     systemd.services.frab = {
       after = [ "network.target" "gitlab.service" ];
       wantedBy = [ "multi-user.target" ];
       environment = frabEnv;
 
       preStart = ''
-        mkdir -p ${cfg.statePath}/system/attachments
-        chown ${cfg.user}:${cfg.group} -R ${cfg.statePath}
-
-        mkdir /run/frab -p
         ln -sf ${pkgs.writeText "frab-database.yml" databaseConfig} /run/frab/database.yml
         ln -sf ${cfg.statePath}/system /run/frab/system
 
@@ -204,7 +204,6 @@ in
       '';
 
       serviceConfig = {
-        PermissionsStartOnly = true;
         PrivateTmp = true;
         PrivateDevices = true;
         Type = "simple";
@@ -213,6 +212,7 @@ in
         TimeoutSec = "300s";
         Restart = "on-failure";
         RestartSec = "10s";
+        RuntimeDirectory = "frab";
         WorkingDirectory = "${package}/share/frab";
         ExecStart = "${frab-rake}/bin/frab-bundle exec rails server " +
           "--binding=${cfg.listenAddress} --port=${toString cfg.listenPort}";
diff --git a/nixos/modules/services/web-apps/limesurvey.nix b/nixos/modules/services/web-apps/limesurvey.nix
index d68812dd45c..99a33b8371c 100644
--- a/nixos/modules/services/web-apps/limesurvey.nix
+++ b/nixos/modules/services/web-apps/limesurvey.nix
@@ -2,7 +2,7 @@
 
 let
 
-  inherit (lib) mkDefault mkEnableOption mkForce mkIf mkMerge mkOption;
+  inherit (lib) mkDefault mkEnableOption mkForce mkIf mkOption;
   inherit (lib) mapAttrs optional optionalString types;
 
   cfg = config.services.limesurvey;
diff --git a/nixos/modules/services/web-apps/matomo-doc.xml b/nixos/modules/services/web-apps/matomo-doc.xml
index 021a89be3f6..8485492c51c 100644
--- a/nixos/modules/services/web-apps/matomo-doc.xml
+++ b/nixos/modules/services/web-apps/matomo-doc.xml
@@ -21,18 +21,18 @@
    passwordless database authentication via the UNIX_SOCKET authentication
    plugin with the following SQL commands:
 <programlisting>
-        # For MariaDB
-        INSTALL PLUGIN unix_socket SONAME 'auth_socket';
-        CREATE DATABASE matomo;
-        CREATE USER 'matomo'@'localhost' IDENTIFIED WITH unix_socket;
-        GRANT ALL PRIVILEGES ON matomo.* TO 'matomo'@'localhost';
+# For MariaDB
+INSTALL PLUGIN unix_socket SONAME 'auth_socket';
+CREATE DATABASE matomo;
+CREATE USER 'matomo'@'localhost' IDENTIFIED WITH unix_socket;
+GRANT ALL PRIVILEGES ON matomo.* TO 'matomo'@'localhost';
 
-        # For MySQL
-        INSTALL PLUGIN auth_socket SONAME 'auth_socket.so';
-        CREATE DATABASE matomo;
-        CREATE USER 'matomo'@'localhost' IDENTIFIED WITH auth_socket;
-        GRANT ALL PRIVILEGES ON matomo.* TO 'matomo'@'localhost';
-   </programlisting>
+# For MySQL
+INSTALL PLUGIN auth_socket SONAME 'auth_socket.so';
+CREATE DATABASE matomo;
+CREATE USER 'matomo'@'localhost' IDENTIFIED WITH auth_socket;
+GRANT ALL PRIVILEGES ON matomo.* TO 'matomo'@'localhost';
+</programlisting>
    Then fill in <literal>matomo</literal> as database user and database name,
    and leave the password field blank. This authentication works by allowing
    only the <literal>matomo</literal> unix user to authenticate as the
diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix
index 35be5cb9712..9475af12fdd 100644
--- a/nixos/modules/services/web-apps/nextcloud.nix
+++ b/nixos/modules/services/web-apps/nextcloud.nix
@@ -1,4 +1,4 @@
-{ config, lib, pkgs, ... }@args:
+{ config, lib, pkgs, ... }:
 
 with lib;
 
diff --git a/nixos/modules/services/web-apps/tt-rss.nix b/nixos/modules/services/web-apps/tt-rss.nix
index 6afb193bb37..e59988ef7b2 100644
--- a/nixos/modules/services/web-apps/tt-rss.nix
+++ b/nixos/modules/services/web-apps/tt-rss.nix
@@ -15,7 +15,6 @@ let
     else cfg.database.port;
 
   poolName = "tt-rss";
-  phpfpmSocketName = "/run/phpfpm/${poolName}.sock";
 
   tt-rss-config = pkgs.writeText "config.php" ''
     <?php
diff --git a/nixos/modules/services/web-servers/lighttpd/cgit.nix b/nixos/modules/services/web-servers/lighttpd/cgit.nix
index 4ec4a5a3359..9f25dc34f3f 100644
--- a/nixos/modules/services/web-servers/lighttpd/cgit.nix
+++ b/nixos/modules/services/web-servers/lighttpd/cgit.nix
@@ -42,10 +42,10 @@ in
     configText = mkOption {
       default = "";
       example = ''
-        cache-size=1000
-        scan-path=/srv/git
         source-filter=''${pkgs.cgit}/lib/cgit/filters/syntax-highlighting.py
         about-filter=''${pkgs.cgit}/lib/cgit/filters/about-formatting.sh
+        cache-size=1000
+        scan-path=/srv/git
       '';
       type = types.lines;
       description = ''
diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix
index d6653a65a95..2b7fcb31404 100644
--- a/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixos/modules/services/web-servers/nginx/default.nix
@@ -269,17 +269,6 @@ let
       ${optionalString (config.proxyPass != null && cfg.recommendedProxySettings) "include ${recommendedProxyConfig};"}
     }
   '') (sortProperties (mapAttrsToList (k: v: v // { location = k; }) locations)));
-  mkBasicAuth = vhostName: authDef: let
-    htpasswdFile = pkgs.writeText "${vhostName}.htpasswd" (
-      concatStringsSep "\n" (mapAttrsToList (user: password: ''
-        ${user}:{PLAIN}${password}
-      '') authDef)
-    );
-  in ''
-    auth_basic secured;
-    auth_basic_user_file ${htpasswdFile};
-  '';
-
   mkHtpasswd = vhostName: authDef: pkgs.writeText "${vhostName}.htpasswd" (
     concatStringsSep "\n" (mapAttrsToList (user: password: ''
       ${user}:{PLAIN}${password}
diff --git a/nixos/modules/services/x11/desktop-managers/enlightenment.nix b/nixos/modules/services/x11/desktop-managers/enlightenment.nix
index 4da14694064..527e4b18045 100644
--- a/nixos/modules/services/x11/desktop-managers/enlightenment.nix
+++ b/nixos/modules/services/x11/desktop-managers/enlightenment.nix
@@ -34,7 +34,7 @@ in
       pkgs.gtk2 # To get GTK+'s themes.
       pkgs.tango-icon-theme
 
-      pkgs.gnome2.gnomeicontheme
+      pkgs.gnome2.gnome_icon_theme
       pkgs.xorg.xcursorthemes
     ];
 
diff --git a/nixos/modules/services/x11/desktop-managers/pantheon.nix b/nixos/modules/services/x11/desktop-managers/pantheon.nix
index 9a0f77a856a..41903b33fae 100644
--- a/nixos/modules/services/x11/desktop-managers/pantheon.nix
+++ b/nixos/modules/services/x11/desktop-managers/pantheon.nix
@@ -195,7 +195,7 @@ in
       ]);
 
     fonts.fonts = with pkgs; [
-      opensans-ttf
+      open-sans
       roboto-mono
       pantheon.elementary-redacted-script # needed by screenshot-tool
     ];
diff --git a/nixos/modules/services/x11/desktop-managers/xterm.nix b/nixos/modules/services/x11/desktop-managers/xterm.nix
index f386ebc4d3c..ea441fbbe71 100644
--- a/nixos/modules/services/x11/desktop-managers/xterm.nix
+++ b/nixos/modules/services/x11/desktop-managers/xterm.nix
@@ -5,6 +5,7 @@ with lib;
 let
 
   cfg = config.services.xserver.desktopManager.xterm;
+  xserverEnabled = config.services.xserver.enable;
 
 in
 
@@ -13,7 +14,8 @@ in
 
     services.xserver.desktopManager.xterm.enable = mkOption {
       type = types.bool;
-      default = true;
+      default = xserverEnabled;
+      defaultText = "config.services.xserver.enable";
       description = "Enable a xterm terminal as a desktop manager.";
     };
 
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index 0f057c4ab73..a1ed2fd1e97 100644
--- a/nixos/modules/services/x11/xserver.nix
+++ b/nixos/modules/services/x11/xserver.nix
@@ -4,8 +4,6 @@ with lib;
 
 let
 
-  kernelPackages = config.boot.kernelPackages;
-
   # Abbreviations.
   cfg = config.services.xserver;
   xorg = pkgs.xorg;
diff --git a/nixos/modules/system/boot/kernel.nix b/nixos/modules/system/boot/kernel.nix
index ab919099d11..ee43fe10023 100644
--- a/nixos/modules/system/boot/kernel.nix
+++ b/nixos/modules/system/boot/kernel.nix
@@ -196,7 +196,7 @@ in
     # (so you don't need to reboot to have changes take effect).
     boot.kernelParams =
       [ "loglevel=${toString config.boot.consoleLogLevel}" ] ++
-      optionals config.boot.vesa [ "vga=0x317" ];
+      optionals config.boot.vesa [ "vga=0x317" "nomodeset" ];
 
     boot.kernel.sysctl."kernel.printk" = mkDefault config.boot.consoleLogLevel;
 
diff --git a/nixos/modules/system/boot/kernel_config.nix b/nixos/modules/system/boot/kernel_config.nix
index fbbd0982b2c..a316782dfc5 100644
--- a/nixos/modules/system/boot/kernel_config.nix
+++ b/nixos/modules/system/boot/kernel_config.nix
@@ -9,7 +9,6 @@ let
   mergeAnswer = winners: locs: defs:
     let
       values = map (x: x.value) defs;
-      freeformAnswer = intersectLists values winners;
       inter = intersectLists values winners;
       winner = head winners;
     in
diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
index ebe37ca10a2..f48a085ce57 100644
--- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
+++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
@@ -133,7 +133,9 @@ def get_generations(profile=None):
         universal_newlines=True)
     gen_lines = gen_list.split('\n')
     gen_lines.pop()
-    return [ (profile, int(line.split()[0])) for line in gen_lines ]
+
+    configurationLimit = @configurationLimit@
+    return [ (profile, int(line.split()[0])) for line in gen_lines ][-configurationLimit:]
 
 def remove_old_entries(gens):
     rex_profile = re.compile("^@efiSysMountPoint@/loader/entries/nixos-(.*)-generation-.*\.conf$")
diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
index 3e39dc5dd39..910a602c61d 100644
--- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
+++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
@@ -22,7 +22,7 @@ let
 
     editor = if cfg.editor then "True" else "False";
 
-    inherit (cfg) consoleMode;
+    inherit (cfg) consoleMode configurationLimit;
 
     inherit (efi) efiSysMountPoint canTouchEfiVariables;
 
@@ -57,6 +57,16 @@ in {
       '';
     };
 
+    configurationLimit = mkOption {
+      default = 100;
+      example = 120;
+      type = types.int;
+      description = ''
+        Maximum of configurations in boot menu. Otherwise boot partition could
+        run out of disk space.
+      '';
+    };
+
     consoleMode = mkOption {
       default = "keep";
 
diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix
index 93bbd141284..22578b01260 100644
--- a/nixos/modules/tasks/filesystems/zfs.nix
+++ b/nixos/modules/tasks/filesystems/zfs.nix
@@ -314,10 +314,6 @@ in
           assertion = !cfgZfs.forceImportAll || cfgZfs.forceImportRoot;
           message = "If you enable boot.zfs.forceImportAll, you must also enable boot.zfs.forceImportRoot";
         }
-        {
-          assertion = cfgZfs.requestEncryptionCredentials -> cfgZfs.enableUnstable;
-          message = "This feature is only available for zfs unstable. Set the NixOS option boot.zfs.enableUnstable.";
-        }
       ];
 
       virtualisation.lxd.zfsSupport = true;
diff --git a/nixos/modules/virtualisation/anbox.nix b/nixos/modules/virtualisation/anbox.nix
index 9cb89e7b292..c63b971ead0 100644
--- a/nixos/modules/virtualisation/anbox.nix
+++ b/nixos/modules/virtualisation/anbox.nix
@@ -100,12 +100,7 @@ in
       wantedBy = [ "multi-user.target" ];
       after = [ "systemd-udev-settle.service" ];
       preStart = let
-        initsh = let
-          ip = cfg.ipv4.container.address;
-          gw = cfg.ipv4.gateway.address;
-          dns = cfg.ipv4.dns;
-        in
-        pkgs.writeText "nixos-init" (''
+        initsh = pkgs.writeText "nixos-init" (''
           #!/system/bin/sh
           setprop nixos.version ${config.system.nixos.version}
 
diff --git a/nixos/modules/virtualisation/cloudstack-config.nix b/nixos/modules/virtualisation/cloudstack-config.nix
index 81c54567627..78afebdc5dd 100644
--- a/nixos/modules/virtualisation/cloudstack-config.nix
+++ b/nixos/modules/virtualisation/cloudstack-config.nix
@@ -1,4 +1,4 @@
-{ config, lib, pkgs, ... }:
+{ lib, pkgs, ... }:
 
 with lib;
 
diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix
index 2235eec9d95..c10e2b162cc 100644
--- a/nixos/modules/virtualisation/containers.nix
+++ b/nixos/modules/virtualisation/containers.nix
@@ -445,7 +445,7 @@ in
       type = types.bool;
       default = !config.boot.isContainer;
       description = ''
-        Whether to enable support for nixos containers.
+        Whether to enable support for NixOS containers.
       '';
     };
 
diff --git a/nixos/modules/virtualisation/docker-containers.nix b/nixos/modules/virtualisation/docker-containers.nix
index 3e882a1383f..59b0943f591 100644
--- a/nixos/modules/virtualisation/docker-containers.nix
+++ b/nixos/modules/virtualisation/docker-containers.nix
@@ -5,7 +5,7 @@ let
   cfg = config.docker-containers;
 
   dockerContainer =
-    { name, config, ... }: {
+    { ... }: {
 
       options = {
 
diff --git a/nixos/modules/virtualisation/google-compute-config.nix b/nixos/modules/virtualisation/google-compute-config.nix
index 2ee22b80f2f..5c59188b68b 100644
--- a/nixos/modules/virtualisation/google-compute-config.nix
+++ b/nixos/modules/virtualisation/google-compute-config.nix
@@ -2,7 +2,6 @@
 with lib;
 let
   gce = pkgs.google-compute-engine;
-  cfg = config.virtualisation.googleComputeImage;
 in
 {
   imports = [
diff --git a/nixos/modules/virtualisation/kvmgt.nix b/nixos/modules/virtualisation/kvmgt.nix
index 132815a0ad6..bfcf51d09c4 100644
--- a/nixos/modules/virtualisation/kvmgt.nix
+++ b/nixos/modules/virtualisation/kvmgt.nix
@@ -46,22 +46,24 @@ in {
       message = "KVMGT is not properly supported for kernels older than 4.16";
     };
     boot.kernelParams = [ "i915.enable_gvt=1" ];
+    systemd.paths = mapAttrs' (name: value:
+      nameValuePair "kvmgt-${name}" {
+        description = "KVMGT VGPU ${name} path";
+        wantedBy = [ "multi-user.target" ];
+        pathConfig = {
+          PathExists = "/sys/bus/pci/devices/${cfg.device}/mdev_supported_types/${name}/create";
+        };
+      }
+    ) cfg.vgpus;
     systemd.services = mapAttrs' (name: value:
       nameValuePair "kvmgt-${name}" {
         description = "KVMGT VGPU ${name}";
         serviceConfig = {
-          Type = "forking";
+          Type = "oneshot";
           RemainAfterExit = true;
-          Restart = "on-failure";
-          RestartSec = 5;
           ExecStart = "${pkgs.runtimeShell} -c 'echo ${value.uuid} > /sys/bus/pci/devices/${cfg.device}/mdev_supported_types/${name}/create'";
           ExecStop = "${pkgs.runtimeShell} -c 'echo 1 > /sys/bus/pci/devices/${cfg.device}/${value.uuid}/remove'";
         };
-        unitConfig = {
-          StartLimitBurst = 5;
-          StartLimitIntervalSec = 30;
-        };
-        wantedBy = [ "multi-user.target" ];
       }
     ) cfg.vgpus;
   };
diff --git a/nixos/modules/virtualisation/libvirtd.nix b/nixos/modules/virtualisation/libvirtd.nix
index f4d7af1664a..394b4ce5656 100644
--- a/nixos/modules/virtualisation/libvirtd.nix
+++ b/nixos/modules/virtualisation/libvirtd.nix
@@ -23,14 +23,16 @@ let
     ''}
     ${cfg.qemuVerbatimConfig}
   '';
+  dirName = "libvirt";
+  subDirs = list: [ dirName ] ++ map (e: "${dirName}/${e}") list;
 
 in {
 
   ###### interface
 
-  options = {
+  options.virtualisation.libvirtd = {
 
-    virtualisation.libvirtd.enable = mkOption {
+    enable = mkOption {
       type = types.bool;
       default = false;
       description = ''
@@ -41,7 +43,7 @@ in {
       '';
     };
 
-    virtualisation.libvirtd.qemuPackage = mkOption {
+    qemuPackage = mkOption {
       type = types.package;
       default = pkgs.qemu;
       description = ''
@@ -51,7 +53,7 @@ in {
       '';
     };
 
-    virtualisation.libvirtd.extraConfig = mkOption {
+    extraConfig = mkOption {
       type = types.lines;
       default = "";
       description = ''
@@ -60,7 +62,7 @@ in {
       '';
     };
 
-    virtualisation.libvirtd.qemuRunAsRoot = mkOption {
+    qemuRunAsRoot = mkOption {
       type = types.bool;
       default = true;
       description = ''
@@ -72,7 +74,7 @@ in {
       '';
     };
 
-    virtualisation.libvirtd.qemuVerbatimConfig = mkOption {
+    qemuVerbatimConfig = mkOption {
       type = types.lines;
       default = ''
         namespaces = []
@@ -84,7 +86,7 @@ in {
       '';
     };
 
-    virtualisation.libvirtd.qemuOvmf = mkOption {
+    qemuOvmf = mkOption {
       type = types.bool;
       default = true;
       description = ''
@@ -93,7 +95,7 @@ in {
       '';
     };
 
-    virtualisation.libvirtd.extraOptions = mkOption {
+    extraOptions = mkOption {
       type = types.listOf types.str;
       default = [ ];
       example = [ "--verbose" ];
@@ -102,7 +104,7 @@ in {
       '';
     };
 
-    virtualisation.libvirtd.onShutdown = mkOption {
+    onShutdown = mkOption {
       type = types.enum ["shutdown" "suspend" ];
       default = "suspend";
       description = ''
@@ -113,6 +115,14 @@ in {
       '';
     };
 
+    allowedBridges = mkOption {
+      type = types.listOf types.str;
+      default = [ "virbr0" ];
+      description = ''
+        List of bridge devices that can be used by qemu:///session
+      '';
+    };
+
   };
 
 
@@ -120,7 +130,12 @@ in {
 
   config = mkIf cfg.enable {
 
-    environment.systemPackages = with pkgs; [ libvirt libressl.nc cfg.qemuPackage ];
+    environment = {
+      # this file is expected in /etc/qemu and not sysconfdir (/var/lib)
+      etc."qemu/bridge.conf".text = lib.concatMapStringsSep "\n" (e:
+        "allow ${e}") cfg.allowedBridges;
+      systemPackages = with pkgs; [ libvirt libressl.nc cfg.qemuPackage ];
+    };
 
     boot.kernelModules = [ "tun" ];
 
@@ -134,30 +149,15 @@ in {
       group = "qemu-libvirtd";
     };
 
-    systemd.packages = [ pkgs.libvirt ];
-
-    systemd.services.libvirtd = {
-      description = "Libvirt Virtual Machine Management Daemon";
-
-      wantedBy = [ "multi-user.target" ];
-      after = [ "systemd-udev-settle.service" ]
-              ++ optional vswitch.enable "vswitchd.service";
-
-      environment.LIBVIRTD_ARGS = ''--config "${configFile}" ${concatStringsSep " " cfg.extraOptions}'';
-
-      path = [ cfg.qemuPackage ] # libvirtd requires qemu-img to manage disk images
-             ++ optional vswitch.enable vswitch.package;
-
-      preStart = ''
-        mkdir -p /var/log/libvirt/qemu -m 755
-        rm -f /var/run/libvirtd.pid
-
-        mkdir -p /var/lib/libvirt
-        mkdir -p /var/lib/libvirt/dnsmasq
+    security.wrappers.qemu-bridge-helper = {
+      source = "/run/${dirName}/nix-helpers/qemu-bridge-helper";
+    };
 
-        chmod 755 /var/lib/libvirt
-        chmod 755 /var/lib/libvirt/dnsmasq
+    systemd.packages = [ pkgs.libvirt ];
 
+    systemd.services.libvirtd-config = {
+      description = "Libvirt Virtual Machine Management Daemon - configuration";
+      script = ''
         # Copy default libvirt network config .xml files to /var/lib
         # Files modified by the user will not be overwritten
         for i in $(cd ${pkgs.libvirt}/var/lib && echo \
@@ -169,22 +169,46 @@ in {
         done
 
         # Copy generated qemu config to libvirt directory
-        cp -f ${qemuConfigFile} /var/lib/libvirt/qemu.conf
+        cp -f ${qemuConfigFile} /var/lib/${dirName}/qemu.conf
 
         # stable (not GC'able as in /nix/store) paths for using in <emulator> section of xml configs
-        mkdir -p /run/libvirt/nix-emulators
         for emulator in ${pkgs.libvirt}/libexec/libvirt_lxc ${cfg.qemuPackage}/bin/qemu-kvm ${cfg.qemuPackage}/bin/qemu-system-*; do
-          ln -s --force "$emulator" /run/libvirt/nix-emulators/
+          ln -s --force "$emulator" /run/${dirName}/nix-emulators/
+        done
+
+        for helper in libexec/qemu-bridge-helper bin/qemu-pr-helper; do
+          ln -s --force ${cfg.qemuPackage}/$helper /run/${dirName}/nix-helpers/
         done
 
         ${optionalString cfg.qemuOvmf ''
-            mkdir -p /run/libvirt/nix-ovmf
-            ln -s --force ${pkgs.OVMF.fd}/FV/OVMF_CODE.fd /run/libvirt/nix-ovmf/
-            ln -s --force ${pkgs.OVMF.fd}/FV/OVMF_VARS.fd /run/libvirt/nix-ovmf/
+          ln -s --force ${pkgs.OVMF.fd}/FV/OVMF_CODE.fd /run/${dirName}/nix-ovmf/
+          ln -s --force ${pkgs.OVMF.fd}/FV/OVMF_VARS.fd /run/${dirName}/nix-ovmf/
         ''}
       '';
 
       serviceConfig = {
+        Type = "oneshot";
+        RuntimeDirectoryPreserve = "yes";
+        LogsDirectory = subDirs [ "qemu" ];
+        RuntimeDirectory = subDirs [ "nix-emulators" "nix-helpers" "nix-ovmf" ];
+        StateDirectory = subDirs [ "dnsmasq" ];
+      };
+    };
+
+    systemd.services.libvirtd = {
+      description = "Libvirt Virtual Machine Management Daemon";
+
+      wantedBy = [ "multi-user.target" ];
+      requires = [ "libvirtd-config.service" ];
+      after = [ "systemd-udev-settle.service" "libvirtd-config.service" ]
+              ++ optional vswitch.enable "vswitchd.service";
+
+      environment.LIBVIRTD_ARGS = ''--config "${configFile}" ${concatStringsSep " " cfg.extraOptions}'';
+
+      path = [ cfg.qemuPackage ] # libvirtd requires qemu-img to manage disk images
+             ++ optional vswitch.enable vswitch.package;
+
+      serviceConfig = {
         Type = "notify";
         KillMode = "process"; # when stopping, leave the VMs alone
         Restart = "no";
@@ -203,7 +227,7 @@ in {
     systemd.sockets.virtlogd = {
       description = "Virtual machine log manager socket";
       wantedBy = [ "sockets.target" ];
-      listenStreams = [ "/run/libvirt/virtlogd-sock" ];
+      listenStreams = [ "/run/${dirName}/virtlogd-sock" ];
     };
 
     systemd.services.virtlogd = {
@@ -215,7 +239,7 @@ in {
     systemd.sockets.virtlockd = {
       description = "Virtual machine lock manager socket";
       wantedBy = [ "sockets.target" ];
-      listenStreams = [ "/run/libvirt/virtlockd-sock" ];
+      listenStreams = [ "/run/${dirName}/virtlockd-sock" ];
     };
 
     systemd.services.virtlockd = {