summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorFrederik Rietdijk <fridh@fridh.nl>2019-07-09 15:46:26 +0200
committerFrederik Rietdijk <fridh@fridh.nl>2019-07-09 15:46:26 +0200
commit79a03641d58f351454051bf2320e94508525a41b (patch)
tree8fa1b8870eb83ffb282848d8cf1363e542fd126d /nixos
parent7cf5909fadf5cf74f3b0e2bc5b227deb8f45f288 (diff)
parent74c24385cb2864f937031df74af14fc8060e1540 (diff)
downloadnixpkgs-79a03641d58f351454051bf2320e94508525a41b.tar
nixpkgs-79a03641d58f351454051bf2320e94508525a41b.tar.gz
nixpkgs-79a03641d58f351454051bf2320e94508525a41b.tar.bz2
nixpkgs-79a03641d58f351454051bf2320e94508525a41b.tar.lz
nixpkgs-79a03641d58f351454051bf2320e94508525a41b.tar.xz
nixpkgs-79a03641d58f351454051bf2320e94508525a41b.tar.zst
nixpkgs-79a03641d58f351454051bf2320e94508525a41b.zip
Merge staging-next into staging
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/release-notes/rl-1909.xml178
-rw-r--r--nixos/modules/config/networking.nix2
-rw-r--r--nixos/modules/hardware/ksm.nix22
-rw-r--r--nixos/modules/module-list.nix1
-rw-r--r--nixos/modules/rename.nix3
-rw-r--r--nixos/modules/services/logging/graylog.nix2
-rw-r--r--nixos/modules/services/misc/jackett.nix9
-rw-r--r--nixos/modules/services/misc/lidarr.nix1
-rw-r--r--nixos/modules/services/misc/zoneminder.nix2
-rw-r--r--nixos/modules/services/monitoring/loki.nix112
-rw-r--r--nixos/modules/services/monitoring/netdata.nix18
-rw-r--r--nixos/modules/tasks/filesystems/zfs.nix3
-rw-r--r--nixos/modules/virtualisation/kvmgt.nix12
-rw-r--r--nixos/tests/all-tests.nix1
-rw-r--r--nixos/tests/loki.nix37
15 files changed, 303 insertions, 100 deletions
diff --git a/nixos/doc/manual/release-notes/rl-1909.xml b/nixos/doc/manual/release-notes/rl-1909.xml
index eae84ee1a19..8a65642270c 100644
--- a/nixos/doc/manual/release-notes/rl-1909.xml
+++ b/nixos/doc/manual/release-notes/rl-1909.xml
@@ -81,45 +81,45 @@
    </listitem>
    <listitem>
     <para>
-      The options <option>services.prometheus.alertmanager.user</option> and
-      <option>services.prometheus.alertmanager.group</option> have been removed
-      because the alertmanager service is now using systemd's <link
-      xlink:href="http://0pointer.net/blog/dynamic-users-with-systemd.html">
-      DynamicUser mechanism</link> which obviates these options.
+     The options <option>services.prometheus.alertmanager.user</option> and
+     <option>services.prometheus.alertmanager.group</option> have been removed
+     because the alertmanager service is now using systemd's <link
+     xlink:href="http://0pointer.net/blog/dynamic-users-with-systemd.html">
+     DynamicUser mechanism</link> which obviates these options.
     </para>
    </listitem>
    <listitem>
     <para>
-      The NetworkManager systemd unit was renamed back from network-manager.service to
-      NetworkManager.service for better compatibility with other applications expecting this name.
-      The same applies to ModemManager where modem-manager.service is now called ModemManager.service again.
+     The NetworkManager systemd unit was renamed back from network-manager.service to
+     NetworkManager.service for better compatibility with other applications expecting this name.
+     The same applies to ModemManager where modem-manager.service is now called ModemManager.service again.
     </para>
    </listitem>
    <listitem>
     <para>
