summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/installation/installing.xml7
-rw-r--r--nixos/doc/manual/manual.xml4
-rw-r--r--nixos/lib/make-ext4-fs.nix7
-rw-r--r--nixos/modules/installer/cd-dvd/iso-image.nix2
-rw-r--r--nixos/modules/installer/cd-dvd/sd-image.nix11
-rw-r--r--nixos/modules/installer/netboot/netboot.nix3
-rw-r--r--nixos/modules/module-list.nix1
-rw-r--r--nixos/modules/profiles/all-hardware.nix2
-rw-r--r--nixos/modules/services/games/terraria.nix16
-rw-r--r--nixos/modules/services/hardware/undervolt.nix134
-rw-r--r--nixos/modules/services/misc/redmine.nix294
-rw-r--r--nixos/modules/services/networking/dhcpcd.nix3
-rw-r--r--nixos/modules/services/security/cfssl.nix4
-rw-r--r--nixos/modules/system/activation/top-level.nix6
-rw-r--r--nixos/modules/system/boot/loader/generations-dir/generations-dir.nix2
-rw-r--r--nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix2
-rw-r--r--nixos/modules/system/boot/networkd.nix8
-rw-r--r--nixos/release.nix4
-rw-r--r--nixos/tests/home-assistant.nix9
19 files changed, 339 insertions, 180 deletions
diff --git a/nixos/doc/manual/installation/installing.xml b/nixos/doc/manual/installation/installing.xml
index 6066d025adbf..6f8e0f613b19 100644
--- a/nixos/doc/manual/installation/installing.xml
+++ b/nixos/doc/manual/installation/installing.xml
@@ -326,10 +326,9 @@ Retype new UNIX password: ***
     </screen>
     <note>
      <para>
-      To prevent the password prompt, set
-      <code><xref linkend="opt-users.mutableUsers"/> = false;</code> in
-      <filename>configuration.nix</filename>, which allows unattended
-      installation necessary in automation.
+      For unattended installations, it is possible to use
+      <command>nixos-install --no-root-passwd</command>
+      in order to disable the password prompt entirely.
      </para>
     </note>
    </para>
diff --git a/nixos/doc/manual/manual.xml b/nixos/doc/manual/manual.xml
index 61b21203f500..e9338efbc025 100644
--- a/nixos/doc/manual/manual.xml
+++ b/nixos/doc/manual/manual.xml
@@ -17,8 +17,8 @@
   <para>
    If you encounter problems, please report them on the
    <literal
-    xlink:href="https://groups.google.com/forum/#!forum/nix-devel">nix-devel</literal>
-   mailing list or on the <link
+    xlink:href="https://discourse.nixos.org">Discourse</literal>
+   or on the <link
     xlink:href="irc://irc.freenode.net/#nixos">
    <literal>#nixos</literal> channel on Freenode</link>. Bugs should be
    reported in
diff --git a/nixos/lib/make-ext4-fs.nix b/nixos/lib/make-ext4-fs.nix
index 35a8afae4a7a..88be8b73ab37 100644
--- a/nixos/lib/make-ext4-fs.nix
+++ b/nixos/lib/make-ext4-fs.nix
@@ -6,16 +6,19 @@
 , storePaths
 , volumeLabel
 , uuid ? "44444444-4444-4444-8888-888888888888"
+, e2fsprogs
+, libfaketime
+, perl
 }:
 
 let
-  sdClosureInfo = pkgs.closureInfo { rootPaths = storePaths; };
+  sdClosureInfo = pkgs.buildPackages.closureInfo { rootPaths = storePaths; };
 in
 
 pkgs.stdenv.mkDerivation {
   name = "ext4-fs.img";
 
-  nativeBuildInputs = with pkgs; [e2fsprogs.bin libfaketime perl];
+  nativeBuildInputs = [e2fsprogs.bin libfaketime perl];
 
   buildCommand =
     ''
diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix
index 08923970cd38..1ac9e5c5c74b 100644
--- a/nixos/modules/installer/cd-dvd/iso-image.nix
+++ b/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -318,7 +318,7 @@ in
         options = [ "allow_other" "cow" "nonempty" "chroot=/mnt-root" "max_files=32768" "hide_meta_files" "dirs=/nix/.rw-store=rw:/nix/.ro-store=ro" ];
       };
 