-      The <option>services.nzbget.configFile</option> and <option>services.nzbget.openFirewall</option>
-      options were removed as they are managed internally by the nzbget. The
-      <option>services.nzbget.dataDir</option> option hadn't actually been used by
-      the module for some time and so was removed as cleanup.
+     The <option>services.nzbget.configFile</option> and <option>services.nzbget.openFirewall</option>
+     options were removed as they are managed internally by the nzbget. The
+     <option>services.nzbget.dataDir</option> option hadn't actually been used by
+     the module for some time and so was removed as cleanup.
     </para>
    </listitem>
    <listitem>
     <para>
-      The <option>services.mysql.pidDir</option> option was removed, as it was only used by the wordpress
-      apache-httpd service to wait for mysql to have started up.
-      This can be accomplished by either describing a dependency on mysql.service (preferred)
-      or waiting for the (hardcoded) <filename>/run/mysqld/mysql.sock</filename> file to appear.
+     The <option>services.mysql.pidDir</option> option was removed, as it was only used by the wordpress
+     apache-httpd service to wait for mysql to have started up.
+     This can be accomplished by either describing a dependency on mysql.service (preferred)
+     or waiting for the (hardcoded) <filename>/run/mysqld/mysql.sock</filename> file to appear.
     </para>
    </listitem>
    <listitem>
     <para>
-      The <option>services.emby.enable</option> module has been removed, see
-      <option>services.jellyfin.enable</option> instead for a free software fork of Emby.
+     The <option>services.emby.enable</option> module has been removed, see
+     <option>services.jellyfin.enable</option> instead for a free software fork of Emby.
 
-      See the Jellyfin documentation:
-      <link xlink:href="https://jellyfin.readthedocs.io/en/latest/administrator-docs/migrate-from-emby/">
-        Migrating from Emby to Jellyfin
-      </link>
+     See the Jellyfin documentation:
+     <link xlink:href="https://jellyfin.readthedocs.io/en/latest/administrator-docs/migrate-from-emby/">
+       Migrating from Emby to Jellyfin
+     </link>
     </para>
    </listitem>
    <listitem>
@@ -136,50 +136,50 @@
    </listitem>
    <listitem>
     <para>
-      Several of the apache subservices have been replaced with full NixOS
-      modules including LimeSurvey and WordPress.
-      These modules can be enabled using the <option>services.limesurvey.enable</option>
-      and <option>services.wordpress.enable</option> options.
+     Several of the apache subservices have been replaced with full NixOS
+     modules including LimeSurvey and WordPress.
+     These modules can be enabled using the <option>services.limesurvey.enable</option>
+     and <option>services.wordpress.enable</option> options.
     </para>
    </listitem>
    <listitem>
-     <para>
-      The option <option>systemd.network.networks.&lt;name&gt;.routes.*.routeConfig.GatewayOnlink</option>
-      was renamed to <option>systemd.network.networks.&lt;name&gt;.routes.*.routeConfig.GatewayOnLink</option>
-      (capital <literal>L</literal>). This follows
-      <link xlink:href="https://github.com/systemd/systemd/commit/9cb8c5593443d24c19e40bfd4fc06d672f8c554c">
-        upstreams renaming
-      </link> of the setting.
-     </para>
+    <para>
+     The option <option>systemd.network.networks.&lt;name&gt;.routes.*.routeConfig.GatewayOnlink</option>
+     was renamed to <option>systemd.network.networks.&lt;name&gt;.routes.*.routeConfig.GatewayOnLink</option>
+     (capital <literal>L</literal>). This follows
+     <link xlink:href="https://github.com/systemd/systemd/commit/9cb8c5593443d24c19e40bfd4fc06d672f8c554c">
+      upstreams renaming
+     </link> of the setting.
+    </para>
    </listitem>
    <listitem>
     <para>
-      As of this release the NixOps feature <literal>autoLuks</literal> is deprecated. It no longer works
-      with our systemd version without manual intervention.
+     As of this release the NixOps feature <literal>autoLuks</literal> is deprecated. It no longer works
+     with our systemd version without manual intervention.
     </para>
     <para>
-      Whenever the usage of the module is detected the evaluation will fail with a message
-      explaining why and how to deal with the situation.
+     Whenever the usage of the module is detected the evaluation will fail with a message
+     explaining why and how to deal with the situation.
     </para>
     <para>
-      A new knob named <literal>nixops.enableDeprecatedAutoLuks</literal>
-      has been introduced to disable the eval failure and to acknowledge the notice was received and read.
-      If you plan on using the feature please note that it might break with subsequent updates.
+     A new knob named <literal>nixops.enableDeprecatedAutoLuks</literal>
+     has been introduced to disable the eval failure and to acknowledge the notice was received and read.
+     If you plan on using the feature please note that it might break with subsequent updates.
     </para>
     <para>
-      Make sure you set the <literal>_netdev</literal> option for each of the file systems referring to block
-      devices provided by the autoLuks module. Not doing this might render the system in a
-      state where it doesn't boot anymore.
+     Make sure you set the <literal>_netdev</literal> option for each of the file systems referring to block
+     devices provided by the autoLuks module. Not doing this might render the system in a
+     state where it doesn't boot anymore.
     </para>
     <para>
-      If you are actively using the <literal>autoLuks</literal> module please let us know in
-      <link xlink:href="https://github.com/NixOS/nixpkgs/issues/62211">issue #62211</link>.
+     If you are actively using the <literal>autoLuks</literal> module please let us know in
+     <link xlink:href="https://github.com/NixOS/nixpkgs/issues/62211">issue #62211</link>.
     </para>
-  </listitem>
-  <listitem>
+   </listitem>
+   <listitem>
     <para>
-      The setopt declarations will be evaluated at the end of <literal>/etc/zshrc</literal>, so any code in <xref linkend="opt-programs.zsh.interactiveShellInit" />,
-      <xref linkend="opt-programs.zsh.loginShellInit" /> and <xref linkend="opt-programs.zsh.promptInit" /> may break if it relies on those options being set.
+     The setopt declarations will be evaluated at the end of <literal>/etc/zshrc</literal>, so any code in <xref linkend="opt-programs.zsh.interactiveShellInit" />,
+     <xref linkend="opt-programs.zsh.loginShellInit" /> and <xref linkend="opt-programs.zsh.promptInit" /> may break if it relies on those options being set.
     </para>
    </listitem>
   </itemizedlist>
@@ -236,36 +236,36 @@
    </listitem>
    <listitem>
     <para>
-      The <literal>hunspellDicts.fr-any</literal> dictionary now ships with <literal>fr_FR.{aff,dic}</literal>
-      which is linked to <literal>fr-toutesvariantes.{aff,dic}</literal>.
+     The <literal>hunspellDicts.fr-any</literal> dictionary now ships with <literal>fr_FR.{aff,dic}</literal>
+     which is linked to <literal>fr-toutesvariantes.{aff,dic}</literal>.
     </para>
-  </listitem>
-  <listitem>
+   </listitem>
+   <listitem>
     <para>
-      The <literal>mysql</literal> service now runs as <literal>mysql</literal>
-      user. Previously, systemd did execute it as root, and mysql dropped privileges
-      itself.
-      This includes <literal>ExecStartPre=</literal> and
-      <literal>ExecStartPost=</literal> phases.
-      To accomplish that, runtime and data directory setup was delegated to
-      RuntimeDirectory and tmpfiles.
+     The <literal>mysql</literal> service now runs as <literal>mysql</literal>
+     user. Previously, systemd did execute it as root, and mysql dropped privileges
+     itself.
+     This includes <literal>ExecStartPre=</literal> and
+     <literal>ExecStartPost=</literal> phases.
+     To accomplish that, runtime and data directory setup was delegated to
+     RuntimeDirectory and tmpfiles.
     </para>
    </listitem>
    <listitem>
     <para>