-    boot.initrd.availableKernelModules = [ "squashfs" "iso9660" "usb-storage" "uas" ];
+    boot.initrd.availableKernelModules = [ "squashfs" "iso9660" "uas" ];
 
     boot.blacklistedKernelModules = [ "nouveau" ];
 
diff --git a/nixos/modules/installer/cd-dvd/sd-image.nix b/nixos/modules/installer/cd-dvd/sd-image.nix
index 311a5ff69670..2371be9d89a1 100644
--- a/nixos/modules/installer/cd-dvd/sd-image.nix
+++ b/nixos/modules/installer/cd-dvd/sd-image.nix
@@ -12,13 +12,12 @@
 with lib;
 
 let
-  rootfsImage = import ../../../lib/make-ext4-fs.nix {
-    inherit pkgs;
+  rootfsImage = pkgs.callPackage ../../../lib/make-ext4-fs.nix ({
     inherit (config.sdImage) storePaths;
     volumeLabel = "NIXOS_SD";
   } // optionalAttrs (config.sdImage.rootPartitionUUID != null) {
     uuid = config.sdImage.rootPartitionUUID;
-  };
+  });
 in
 {
   options.sdImage = {
@@ -94,10 +93,10 @@ in
 
     sdImage.storePaths = [ config.system.build.toplevel ];
 
-    system.build.sdImage = pkgs.stdenv.mkDerivation {
+    system.build.sdImage = pkgs.callPackage ({ stdenv, dosfstools, e2fsprogs, mtools, libfaketime, utillinux }: stdenv.mkDerivation {
       name = config.sdImage.imageName;
 
-      buildInputs = with pkgs; [ dosfstools e2fsprogs mtools libfaketime utillinux ];
+      nativeBuildInputs = [ dosfstools e2fsprogs mtools libfaketime utillinux ];
 
       buildCommand = ''
         mkdir -p $out/nix-support $out/sd-image
@@ -138,7 +137,7 @@ in
         (cd boot; mcopy -bpsvm -i ../bootpart.img ./* ::)
         dd conv=notrunc if=bootpart.img of=$img seek=$START count=$SECTORS
       '';
-    };
+    }) {};
 
     boot.postBootCommands = ''
       # On the first boot do some maintenance tasks
diff --git a/nixos/modules/installer/netboot/netboot.nix b/nixos/modules/installer/netboot/netboot.nix
index a4eda3c52dce..ea640173c6dd 100644
--- a/nixos/modules/installer/netboot/netboot.nix
+++ b/nixos/modules/installer/netboot/netboot.nix
@@ -28,7 +28,6 @@ with lib;
       ++ (if pkgs.stdenv.system == "aarch64-linux"
           then []
           else [ pkgs.grub2 pkgs.syslinux ]);
-    system.boot.loader.kernelFile = pkgs.stdenv.platform.kernelTarget;
 
     fileSystems."/" =
       { fsType = "tmpfs";
@@ -86,7 +85,7 @@ with lib;
 
     system.build.netbootIpxeScript = pkgs.writeTextDir "netboot.ipxe" ''
       #!ipxe
-      kernel ${pkgs.stdenv.platform.kernelTarget} init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
+      kernel ${pkgs.stdenv.hostPlatform.platform.kernelTarget} init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
       initrd initrd
       boot
     '';
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 396e91204079..2846afea8fbc 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -281,6 +281,7 @@
   ./services/hardware/upower.nix
   ./services/hardware/usbmuxd.nix
   ./services/hardware/thermald.nix
+  ./services/hardware/undervolt.nix
   ./services/logging/SystemdJournal2Gelf.nix
   ./services/logging/awstats.nix
   ./services/logging/fluentd.nix
diff --git a/nixos/modules/profiles/all-hardware.nix b/nixos/modules/profiles/all-hardware.nix
index 0d7124be0a5c..19f821ae17f3 100644
--- a/nixos/modules/profiles/all-hardware.nix
+++ b/nixos/modules/profiles/all-hardware.nix
@@ -33,7 +33,7 @@
 
       # USB support, especially for booting from USB CD-ROM
       # drives.
-      "usb_storage"
+      "uas"
 
       # Firewire support.  Not tested.
       "ohci1394" "sbp2"
diff --git a/nixos/modules/services/games/terraria.nix b/nixos/modules/services/games/terraria.nix
index ddf17599296a..31f8edca20ce 100644
--- a/nixos/modules/services/games/terraria.nix
+++ b/nixos/modules/services/games/terraria.nix
@@ -18,6 +18,16 @@ let
     (boolFlag "secure" cfg.secure)
     (boolFlag "noupnp" cfg.noUPnP)
   ];
+  stopScript = pkgs.writeScript "terraria-stop" ''
+    #!${pkgs.runtimeShell}
+
+    if ! [ -d "/proc/$1" ]; then
+      exit 0
+    fi
+
+    ${getBin pkgs.tmux}/bin/tmux -S /var/lib/terraria/terraria.sock send-keys Enter exit Enter
+    ${getBin pkgs.coreutils}/bin/tail --pid="$1" -f /dev/null
+  '';
 in
 {
   options = {
@@ -124,10 +134,10 @@ in
 
       serviceConfig = {
         User    = "terraria";
-        Type = "oneshot";
-        RemainAfterExit = true;
+        Type = "forking";
+        GuessMainPID = true;
         ExecStart = "${getBin pkgs.tmux}/bin/tmux -S /var/lib/terraria/terraria.sock new -d ${pkgs.terraria-server}/bin/TerrariaServer ${concatStringsSep " " flags}";
-        ExecStop = "${getBin pkgs.tmux}/bin/tmux -S /var/lib/terraria/terraria.sock send-keys Enter \"exit\" Enter";
+        ExecStop = "${stopScript} $MAINPID";
       };
 
       postStart = ''
diff --git a/nixos/modules/services/hardware/undervolt.nix b/nixos/modules/services/hardware/undervolt.nix
new file mode 100644
index 000000000000..e5ef0601de3c
--- /dev/null
+++ b/nixos/modules/services/hardware/undervolt.nix
@@ -0,0 +1,134 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+  cfg = config.services.undervolt;
+in {
+  options.services.undervolt = {
+    enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Whether to undervolt intel cpus.
+      '';
+    };
+
+    verbose = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Whether to enable verbose logging.
+      '';
+    };
+
+    package = mkOption {
+      type = types.package;
+      default = pkgs.undervolt;
+      defaultText = "pkgs.undervolt";
+      description = ''
+        undervolt derivation to use.
+      '';
+    };
+
+    coreOffset = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        The amount of voltage to offset the CPU cores by. Accepts a floating point number.
+      '';
+    };
+
+    gpuOffset = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        The amount of voltage to offset the GPU by. Accepts a floating point number.
+      '';
+    };
+
+    uncoreOffset = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        The amount of voltage to offset uncore by. Accepts a floating point number.
+      '';
+    };
+
+    analogioOffset = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        The amount of voltage to offset analogio by. Accepts a floating point number.
+      '';
+    };
+
+    temp = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        The temperature target. Accepts a floating point number.
+      '';
+    };
+
+    tempAc = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        The temperature target on AC power. Accepts a floating point number.
+      '';
+    };
+
+    tempBat = mkOption {
+      type = types.nullOr types.str;
+      default = null;
+      description = ''
+        The temperature target on battery power. Accepts a floating point number.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    boot.kernelModules = [ "msr" ];
+
+    environment.systemPackages = [ cfg.package ];
+
+    systemd.services.undervolt = {
+      path = [ pkgs.undervolt ];
+
+      description = "Intel Undervolting Service";
+      serviceConfig = {
+        Type = "oneshot";
+        Restart = "no";
+
+        # `core` and `cache` are both intentionally set to `cfg.coreOffset` as according to the undervolt docs:
+        #
+        #     Core or Cache offsets have no effect. It is not possible to set different offsets for
+        #     CPU Core and Cache. The CPU will take the smaller of the two offsets, and apply that to
+        #     both CPU and Cache. A warning message will be displayed if you attempt to set different offsets.
+        ExecStart = ''
+          ${pkgs.undervolt}/bin/undervolt \
+            ${optionalString cfg.verbose "--verbose"} \
+            ${optionalString (cfg.coreOffset != null) "--core ${cfg.coreOffset}"} \
+            ${optionalString (cfg.coreOffset != null) "--cache ${cfg.coreOffset}"} \
+            ${optionalString (cfg.gpuOffset != null) "--gpu ${cfg.gpuOffset}"} \
+            ${optionalString (cfg.uncoreOffset != null) "--uncore ${cfg.uncoreOffset}"} \
+            ${optionalString (cfg.analogioOffset != null) "--analogio ${cfg.analogioOffset}"} \
+            ${optionalString (cfg.temp != null) "--temp ${cfg.temp}"} \
+            ${optionalString (cfg.tempAc != null) "--temp-ac ${cfg.tempAc}"} \
+            ${optionalString (cfg.tempBat != null) "--temp-bat ${cfg.tempBat}"}
+        '';
+      };
+    };
+
+    systemd.timers.undervolt = {
+      description = "Undervolt timer to ensure voltage settings are always applied";
+      partOf = [ "undervolt.service" ];
+      wantedBy = [ "multi-user.target" ];
+      timerConfig = {
+        OnBootSec = "2min";
+        OnUnitActiveSec = "30";
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/misc/redmine.nix b/nixos/modules/services/misc/redmine.nix
index 9a9424449f80..f763ba21d0b2 100644
--- a/nixos/modules/services/misc/redmine.nix
+++ b/nixos/modules/services/misc/redmine.nix
@@ -1,121 +1,124 @@
 { config, lib, pkgs, ... }:
 
-# TODO: support non-postgresql
-
 with lib;
 
 let
   cfg = config.services.redmine;
 
-  ruby = pkgs.ruby;
+  bundle = "${pkgs.redmine}/share/redmine/bin/bundle";
 
-  databaseYml = ''
+  databaseYml = pkgs.writeText "database.yml" ''
     production:
-      adapter: postgresql
-      database: ${cfg.databaseName}
-      host: ${cfg.databaseHost}
-      password: ${cfg.databasePassword}
-      username: ${cfg.databaseUsername}
-      encoding: utf8
+      adapter: ${cfg.database.type}
+      database: ${cfg.database.name}
+      host: ${cfg.database.host}
+      port: ${toString cfg.database.port}
+      username: ${cfg.database.user}
+      password: #dbpass#
   '';
 
-  configurationYml = ''
+  configurationYml = pkgs.writeText "configuration.yml" ''
     default:
-      # Absolute path to the directory where attachments are stored.
-      # The default is the 'files' directory in your Redmine instance.
-      # Your Redmine instance needs to have write permission on this
-      # directory.
-      # Examples:
-      # attachments_storage_path: /var/redmine/files
-      # attachments_storage_path: D:/redmine/files
-      attachments_storage_path: ${cfg.stateDir}/files
-
-      # Absolute path to the SCM commands errors (stderr) log file.
-      # The default is to log in the 'log' directory of your Redmine instance.
-      # Example:
-      # scm_stderr_log_file: /var/log/redmine_scm_stderr.log
-      scm_stderr_log_file: ${cfg.stateDir}/redmine_scm_stderr.log
-
-      ${cfg.extraConfig}
+      scm_subversion_command: ${pkgs.subversion}/bin/svn
+      scm_mercurial_command: ${pkgs.mercurial}/bin/hg
+      scm_git_command: ${pkgs.gitAndTools.git}/bin/git
+      scm_cvs_command: ${pkgs.cvs}/bin/cvs
+      scm_bazaar_command: ${pkgs.bazaar}/bin/bzr
+      scm_darcs_command: ${pkgs.darcs}/bin/darcs
+
+    ${cfg.extraConfig}
   '';
 
-  unpackTheme = unpack "theme";
-  unpackPlugin = unpack "plugin";
-  unpack = id: (name: source:
-    pkgs.stdenv.mkDerivation {
-      name = "redmine-${id}-${name}";
-      buildInputs = [ pkgs.unzip ];
-      buildCommand = ''
-        mkdir -p $out
-        cd $out
-        unpackFile ${source}
-      '';
-    });
-
-in {
+in
 
+{
   options = {
     services.redmine = {
       enable = mkOption {
         type = types.bool;
         default = false;
-        description = ''
-          Enable the redmine service.
-        '';
+        description = "Enable the Redmine service.";
       };
 
-      stateDir = mkOption {
+      user = mkOption {
         type = types.str;
-        default = "/var/redmine";
-        description = "The state directory, logs and plugins are stored here";
-      };
-
-      extraConfig = mkOption {
-        type = types.lines;
-        default = "";
-        description = "Extra configuration in configuration.yml";
-      };
-
-      themes = mkOption {
-        type = types.attrsOf types.path;
-        default = {};
-        description = "Set of themes";
+        default = "redmine";
+        description = "User under which Redmine is ran.";
       };
 
-      plugins = mkOption {
-        type = types.attrsOf types.path;
-        default = {};
-        description = "Set of plugins";
+      group = mkOption {
+        type = types.str;
+        default = "redmine";
+        description = "Group under which Redmine is ran.";
       };
 
-      #databaseType = mkOption {
-      #  type = types.str;
-      #  default = "postgresql";
-      #  description = "Type of database";
-      #};
-
-      databaseHost = mkOption {
+      stateDir = mkOption {
         type = types.str;
-        default = "127.0.0.1";
-        description = "Database hostname";
+        default = "/var/lib/redmine";
+        description = "The state directory, logs and plugins are stored here.";
       };
 
-      databasePassword = mkOption {
-        type = types.str;
+      extraConfig = mkOption {
+        type = types.lines;
         default = "";
-        description = "Database user password";
-      };
+        description = ''
+          Extra configuration in configuration.yml.
 
-      databaseName = mkOption {
-        type = types.str;
-        default = "redmine";
-        description = "Database name";
+          See https://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration
+        '';
       };
 
-      databaseUsername = mkOption {
-        type = types.str;
-        default = "redmine";
-        description = "Database user";
+      database = {
+        type = mkOption {
+          type = types.enum [ "mysql2" "postgresql" ];
+          example = "postgresql";
+          default = "mysql2";
+          description = "Database engine to use.";
+        };
+
+        host = mkOption {
+          type = types.str;
+          default = "127.0.0.1";
+          description = "Database host address.";
+        };
+
+        port = mkOption {
+          type = types.int;
+          default = 3306;
+          description = "Database host port.";
+        };
+
+        name = mkOption {
+          type = types.str;
+          default = "redmine";
+          description = "Database name.";
+        };
+
+        user = mkOption {
+          type = types.str;
+          default = "redmine";
+          description = "Database user.";
+        };
+
+        password = mkOption {
+          type = types.str;
+          default = "";
+          description = ''
+            The password corresponding to <option>database.user</option>.
+            Warning: this is stored in cleartext in the Nix store!
+            Use <option>database.passwordFile</option> instead.
+          '';
+        };
+
+        passwordFile = mkOption {
+          type = types.nullOr types.path;
+          default = null;
+          example = "/run/keys/redmine-dbpassword";
+          description = ''
+            A file containing the password corresponding to
+            <option>database.user</option>.
+          '';
+        };
       };
     };
   };
@@ -123,99 +126,106 @@ in {
   config = mkIf cfg.enable {
 
     assertions = [
-      { assertion = cfg.databasePassword != "";
-        message = "services.redmine.databasePassword must be set";
+      { assertion = cfg.database.passwordFile != null || cfg.database.password != "";
+        message = "either services.redmine.database.passwordFile or services.redmine.database.password must be set";
       }
     ];
 
-    users.users = [
-      { name = "redmine";
-        group = "redmine";
-        uid = config.ids.uids.redmine;
-      } ];
-
-    users.groups = [
-      { name = "redmine";
-        gid = config.ids.gids.redmine;
-      } ];
+    environment.systemPackages = [ pkgs.redmine ];
 
     systemd.services.redmine = {
-      after = [ "network.target" "postgresql.service" ];
+      after = [ "network.target" (if cfg.database.type == "mysql2" then "mysql.service" else "postgresql.service") ];
       wantedBy = [ "multi-user.target" ];
+      environment.HOME = "${pkgs.redmine}/share/redmine";
       environment.RAILS_ENV = "production";
-      environment.RAILS_ETC = "${cfg.stateDir}/config";
-      environment.RAILS_LOG = "${cfg.stateDir}/log";
-      environment.RAILS_VAR = "${cfg.stateDir}/var";
       environment.RAILS_CACHE = "${cfg.stateDir}/cache";
-      environment.RAILS_PLUGINS = "${cfg.stateDir}/plugins";
-      environment.RAILS_PUBLIC = "${cfg.stateDir}/public";
-      environment.RAILS_TMP = "${cfg.stateDir}/tmp";
-      environment.SCHEMA = "${cfg.stateDir}/cache/schema.db";
-      environment.HOME = "${pkgs.redmine}/share/redmine";
       environment.REDMINE_LANG = "en";
-      environment.GEM_HOME = "${pkgs.redmine}/share/redmine/vendor/bundle/ruby/1.9.1";
-      environment.GEM_PATH = "${pkgs.bundler}/${pkgs.bundler.ruby.gemPath}";
+      environment.SCHEMA = "${cfg.stateDir}/cache/schema.db";
       path = with pkgs; [
         imagemagickBig
-        subversion
-        mercurial
-        cvs
-        config.services.postgresql.package
         bazaar
+        cvs
+        darcs
         gitAndTools.git
-        # once we build binaries for darc enable it
-        #darcs
+        mercurial
+        subversion
       ];
       preStart = ''
-        # TODO: use env vars
-        for i in plugins public/plugin_assets db files log config cache var/files tmp; do
+        # start with a fresh config directory every time
+        rm -rf ${cfg.stateDir}/config
+        cp -r ${pkgs.redmine}/share/redmine/config.dist ${cfg.stateDir}/config
+
+        # create the basic state directory layout pkgs.redmine expects
+        mkdir -p /run/redmine
+
+        for i in config files log plugins tmp; do
           mkdir -p ${cfg.stateDir}/$i
+          ln -fs ${cfg.stateDir}/$i /run/redmine/$i
         done
 
-        chown -R redmine:redmine ${cfg.stateDir}
-        chmod -R 755 ${cfg.stateDir}
+        # ensure cache directory exists for db:migrate command
+        mkdir -p ${cfg.stateDir}/cache
 
-        rm -rf ${cfg.stateDir}/public/*
-        cp -R ${pkgs.redmine}/share/redmine/public/* ${cfg.stateDir}/public/
-        for theme in ${concatStringsSep " " (mapAttrsToList unpackTheme cfg.themes)}; do
-          ln -fs $theme/* ${cfg.stateDir}/public/themes/
-        done
+        # link in the application configuration
+        ln -fs ${configurationYml} ${cfg.stateDir}/config/configuration.yml
 
-        rm -rf ${cfg.stateDir}/plugins/*
-        for plugin in ${concatStringsSep " " (mapAttrsToList unpackPlugin cfg.plugins)}; do
-          ln -fs $plugin/* ${cfg.stateDir}/plugins/''${plugin##*-redmine-plugin-}
-        done
+        chmod -R ug+rwX,o-rwx+x ${cfg.stateDir}/
 
-        ln -fs ${pkgs.writeText "database.yml" databaseYml} ${cfg.stateDir}/config/database.yml
-        ln -fs ${pkgs.writeText "configuration.yml" configurationYml} ${cfg.stateDir}/config/configuration.yml
+        # handle database.passwordFile
+        DBPASS=$(head -n1 ${cfg.database.passwordFile})
+        cp -f ${databaseYml} ${cfg.stateDir}/config/database.yml
+        sed -e "s,#dbpass#,$DBPASS,g" -i ${cfg.stateDir}/config/database.yml
+        chmod 440 ${cfg.stateDir}/config/database.yml
 
-        if [ "${cfg.databaseHost}" = "127.0.0.1" ]; then
-          if ! test -e "${cfg.stateDir}/db-created"; then
-            psql postgres -c "CREATE ROLE redmine WITH LOGIN NOCREATEDB NOCREATEROLE ENCRYPTED PASSWORD '${cfg.databasePassword}'"
-            ${config.services.postgresql.package}/bin/createdb --owner redmine redmine || true
-            touch "${cfg.stateDir}/db-created"
-          fi
+        # generate a secret token if required
+        if ! test -e "${cfg.stateDir}/config/initializers/secret_token.rb"; then
+          ${bundle} exec rake generate_secret_token
+          chmod 440 ${cfg.stateDir}/config/initializers/secret_token.rb
         fi
 
-        cd ${pkgs.redmine}/share/redmine/
-        ${ruby}/bin/rake db:migrate
-        ${ruby}/bin/rake redmine:plugins:migrate
-        ${ruby}/bin/rake redmine:load_default_data
-        ${ruby}/bin/rake generate_secret_token
+        # ensure everything is owned by ${cfg.user}
+        chown -R ${cfg.user}:${cfg.group} ${cfg.stateDir}
+
+        ${bundle} exec rake db:migrate
+        ${bundle} exec rake redmine:load_default_data
       '';
 
       serviceConfig = {
         PermissionsStartOnly = true; # preStart must be run as root
         Type = "simple";
-        User = "redmine";
-        Group = "redmine";
+        User = cfg.user;
+        Group = cfg.group;
         TimeoutSec = "300";
         WorkingDirectory = "${pkgs.redmine}/share/redmine";
-        ExecStart="${ruby}/bin/ruby ${pkgs.redmine}/share/redmine/script/rails server webrick -e production -P ${cfg.stateDir}/redmine.pid";
+        ExecStart="${bundle} exec rails server webrick -e production -P ${cfg.stateDir}/redmine.pid";
       };
 
     };
 
+    users.extraUsers = optionalAttrs (cfg.user == "redmine") (singleton
+      { name = "redmine";
+        group = cfg.group;
+        home = cfg.stateDir;
+        createHome = true;
+        uid = config.ids.uids.redmine;
+      });
+
+    users.extraGroups = optionalAttrs (cfg.group == "redmine") (singleton
+      { name = "redmine";
+        gid = config.ids.gids.redmine;
+      });
+
+    warnings = optional (cfg.database.password != "")
+      ''config.services.redmine.database.password will be stored as plaintext
+      in the Nix store. Use database.passwordFile instead.'';
+
+    # Create database passwordFile default when password is configured.
+    services.redmine.database.passwordFile =
+      (mkDefault (toString (pkgs.writeTextFile {
+        name = "redmine-database-password";
+        text = cfg.database.password;
+      })));
+
   };
 
 }
diff --git a/nixos/modules/services/networking/dhcpcd.nix b/nixos/modules/services/networking/dhcpcd.nix
index 019c8fd9ec48..efdbca5d52e8 100644
--- a/nixos/modules/services/networking/dhcpcd.nix
+++ b/nixos/modules/services/networking/dhcpcd.nix
@@ -161,8 +161,9 @@ in
       { description = "DHCP Client";
 
         wantedBy = [ "multi-user.target" ] ++ optional (!hasDefaultGatewaySet) "network-online.target";
-        wants = [ "network.target" ];
+        wants = [ "network.target" "systemd-udev-settle.service" ];
         before = [ "network.target" ];
+        after = [ "systemd-udev-settle.service" ];
 
         # Stopping dhcpcd during a reconfiguration is undesirable
         # because it brings down the network interfaces configured by
diff --git a/nixos/modules/services/security/cfssl.nix b/nixos/modules/services/security/cfssl.nix
index 1eb2f65ba602..ee6d5d91fe15 100644
--- a/nixos/modules/services/security/cfssl.nix
+++ b/nixos/modules/services/security/cfssl.nix
@@ -146,7 +146,7 @@ in {
     };
   };
 
-  config = {
+  config = mkIf cfg.enable {
     users.extraGroups.cfssl = {
       gid = config.ids.gids.cfssl;
     };
@@ -159,7 +159,7 @@ in {
       uid = config.ids.uids.cfssl;
     };
 
-    systemd.services.cfssl = mkIf cfg.enable {
+    systemd.services.cfssl = {
       description = "CFSSL CA API server";
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" ];
diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix
index da29e08b3691..9d410a8b9ca4 100644
--- a/nixos/modules/system/activation/top-level.nix
+++ b/nixos/modules/system/activation/top-level.nix
@@ -46,7 +46,7 @@ let
 
         ln -s ${kernelPath} $out/kernel
         ln -s ${config.system.modulesTree} $out/kernel-modules
-        ${optionalString (pkgs.stdenv.platform.kernelDTB or false) ''
+        ${optionalString (pkgs.stdenv.hostPlatform.platform.kernelDTB or false) ''
           ln -s ${config.boot.kernelPackages.kernel}/dtbs $out/dtbs
         ''}
 
@@ -74,7 +74,7 @@ let
       echo -n "$configurationName" > $out/configuration-name
       echo -n "systemd ${toString config.systemd.package.interfaceVersion}" > $out/init-interface-version
       echo -n "$nixosLabel" > $out/nixos-version
-      echo -n "$system" > $out/system
+      echo -n "${pkgs.stdenv.hostPlatform.system}" > $out/system
 
       mkdir $out/fine-tune
       childCount=0
@@ -175,7 +175,7 @@ in
 
     system.boot.loader.kernelFile = mkOption {
       internal = true;
-      default = pkgs.stdenv.platform.kernelTarget;
+      default = pkgs.stdenv.hostPlatform.platform.kernelTarget;
       type = types.str;
       description = ''
         Name of the kernel file to be passed to the bootloader.
diff --git a/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix b/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix
index f8a00784034a..2d27611946e2 100644
--- a/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix
+++ b/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix
@@ -13,7 +13,7 @@ let
   };
 
   # Temporary check, for nixos to cope both with nixpkgs stdenv-updates and trunk
-  platform = pkgs.stdenv.platform;
+  inherit (pkgs.stdenv.hostPlatform) platform;
 
 in
 
diff --git a/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix b/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix
index f974d07da9e5..9bec24c53f5b 100644
--- a/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix
+++ b/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix
@@ -15,7 +15,7 @@ let
     inherit configTxt;
   };
 
-  platform = pkgs.stdenv.platform;
+  inherit (pkgs.stdenv.hostPlatform) platform;
 
   builderUboot = import ./builder_uboot.nix { inherit config; inherit pkgs; inherit configTxt; };
 
diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix
index a3b7d7ba07ad..c11aaeaeb6dc 100644
--- a/nixos/modules/system/boot/networkd.nix
+++ b/nixos/modules/system/boot/networkd.nix
@@ -30,10 +30,10 @@ let
     (assertValueOneOf "UDPSegmentationOffload" boolValues)
     (assertValueOneOf "GenericReceiveOffload" boolValues)
     (assertValueOneOf "LargeReceiveOffload" boolValues)
-    (range "RxChannels" 1 4294967295)
-    (range "TxChannels" 1 4294967295)
-    (range "OtherChannels" 1 4294967295)
-    (range "CombinedChannels" 1 4294967295)
+    (assertRange "RxChannels" 1 4294967295)
+    (assertRange "TxChannels" 1 4294967295)
+    (assertRange "OtherChannels" 1 4294967295)
+    (assertRange "CombinedChannels" 1 4294967295)
   ];
 
   checkNetdev = checkUnitConfig "Netdev" [
diff --git a/nixos/release.nix b/nixos/release.nix
index 1d1f8009f27c..b25c684ff47a 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -83,7 +83,7 @@ let
     in
       tarball //
         { meta = {
-            description = "NixOS system tarball for ${system} - ${stdenv.platform.name}";
+            description = "NixOS system tarball for ${system} - ${stdenv.hostPlatform.platform.name}";
             maintainers = map (x: lib.maintainers.${x}) maintainers;
           };
           inherit config;
@@ -106,7 +106,7 @@ let
     let
       configEvaled = import lib/eval-config.nix config;
       build = configEvaled.config.system.build;
-      kernelTarget = configEvaled.pkgs.stdenv.platform.kernelTarget;
+      kernelTarget = configEvaled.pkgs.stdenv.hostPlatform.platform.kernelTarget;
     in
       pkgs.symlinkJoin {
         name = "netboot";
diff --git a/nixos/tests/home-assistant.nix b/nixos/tests/home-assistant.nix
index 0c027eaca619..2d74b59bca46 100644
--- a/nixos/tests/home-assistant.nix
+++ b/nixos/tests/home-assistant.nix
@@ -2,7 +2,8 @@ import ./make-test.nix ({ pkgs, ... }:
 
 let
   configDir = "/var/lib/foobar";
-  apiPassword = "secret";
+  apiPassword = "some_secret";
+  mqttPassword = "another_secret";
 
 in {
   name = "home-assistant";
@@ -33,7 +34,9 @@ in {
             };
             frontend = { };
             http.api_password = apiPassword;
-            mqtt = { }; # Use hbmqtt as broker
+            mqtt = { # Use hbmqtt as broker
+              password = mqttPassword;
+            };
             binary_sensor = [
               {
                 platform = "mqtt";
@@ -62,7 +65,7 @@ in {
 
     # Toggle a binary sensor using MQTT
     $hass->succeed("curl http://localhost:8123/api/states/binary_sensor.mqtt_binary_sensor -H 'x-ha-access: ${apiPassword}' | grep -qF '\"state\": \"off\"'");
-    $hass->waitUntilSucceeds("mosquitto_pub -V mqttv311 -t home-assistant/test -u homeassistant -P '${apiPassword}' -m let_there_be_light");
+    $hass->waitUntilSucceeds("mosquitto_pub -V mqttv311 -t home-assistant/test -u homeassistant -P '${mqttPassword}' -m let_there_be_light");
     $hass->succeed("curl http://localhost:8123/api/states/binary_sensor.mqtt_binary_sensor -H 'x-ha-access: ${apiPassword}' | grep -qF '\"state\": \"on\"'");
 
     # Print log to ease debugging