-      With the upgrade to systemd version 242 the <literal>systemd-timesyncd</literal>
-      service is no longer using <literal>DynamicUser=yes</literal>. In order for the
-      upgrade to work we rely on an activation script to move the state from the old
-      to the new directory. The older directory (prior <literal>19.09</literal>) was
-      <literal>/var/lib/private/systemd/timesync</literal>.
+     With the upgrade to systemd version 242 the <literal>systemd-timesyncd</literal>
+     service is no longer using <literal>DynamicUser=yes</literal>. In order for the
+     upgrade to work we rely on an activation script to move the state from the old
+     to the new directory. The older directory (prior <literal>19.09</literal>) was
+     <literal>/var/lib/private/systemd/timesync</literal>.
     </para>
     <para>
-      As long as the <literal>system.config.stateVersion</literal> is below
-      <literal>19.09</literal> the state folder will migrated to its proper location
-      (<literal>/var/lib/systemd/timesync</literal>), if required.
+     As long as the <literal>system.config.stateVersion</literal> is below
+     <literal>19.09</literal> the state folder will migrated to its proper location
+     (<literal>/var/lib/systemd/timesync</literal>), if required.
     </para>
-  </listitem>
-  <listitem>
+   </listitem>
+   <listitem>
     <para>
      The package <literal>avahi</literal> is now built to look up service
      definitions from <literal>/etc/avahi/services</literal> instead of its
@@ -275,32 +275,36 @@
      in the aforementioned directory. See <citerefentry>
      <refentrytitle>avahi.service</refentrytitle><manvolnum>5</manvolnum>
      </citerefentry> for more information on custom service definitions.
-      Since version 0.1.19, <literal>cargo-vendor</literal> honors package
-      includes that are specified in the <filename>Cargo.toml</filename>
-      file of Rust crates. <literal>rustPlatform.buildRustPackage</literal> uses
-      <literal>cargo-vendor</literal> to collect and build dependent crates.
-      Since this change in <literal>cargo-vendor</literal> changes the set of
-      vendored files for most Rust packages, the hash that use used to verify
-      the dependencies, <literal>cargoSha256</literal>, also changes.
+    </para>
+   </listitem>
+   <listitem>
+    <para>
+     Since version 0.1.19, <literal>cargo-vendor</literal> honors package
+     includes that are specified in the <filename>Cargo.toml</filename>
+     file of Rust crates. <literal>rustPlatform.buildRustPackage</literal> uses
+     <literal>cargo-vendor</literal> to collect and build dependent crates.
+     Since this change in <literal>cargo-vendor</literal> changes the set of
+     vendored files for most Rust packages, the hash that use used to verify
+     the dependencies, <literal>cargoSha256</literal>, also changes.
     </para>
     <para>
-      The <literal>cargoSha256</literal> hashes of all in-tree derivations that
-      use <literal>buildRustPackage</literal> have been updated to reflect this
-      change. However, third-party derivations that use
-      <literal>buildRustPackage</literal> may have to be updated as well.
+     The <literal>cargoSha256</literal> hashes of all in-tree derivations that
+     use <literal>buildRustPackage</literal> have been updated to reflect this
+     change. However, third-party derivations that use
+     <literal>buildRustPackage</literal> may have to be updated as well.
     </para>
    </listitem>
    <listitem>
     <para>
-      The <literal>consul</literal> package was upgraded past version <literal>1.5</literal>,
-      so its deprecated legacy UI is no longer available.
+     The <literal>consul</literal> package was upgraded past version <literal>1.5</literal>,
+     so its deprecated legacy UI is no longer available.
     </para>
    </listitem>
    <listitem>
     <para>
-      The default resample-method for PulseAudio has been changed from the upstream default <literal>speex-float-1</literal>
-      to <literal>speex-float-5</literal>. Be aware that low-powered ARM-based and MIPS-based boards will struggle with this
-      so you'll need to set <option>hardware.pulseaudio.daemon.config.resample-method</option> back to <literal>speex-float-1</literal>.
+     The default resample-method for PulseAudio has been changed from the upstream default <literal>speex-float-1</literal>
+     to <literal>speex-float-5</literal>. Be aware that low-powered ARM-based and MIPS-based boards will struggle with this
+     so you'll need to set <option>hardware.pulseaudio.daemon.config.resample-method</option> back to <literal>speex-float-1</literal>.
     </para>
    </listitem>
    <listitem>
diff --git a/nixos/modules/config/networking.nix b/nixos/modules/config/networking.nix
index 8b352dad472..eab4e73e19a 100644
--- a/nixos/modules/config/networking.nix
+++ b/nixos/modules/config/networking.nix
@@ -233,7 +233,7 @@ in
           oneToString = set: ip: ip + " " + concatStringsSep " " set.${ip};
           allToString = set: concatMapStringsSep "\n" (oneToString set) (attrNames set);
         in ''
-          ${allToString cfg.hosts}
+          ${allToString (filterAttrs (_: v: v != []) cfg.hosts)}
           ${cfg.extraHosts}
         '';
 
diff --git a/nixos/modules/hardware/ksm.nix b/nixos/modules/hardware/ksm.nix
index d6ac69b5d65..99d46c25236 100644
--- a/nixos/modules/hardware/ksm.nix
+++ b/nixos/modules/hardware/ksm.nix
@@ -1,9 +1,24 @@
 { config, lib, ... }:
 
-{
-  options.hardware.enableKSM = lib.mkEnableOption "Kernel Same-Page Merging";
+with lib;
 
-  config = lib.mkIf config.hardware.enableKSM {
+let
+  cfg = config.hardware.ksm;
+
+in {
+  options.hardware.ksm = {
+    enable = mkEnableOption "Kernel Same-Page Merging";
+    sleep = mkOption {
+      type = types.nullOr types.int;
+      default = null;
+      description = ''
+        How many milliseconds ksmd should sleep between scans.
+        Setting it to <literal>null</literal> uses the kernel's default time.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
     systemd.services.enable-ksm = {
       description = "Enable Kernel Same-Page Merging";
       wantedBy = [ "multi-user.target" ];
@@ -11,6 +26,7 @@
       script = ''
         if [ -e /sys/kernel/mm/ksm ]; then
           echo 1 > /sys/kernel/mm/ksm/run
+          ${optionalString (cfg.sleep != null) ''echo ${toString cfg.sleep} > /sys/kernel/mm/ksm/sleep_millisecs''}
         fi
       '';
     };
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index c4ee28a9593..1d1995eda25 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -492,6 +492,7 @@
   ./services/monitoring/heapster.nix
   ./services/monitoring/incron.nix
   ./services/monitoring/kapacitor.nix
+  ./services/monitoring/loki.nix
   ./services/monitoring/longview.nix
   ./services/monitoring/monit.nix
   ./services/monitoring/munin.nix
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index 7fa76dc0c68..1b77a895d71 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -241,6 +241,9 @@ with lib;
     # binfmt
     (mkRenamedOptionModule [ "boot" "binfmtMiscRegistrations" ] [ "boot" "binfmt" "registrations" ])
 
+    # KSM
+    (mkRenamedOptionModule [ "hardware" "enableKSM" ] [ "hardware" "ksm" "enable" ])
+
   ] ++ (flip map [ "blackboxExporter" "collectdExporter" "fritzboxExporter"
                    "jsonExporter" "minioExporter" "nginxExporter" "nodeExporter"
                    "snmpExporter" "unifiExporter" "varnishExporter" ]
diff --git a/nixos/modules/services/logging/graylog.nix b/nixos/modules/services/logging/graylog.nix
index ee566825498..c8c4a9ff06d 100644
--- a/nixos/modules/services/logging/graylog.nix
+++ b/nixos/modules/services/logging/graylog.nix
@@ -108,7 +108,7 @@ in
       };
 
       extraConfig = mkOption {
-        type = types.str;
+        type = types.lines;
         default = "";
         description = "Any other configuration options you might want to add";
       };
diff --git a/nixos/modules/services/misc/jackett.nix b/nixos/modules/services/misc/jackett.nix
index a07f20e5c24..f2dc6635df9 100644
--- a/nixos/modules/services/misc/jackett.nix
+++ b/nixos/modules/services/misc/jackett.nix
@@ -34,6 +34,13 @@ in
         default = "jackett";
         description = "Group under which Jackett runs.";
       };
+
+      package = mkOption {
+        type = types.package;
+        default = pkgs.jackett;
+        defaultText = "pkgs.jackett";
+        description = "Jackett package to use.";
+      };
     };
   };
 
@@ -51,7 +58,7 @@ in
         Type = "simple";
         User = cfg.user;
         Group = cfg.group;
-        ExecStart = "${pkgs.jackett}/bin/Jackett --NoUpdates --DataFolder '${cfg.dataDir}'";
+        ExecStart = "${cfg.package}/bin/Jackett --NoUpdates --DataFolder '${cfg.dataDir}'";
         Restart = "on-failure";
       };
     };
diff --git a/nixos/modules/services/misc/lidarr.nix b/nixos/modules/services/misc/lidarr.nix
index 4c37bd74f15..40755c16217 100644
--- a/nixos/modules/services/misc/lidarr.nix
+++ b/nixos/modules/services/misc/lidarr.nix
@@ -68,6 +68,7 @@ in
     users.users = mkIf (cfg.user == "lidarr") {
       lidarr = {
         group = cfg.group;
+        home = "/var/lib/lidarr";
         uid = config.ids.uids.lidarr;
       };
     };
diff --git a/nixos/modules/services/misc/zoneminder.nix b/nixos/modules/services/misc/zoneminder.nix
index 8d58c2b37c8..cf56ae89b39 100644
--- a/nixos/modules/services/misc/zoneminder.nix
+++ b/nixos/modules/services/misc/zoneminder.nix
@@ -262,7 +262,7 @@ in {
                   fastcgi_pass ${fcgi.socketType}:${fcgi.socketAddress};
                 }
 
-                location /cache {
+                location /cache/ {
                   alias /var/cache/${dirName};
                 }
 
diff --git a/nixos/modules/services/monitoring/loki.nix b/nixos/modules/services/monitoring/loki.nix
new file mode 100644
index 00000000000..4d11360d07e
--- /dev/null
+++ b/nixos/modules/services/monitoring/loki.nix
@@ -0,0 +1,112 @@
+{ config, lib, pkgs, ... }:
+
+let
+  inherit (lib) escapeShellArgs literalExample mkEnableOption mkIf mkOption types;
+
+  cfg = config.services.loki;
+
+  prettyJSON = conf:
+    pkgs.runCommand "loki-config.json" { } ''
+      echo '${builtins.toJSON conf}' | ${pkgs.jq}/bin/jq 'del(._module)' > $out
+    '';
+
+in {
+  options.services.loki = {
+    enable = mkEnableOption "loki";
+
+    user = mkOption {
+      type = types.str;
+      default = "loki";
+      description = ''
+        User under which the Loki service runs.
+      '';
+    };
+
+    group = mkOption {
+      type = types.str;
+      default = "loki";
+      description = ''
+        Group under which the Loki service runs.
+      '';
+    };
+
+    dataDir = mkOption {
+      type = types.path;
+      default = "/var/lib/loki";
+      description = ''
+        Specify the directory for Loki.
+      '';
+    };
+
+    configuration = mkOption {
+      type = types.attrs;
+      default = {};
+      description = ''
+        Specify the configuration for Loki in Nix.
+      '';
+    };
+
+    configFile = mkOption {
+      type = types.nullOr types.path;
+      default = null;
+      description = ''
+        Specify a configuration file that Loki should use.
+      '';
+    };
+
+    extraFlags = mkOption {
+      type = types.listOf types.str;
+      default = [];
+      example = literalExample [ "--server.http-listen-port=3101" ];
+      description = ''
+        Specify a list of additional command line flags,
+        which get escaped and are then passed to Loki.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    assertions = [{
+      assertion = (
+        (cfg.configuration == {} -> cfg.configFile != null) &&
+        (cfg.configFile != null -> cfg.configuration == {})
+      );
+      message  = ''
+        Please specify either
+        'services.loki.configuration' or
+        'services.loki.configFile'.
+      '';
+    }];
+
+    users.groups.${cfg.group} = { };
+    users.users.${cfg.user} = {
+      description = "Loki Service User";
+      group = cfg.group;
+      home = cfg.dataDir;
+      createHome = true;
+      isSystemUser = true;
+    };
+
+    systemd.services.loki = {
+      description = "Loki Service Daemon";
+      wantedBy = [ "multi-user.target" ];
+
+      serviceConfig = let
+        conf = if cfg.configFile == null
+               then prettyJSON cfg.configuration
+               else cfg.configFile;
+      in
+      {
+        ExecStart = "${pkgs.grafana-loki}/bin/loki --config.file=${conf} ${escapeShellArgs cfg.extraFlags}";
+        User = cfg.user;
+        Restart = "always";
+        PrivateTmp = true;
+        ProtectHome = true;
+        ProtectSystem = "full";
+        DecvicePolicy = "closed";
+        NoNewPrivileges = true;
+        WorkingDirectory = cfg.dataDir;
+      };
+    };
+  };
+}
diff --git a/nixos/modules/services/monitoring/netdata.nix b/nixos/modules/services/monitoring/netdata.nix
index f264b6dd456..f9b7550af23 100644
--- a/nixos/modules/services/monitoring/netdata.nix
+++ b/nixos/modules/services/monitoring/netdata.nix
@@ -141,11 +141,18 @@ in {
       path = (with pkgs; [ gawk curl ]) ++ lib.optional cfg.python.enable
         (pkgs.python3.withPackages cfg.python.extraPackages);
       serviceConfig = {
-        User = cfg.user;
-        Group = cfg.group;
         Environment="PYTHONPATH=${pkgs.netdata}/libexec/netdata/python.d/python_modules";
-        ExecStart = "${pkgs.netdata}/bin/netdata -D -c ${configFile}";
+        ExecStart = "${pkgs.netdata}/bin/netdata -P /run/netdata/netdata.pid -D -c ${configFile}";
+        ExecReload = "${pkgs.utillinux}/bin/kill -s HUP -s USR1 -s USR2 $MAINPID";
         TimeoutStopSec = 60;
+        # User and group
+        User = cfg.user;
+        Group = cfg.group;
+        # Runtime directory and mode
+        RuntimeDirectory = "netdata";
+        RuntimeDirectoryMode = "0755";
+        # Performance
+        LimitNOFILE = "30000";
       };
     };
 
@@ -165,6 +172,11 @@ in {
       permissions = "u+rx,g+rx,o-rwx";
     };
 
+    security.pam.loginLimits = [
+      { domain = "netdata"; type = "soft"; item = "nofile"; value = "10000"; }
+      { domain = "netdata"; type = "hard"; item = "nofile"; value = "30000"; }
+    ];
+
     users.users = optional (cfg.user == defaultUser) {
       name = defaultUser;
     };
diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix
index 22578b01260..f7f07bad952 100644
--- a/nixos/modules/tasks/filesystems/zfs.nix
+++ b/nixos/modules/tasks/filesystems/zfs.nix
@@ -179,10 +179,9 @@ in
 
       requestEncryptionCredentials = mkOption {
         type = types.bool;
-        default = config.boot.zfs.enableUnstable;
+        default = true;
         description = ''
           Request encryption keys or passwords for all encrypted datasets on import.
-          Dataset encryption is only supported in zfsUnstable at the moment.
           For root pools the encryption key can be supplied via both an
           interactive prompt (keylocation=prompt) and from a file
           (keylocation=file://). Note that for data pools the encryption key can
diff --git a/nixos/modules/virtualisation/kvmgt.nix b/nixos/modules/virtualisation/kvmgt.nix
index bfcf51d09c4..289e26e1703 100644
--- a/nixos/modules/virtualisation/kvmgt.nix
+++ b/nixos/modules/virtualisation/kvmgt.nix
@@ -4,13 +4,16 @@ with lib;
 
 let
   cfg = config.virtualisation.kvmgt;
+
   kernelPackages = config.boot.kernelPackages;
+
   vgpuOptions = {
     uuid = mkOption {
       type = types.string;
       description = "UUID of VGPU device. You can generate one with <package>libossp_uuid</package>.";
     };
   };
+
 in {
   options = {
     virtualisation.kvmgt = {
@@ -45,7 +48,13 @@ in {
       assertion = versionAtLeast kernelPackages.kernel.version "4.16";
       message = "KVMGT is not properly supported for kernels older than 4.16";
     };
-    boot.kernelParams = [ "i915.enable_gvt=1" ];
+
+    boot.kernelModules = [ "kvmgt" ];
+
+    boot.extraModprobeConfig = ''
+      options i915 enable_gvt=1
+    '';
+
     systemd.paths = mapAttrs' (name: value:
       nameValuePair "kvmgt-${name}" {
         description = "KVMGT VGPU ${name} path";
@@ -55,6 +64,7 @@ in {
         };
       }
     ) cfg.vgpus;
+
     systemd.services = mapAttrs' (name: value:
       nameValuePair "kvmgt-${name}" {
         description = "KVMGT VGPU ${name}";
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index 359f62751b9..2f527bfa090 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -139,6 +139,7 @@ in
   #lightdm = handleTest ./lightdm.nix {};
   limesurvey = handleTest ./limesurvey.nix {};
   login = handleTest ./login.nix {};
+  loki = handleTest ./loki.nix {};
   #logstash = handleTest ./logstash.nix {};
   mailcatcher = handleTest ./mailcatcher.nix {};
   mathics = handleTest ./mathics.nix {};
diff --git a/nixos/tests/loki.nix b/nixos/tests/loki.nix
new file mode 100644
index 00000000000..9c3058d02f8
--- /dev/null
+++ b/nixos/tests/loki.nix
@@ -0,0 +1,37 @@
+import ./make-test.nix ({ lib, pkgs, ... }:
+
+{
+  name = "loki";
+
+  meta = with lib.maintainers; {
+    maintainers = [ willibutz ];
+  };
+
+  machine = { ... }: {
+    services.loki = {
+      enable = true;
+      configFile = "${pkgs.grafana-loki.src}/cmd/loki/loki-local-config.yaml";
+    };
+    systemd.services.promtail = {
+      description = "Promtail service for Loki test";
+      wantedBy = [ "multi-user.target" ];
+
+      serviceConfig = {
+        ExecStart = ''
+          ${pkgs.grafana-loki}/bin/promtail --config.file ${pkgs.grafana-loki.src}/cmd/promtail/promtail-local-config.yaml
+        '';
+        DynamicUser = true;
+      };
+    };
+  };
+
+  testScript = ''
+    $machine->start;
+    $machine->waitForUnit("loki.service");
+    $machine->waitForUnit("promtail.service");
+    $machine->waitForOpenPort(3100);
+    $machine->waitForOpenPort(9080);
+    $machine->succeed("echo 'Loki Ingestion Test' > /var/log/testlog");
+    $machine->waitUntilSucceeds("${pkgs.grafana-loki}/bin/logcli --addr='http://localhost:3100' query --no-labels '{job=\"varlogs\",filename=\"/var/log/testlog\"}' | grep -q 'Loki Ingestion Test'");
+  '';
+})