aboutsummaryrefslogtreecommitdiff
path: root/nixpkgs/nixos/modules
diff options
context:
space:
mode:
authorKatharina Fey <kookie@spacekookie.de>2020-03-24 10:15:32 +0100
committerKatharina Fey <kookie@spacekookie.de>2020-03-24 10:15:32 +0100
commit96f063dd321abc80ecaa156226cfb7cf9540315a (patch)
tree7a53ef61484fc7bfff6419b1fd635c67199f27d2 /nixpkgs/nixos/modules
parentaf58f08d3d524e7b008b73a8497ea710915ffaf1 (diff)
parentd96bd3394b734487d1c3bfbac0e8f17465e03afe (diff)
Merge commit 'd96bd3394b734487d1c3bfbac0e8f17465e03afe'
Diffstat (limited to 'nixpkgs/nixos/modules')
-rw-r--r--nixpkgs/nixos/modules/config/ldap.nix3
-rw-r--r--nixpkgs/nixos/modules/config/networking.nix27
-rw-r--r--nixpkgs/nixos/modules/config/pulseaudio.nix3
-rw-r--r--nixpkgs/nixos/modules/config/resolvconf.nix10
-rw-r--r--nixpkgs/nixos/modules/config/swap.nix2
-rw-r--r--nixpkgs/nixos/modules/config/system-path.nix1
-rw-r--r--nixpkgs/nixos/modules/config/xdg/portal.nix6
-rw-r--r--nixpkgs/nixos/modules/hardware/brightnessctl.nix31
-rw-r--r--nixpkgs/nixos/modules/hardware/openrazer.nix2
-rw-r--r--nixpkgs/nixos/modules/hardware/video/amdgpu-pro.nix2
-rw-r--r--nixpkgs/nixos/modules/hardware/video/ati.nix2
-rw-r--r--nixpkgs/nixos/modules/hardware/video/nvidia.nix138
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/channel.nix4
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix3
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix21
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix14
-rw-r--r--nixpkgs/nixos/modules/installer/netboot/netboot.nix14
-rw-r--r--nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix8
-rw-r--r--nixpkgs/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix2
-rw-r--r--nixpkgs/nixos/modules/installer/tools/nixos-enter.sh18
-rw-r--r--nixpkgs/nixos/modules/installer/tools/nixos-option/nixos-option.cc251
-rw-r--r--nixpkgs/nixos/modules/installer/tools/nixos-rebuild.sh98
-rw-r--r--nixpkgs/nixos/modules/installer/tools/nixos-version.sh9
-rw-r--r--nixpkgs/nixos/modules/installer/tools/tools.nix9
-rw-r--r--nixpkgs/nixos/modules/misc/ids.nix8
-rw-r--r--nixpkgs/nixos/modules/misc/locate.nix7
-rw-r--r--nixpkgs/nixos/modules/misc/nixpkgs.nix8
-rw-r--r--nixpkgs/nixos/modules/misc/version.nix16
-rw-r--r--nixpkgs/nixos/modules/module-list.nix25
-rw-r--r--nixpkgs/nixos/modules/programs/bash-my-aws.nix25
-rw-r--r--nixpkgs/nixos/modules/programs/bash/bash.nix13
-rw-r--r--nixpkgs/nixos/modules/programs/firejail.nix30
-rw-r--r--nixpkgs/nixos/modules/programs/fish_completion-generator.patch12
-rw-r--r--nixpkgs/nixos/modules/programs/sway.nix4
-rw-r--r--nixpkgs/nixos/modules/programs/tmux.nix8
-rw-r--r--nixpkgs/nixos/modules/programs/zsh/zsh.nix69
-rw-r--r--nixpkgs/nixos/modules/rename.nix19
-rw-r--r--nixpkgs/nixos/modules/security/acme.nix224
-rw-r--r--nixpkgs/nixos/modules/security/acme.xml2
-rw-r--r--nixpkgs/nixos/modules/security/duosec.nix16
-rw-r--r--nixpkgs/nixos/modules/security/google_oslogin.nix6
-rw-r--r--nixpkgs/nixos/modules/security/rngd.nix12
-rw-r--r--nixpkgs/nixos/modules/security/sudo.nix36
-rw-r--r--nixpkgs/nixos/modules/security/tpm2.nix185
-rw-r--r--nixpkgs/nixos/modules/services/audio/alsa.nix6
-rw-r--r--nixpkgs/nixos/modules/services/audio/mopidy.nix4
-rw-r--r--nixpkgs/nixos/modules/services/backup/restic.nix56
-rw-r--r--nixpkgs/nixos/modules/services/backup/sanoid.nix213
-rw-r--r--nixpkgs/nixos/modules/services/backup/syncoid.nix168
-rw-r--r--nixpkgs/nixos/modules/services/computing/foldingathome/client.nix81
-rw-r--r--nixpkgs/nixos/modules/services/computing/slurm/slurm.nix1
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/buildkite-agents.nix (renamed from nixpkgs/nixos/modules/services/continuous-integration/buildkite-agent.nix)81
-rw-r--r--nixpkgs/nixos/modules/services/databases/mysql.nix103
-rw-r--r--nixpkgs/nixos/modules/services/databases/postgresql.nix35
-rw-r--r--nixpkgs/nixos/modules/services/databases/redis.nix47
-rw-r--r--nixpkgs/nixos/modules/services/desktops/malcontent.nix32
-rw-r--r--nixpkgs/nixos/modules/services/development/jupyter/default.nix6
-rw-r--r--nixpkgs/nixos/modules/services/hardware/fwupd.nix5
-rw-r--r--nixpkgs/nixos/modules/services/hardware/irqbalance.nix14
-rw-r--r--nixpkgs/nixos/modules/services/hardware/tlp.nix142
-rw-r--r--nixpkgs/nixos/modules/services/mail/dovecot.nix234
-rw-r--r--nixpkgs/nixos/modules/services/mail/mailman.nix8
-rw-r--r--nixpkgs/nixos/modules/services/mail/sympa.nix596
-rw-r--r--nixpkgs/nixos/modules/services/misc/ankisyncd.nix79
-rw-r--r--nixpkgs/nixos/modules/services/misc/autorandr.nix2
-rw-r--r--nixpkgs/nixos/modules/services/misc/disnix.nix5
-rw-r--r--nixpkgs/nixos/modules/services/misc/folding-at-home.nix67
-rw-r--r--nixpkgs/nixos/modules/services/misc/home-assistant.nix15
-rw-r--r--nixpkgs/nixos/modules/services/misc/matrix-synapse.nix46
-rw-r--r--nixpkgs/nixos/modules/services/misc/matrix-synapse.xml224
-rw-r--r--nixpkgs/nixos/modules/services/misc/parsoid.nix25
-rw-r--r--nixpkgs/nixos/modules/services/misc/sssd.nix6
-rw-r--r--nixpkgs/nixos/modules/services/misc/zoneminder.nix4
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/cadvisor.nix1
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/heapster.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/nagios.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix27
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix17
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/json.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mail.nix9
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mikrotik.nix66
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/minio.nix4
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix13
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix6
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix16
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix4
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix4
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/xmpp-alerts.nix47
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/statsd.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/cjdns.nix52
-rw-r--r--nixpkgs/nixos/modules/services/networking/dhcpcd.nix4
-rw-r--r--nixpkgs/nixos/modules/services/networking/dnscrypt-proxy.nix328
-rw-r--r--nixpkgs/nixos/modules/services/networking/dnscrypt-proxy.xml66
-rw-r--r--nixpkgs/nixos/modules/services/networking/dnscrypt-proxy2.nix61
-rw-r--r--nixpkgs/nixos/modules/services/networking/firewall.nix10
-rw-r--r--nixpkgs/nixos/modules/services/networking/freeradius.nix18
-rw-r--r--nixpkgs/nixos/modules/services/networking/git-daemon.nix4
-rw-r--r--nixpkgs/nixos/modules/services/networking/haproxy.nix26
-rw-r--r--nixpkgs/nixos/modules/services/networking/i2pd.nix22
-rw-r--r--nixpkgs/nixos/modules/services/networking/iodine.nix163
-rw-r--r--nixpkgs/nixos/modules/services/networking/iwd.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/knot.nix40
-rw-r--r--nixpkgs/nixos/modules/services/networking/kresd.nix152
-rw-r--r--nixpkgs/nixos/modules/services/networking/minidlna.nix17
-rw-r--r--nixpkgs/nixos/modules/services/networking/nat.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/nix-store-gcs-proxy.nix75
-rw-r--r--nixpkgs/nixos/modules/services/networking/nsd.nix4
-rw-r--r--nixpkgs/nixos/modules/services/networking/ntp/ntpd.nix13
-rw-r--r--nixpkgs/nixos/modules/services/networking/pppd.nix4
-rw-r--r--nixpkgs/nixos/modules/services/networking/shorewall.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/shorewall6.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/smartdns.nix61
-rw-r--r--nixpkgs/nixos/modules/services/networking/ssh/sshd.nix26
-rw-r--r--nixpkgs/nixos/modules/services/networking/sslh.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/stubby.nix3
-rw-r--r--nixpkgs/nixos/modules/services/networking/supybot.nix111
-rw-r--r--nixpkgs/nixos/modules/services/networking/tailscale.nix46
-rw-r--r--nixpkgs/nixos/modules/services/networking/vsftpd.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/wireguard.nix6
-rw-r--r--nixpkgs/nixos/modules/services/networking/zerotierone.nix11
-rw-r--r--nixpkgs/nixos/modules/services/torrent/transmission.nix3
-rw-r--r--nixpkgs/nixos/modules/services/wayland/cage.nix99
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/codimd.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/grocy.nix172
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/grocy.xml77
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/jirafeau.nix169
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/limesurvey.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/mattermost.nix16
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/mediawiki.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/moodle.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/nextcloud.nix4
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/wordpress.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/zabbix.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix210
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/apache-httpd/vhost-options.nix (renamed from nixpkgs/nixos/modules/services/web-servers/apache-httpd/per-server-options.nix)9
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/caddy.nix18
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/nginx/default.nix20
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/uwsgi.nix2
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix1
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix5
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.xml130
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix178
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/xfce.nix11
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/default.nix7
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/gdm.nix5
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/tiny.nix92
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/lightdm.nix1
-rw-r--r--nixpkgs/nixos/modules/services/x11/unclutter.nix2
-rw-r--r--nixpkgs/nixos/modules/services/x11/urxvtd.nix6
-rw-r--r--nixpkgs/nixos/modules/services/x11/xserver.nix76
-rw-r--r--nixpkgs/nixos/modules/system/activation/activation-script.nix33
-rw-r--r--nixpkgs/nixos/modules/system/activation/switch-to-configuration.pl4
-rw-r--r--nixpkgs/nixos/modules/system/activation/top-level.nix1
-rw-r--r--nixpkgs/nixos/modules/system/boot/initrd-network.nix64
-rw-r--r--nixpkgs/nixos/modules/system/boot/kernel.nix272
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix8
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl3
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/grub/memtest.nix57
-rw-r--r--nixpkgs/nixos/modules/system/boot/networkd.nix168
-rw-r--r--nixpkgs/nixos/modules/system/boot/stage-1-init.sh19
-rw-r--r--nixpkgs/nixos/modules/system/boot/stage-1.nix28
-rw-r--r--nixpkgs/nixos/modules/system/boot/systemd-lib.nix5
-rw-r--r--nixpkgs/nixos/modules/system/boot/systemd.nix28
-rw-r--r--nixpkgs/nixos/modules/system/etc/etc.nix8
-rw-r--r--nixpkgs/nixos/modules/tasks/auto-upgrade.nix15
-rw-r--r--nixpkgs/nixos/modules/tasks/encrypted-devices.nix2
-rw-r--r--nixpkgs/nixos/modules/tasks/filesystems.nix9
-rw-r--r--nixpkgs/nixos/modules/tasks/filesystems/btrfs.nix7
-rw-r--r--nixpkgs/nixos/modules/tasks/filesystems/zfs.nix6
-rw-r--r--nixpkgs/nixos/modules/tasks/network-interfaces-scripted.nix49
-rw-r--r--nixpkgs/nixos/modules/tasks/network-interfaces-systemd.nix69
-rw-r--r--nixpkgs/nixos/modules/tasks/network-interfaces.nix119
-rw-r--r--nixpkgs/nixos/modules/testing/service-runner.nix28
-rw-r--r--nixpkgs/nixos/modules/virtualisation/docker-containers.nix34
-rw-r--r--nixpkgs/nixos/modules/virtualisation/hyperv-guest.nix2
-rw-r--r--nixpkgs/nixos/modules/virtualisation/kvmgt.nix16
-rw-r--r--nixpkgs/nixos/modules/virtualisation/libvirtd.nix2
-rw-r--r--nixpkgs/nixos/modules/virtualisation/openvswitch.nix7
-rw-r--r--nixpkgs/nixos/modules/virtualisation/virtualbox-image.nix39
185 files changed, 5699 insertions, 2031 deletions
diff --git a/nixpkgs/nixos/modules/config/ldap.nix b/nixpkgs/nixos/modules/config/ldap.nix
index 9c8e9d14937..b554f197dc4 100644
--- a/nixpkgs/nixos/modules/config/ldap.nix
+++ b/nixpkgs/nixos/modules/config/ldap.nix
@@ -28,8 +28,6 @@ let
};
nslcdConfig = writeText "nslcd.conf" ''
- uid nslcd
- gid nslcd
uri ${cfg.server}
base ${cfg.base}
timelimit ${toString cfg.timeLimit}
@@ -282,6 +280,7 @@ in
Group = "nslcd";
RuntimeDirectory = [ "nslcd" ];
PIDFile = "/run/nslcd/nslcd.pid";
+ AmbientCapabilities = "CAP_SYS_RESOURCE";
};
};
diff --git a/nixpkgs/nixos/modules/config/networking.nix b/nixpkgs/nixos/modules/config/networking.nix
index 81427bb8ee6..dd36696b94d 100644
--- a/nixpkgs/nixos/modules/config/networking.nix
+++ b/nixpkgs/nixos/modules/config/networking.nix
@@ -35,12 +35,22 @@ in
'';
};
+ networking.hostFiles = lib.mkOption {
+ type = types.listOf types.path;
+ defaultText = lib.literalExample "Hosts from `networking.hosts` and `networking.extraHosts`";
+ example = lib.literalExample ''[ "''${pkgs.my-blocklist-package}/share/my-blocklist/hosts" ]'';
+ description = ''
+ Files that should be concatenated together to form <filename>/etc/hosts</filename>.
+ '';
+ };
+
networking.extraHosts = lib.mkOption {
type = types.lines;
default = "";
example = "192.168.0.1 lanlocalhost";
description = ''
Additional verbatim entries to be appended to <filename>/etc/hosts</filename>.
+ For adding hosts from derivation results, use <option>networking.hostFiles</option> instead.
'';
};
@@ -159,6 +169,15 @@ in
"::1" = [ "localhost" ];
};
+ networking.hostFiles = let
+ stringHosts =
+ let
+ oneToString = set: ip: ip + " " + concatStringsSep " " set.${ip} + "\n";
+ allToString = set: concatMapStrings (oneToString set) (attrNames set);
+ in pkgs.writeText "string-hosts" (allToString (filterAttrs (_: v: v != []) cfg.hosts));
+ extraHosts = pkgs.writeText "extra-hosts" cfg.extraHosts;
+ in mkBefore [ stringHosts extraHosts ];
+
environment.etc =
{ # /etc/services: TCP/UDP port assignments.
services.source = pkgs.iana-etc + "/etc/services";
@@ -167,12 +186,8 @@ in
protocols.source = pkgs.iana-etc + "/etc/protocols";
# /etc/hosts: Hostname-to-IP mappings.
- hosts.text = let
- oneToString = set: ip: ip + " " + concatStringsSep " " set.${ip};
- allToString = set: concatMapStringsSep "\n" (oneToString set) (attrNames set);
- in ''
- ${allToString (filterAttrs (_: v: v != []) cfg.hosts)}
- ${cfg.extraHosts}
+ hosts.source = pkgs.runCommandNoCC "hosts" {} ''
+ cat ${escapeShellArgs cfg.hostFiles} > $out
'';
# /etc/host.conf: resolver configuration file
diff --git a/nixpkgs/nixos/modules/config/pulseaudio.nix b/nixpkgs/nixos/modules/config/pulseaudio.nix
index 048bbb30c73..408d0a9c33f 100644
--- a/nixpkgs/nixos/modules/config/pulseaudio.nix
+++ b/nixpkgs/nixos/modules/config/pulseaudio.nix
@@ -248,6 +248,9 @@ in {
security.rtkit.enable = true;
systemd.packages = [ overriddenPackage ];
+
+ # PulseAudio is packaged with udev rules to handle various audio device quirks
+ services.udev.packages = [ overriddenPackage ];
})
(mkIf (cfg.extraModules != []) {
diff --git a/nixpkgs/nixos/modules/config/resolvconf.nix b/nixpkgs/nixos/modules/config/resolvconf.nix
index 7d2f252a888..cc202bca6c4 100644
--- a/nixpkgs/nixos/modules/config/resolvconf.nix
+++ b/nixpkgs/nixos/modules/config/resolvconf.nix
@@ -38,6 +38,7 @@ in
(mkRenamedOptionModule [ "networking" "dnsExtensionMechanism" ] [ "networking" "resolvconf" "dnsExtensionMechanism" ])
(mkRenamedOptionModule [ "networking" "extraResolvconfConf" ] [ "networking" "resolvconf" "extraConfig" ])
(mkRenamedOptionModule [ "networking" "resolvconfOptions" ] [ "networking" "resolvconf" "extraOptions" ])
+ (mkRemovedOptionModule [ "networking" "resolvconf" "useHostResolvConf" ] "This option was never used for anything anyways")
];
options = {
@@ -53,15 +54,6 @@ in
'';
};
- useHostResolvConf = mkOption {
- type = types.bool;
- default = false;
- description = ''
- In containers, whether to use the
- <filename>resolv.conf</filename> supplied by the host.
- '';
- };
-
dnsSingleRequest = lib.mkOption {
type = types.bool;
default = false;
diff --git a/nixpkgs/nixos/modules/config/swap.nix b/nixpkgs/nixos/modules/config/swap.nix
index d0fc0d4a3ea..adb4e229421 100644
--- a/nixpkgs/nixos/modules/config/swap.nix
+++ b/nixpkgs/nixos/modules/config/swap.nix
@@ -185,6 +185,8 @@ in
{ description = "Initialisation of swap device ${sw.device}";
wantedBy = [ "${realDevice'}.swap" ];
before = [ "${realDevice'}.swap" ];
+ # If swap is encrypted, depending on rngd resolves a possible entropy starvation during boot
+ after = mkIf (config.security.rngd.enable && sw.randomEncryption.enable) [ "rngd.service" ];
path = [ pkgs.utillinux ] ++ optional sw.randomEncryption.enable pkgs.cryptsetup;
script =
diff --git a/nixpkgs/nixos/modules/config/system-path.nix b/nixpkgs/nixos/modules/config/system-path.nix
index aba9bc0945b..4100ec89701 100644
--- a/nixpkgs/nixos/modules/config/system-path.nix
+++ b/nixpkgs/nixos/modules/config/system-path.nix
@@ -116,6 +116,7 @@ in
"/lib" # FIXME: remove and update debug-info.nix
"/sbin"
"/share/emacs"
+ "/share/hunspell"
"/share/nano"
"/share/org"
"/share/themes"
diff --git a/nixpkgs/nixos/modules/config/xdg/portal.nix b/nixpkgs/nixos/modules/config/xdg/portal.nix
index 95fa8e05fa3..1330a08070c 100644
--- a/nixpkgs/nixos/modules/config/xdg/portal.nix
+++ b/nixpkgs/nixos/modules/config/xdg/portal.nix
@@ -42,6 +42,10 @@ with lib;
let
cfg = config.xdg.portal;
packages = [ pkgs.xdg-desktop-portal ] ++ cfg.extraPortals;
+ joinedPortals = pkgs.symlinkJoin {
+ name = "xdg-portals";
+ paths = cfg.extraPortals;
+ };
in mkIf cfg.enable {
@@ -56,7 +60,7 @@ with lib;
environment.variables = {
GTK_USE_PORTAL = mkIf cfg.gtkUsePortal "1";
- XDG_DESKTOP_PORTAL_PATH = map (p: "${p}/share/xdg-desktop-portal/portals") cfg.extraPortals;
+ XDG_DESKTOP_PORTAL_DIR = "${joinedPortals}/share/xdg-desktop-portal/portals";
};
};
}
diff --git a/nixpkgs/nixos/modules/hardware/brightnessctl.nix b/nixpkgs/nixos/modules/hardware/brightnessctl.nix
deleted file mode 100644
index 2d54398d10d..00000000000
--- a/nixpkgs/nixos/modules/hardware/brightnessctl.nix
+++ /dev/null
@@ -1,31 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-let
- cfg = config.hardware.brightnessctl;
-in
-{
-
- options = {
-
- hardware.brightnessctl = {
-
- enable = mkOption {
- default = false;
- type = types.bool;
- description = ''
- Enable brightnessctl in userspace.
- This will allow brightness control from users in the video group.
- '';
-
- };
- };
- };
-
-
- config = mkIf cfg.enable {
- services.udev.packages = with pkgs; [ brightnessctl ];
- environment.systemPackages = with pkgs; [ brightnessctl ];
- };
-
-}
diff --git a/nixpkgs/nixos/modules/hardware/openrazer.nix b/nixpkgs/nixos/modules/hardware/openrazer.nix
index 883db7f2f4f..b5c3d674414 100644
--- a/nixpkgs/nixos/modules/hardware/openrazer.nix
+++ b/nixpkgs/nixos/modules/hardware/openrazer.nix
@@ -49,7 +49,7 @@ in
{
options = {
hardware.openrazer = {
- enable = mkEnableOption "OpenRazer drivers and userspace daemon.";
+ enable = mkEnableOption "OpenRazer drivers and userspace daemon";
verboseLogging = mkOption {
type = types.bool;
diff --git a/nixpkgs/nixos/modules/hardware/video/amdgpu-pro.nix b/nixpkgs/nixos/modules/hardware/video/amdgpu-pro.nix
index 8e91e9d2baa..ec1c8c2d57a 100644
--- a/nixpkgs/nixos/modules/hardware/video/amdgpu-pro.nix
+++ b/nixpkgs/nixos/modules/hardware/video/amdgpu-pro.nix
@@ -30,7 +30,7 @@ in
nixpkgs.config.xorg.abiCompat = "1.19";
services.xserver.drivers = singleton
- { name = "amdgpu"; modules = [ package ]; };
+ { name = "amdgpu"; modules = [ package ]; display = true; };
hardware.opengl.package = package;
hardware.opengl.package32 = package32;
diff --git a/nixpkgs/nixos/modules/hardware/video/ati.nix b/nixpkgs/nixos/modules/hardware/video/ati.nix
index 0aab7bd6b92..06d3ea324d8 100644
--- a/nixpkgs/nixos/modules/hardware/video/ati.nix
+++ b/nixpkgs/nixos/modules/hardware/video/ati.nix
@@ -21,7 +21,7 @@ in
nixpkgs.config.xorg.abiCompat = "1.17";
services.xserver.drivers = singleton
- { name = "fglrx"; modules = [ ati_x11 ]; };
+ { name = "fglrx"; modules = [ ati_x11 ]; display = true; };
hardware.opengl.package = ati_x11;
hardware.opengl.package32 = pkgs.pkgsi686Linux.linuxPackages.ati_drivers_x11.override { libsOnly = true; kernel = null; };
diff --git a/nixpkgs/nixos/modules/hardware/video/nvidia.nix b/nixpkgs/nixos/modules/hardware/video/nvidia.nix
index 1794bb4b433..7461e231402 100644
--- a/nixpkgs/nixos/modules/hardware/video/nvidia.nix
+++ b/nixpkgs/nixos/modules/hardware/video/nvidia.nix
@@ -34,26 +34,57 @@ let
enabled = nvidia_x11 != null;
cfg = config.hardware.nvidia;
- optimusCfg = cfg.optimus_prime;
+ pCfg = cfg.prime;
+ syncCfg = pCfg.sync;
+ offloadCfg = pCfg.offload;
+ primeEnabled = syncCfg.enable || offloadCfg.enable;
in
{
+ imports =
+ [
+ (mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "enable" ] [ "hardware" "nvidia" "prime" "sync" "enable" ])
+ (mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "allowExternalGpu" ] [ "hardware" "nvidia" "prime" "sync" "allowExternalGpu" ])
+ (mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "nvidiaBusId" ] [ "hardware" "nvidia" "prime" "nvidiaBusId" ])
+ (mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "intelBusId" ] [ "hardware" "nvidia" "prime" "intelBusId" ])
+ ];
+
options = {
- hardware.nvidia.modesetting.enable = lib.mkOption {
- type = lib.types.bool;
+ hardware.nvidia.modesetting.enable = mkOption {
+ type = types.bool;
default = false;
description = ''
Enable kernel modesetting when using the NVIDIA proprietary driver.
Enabling this fixes screen tearing when using Optimus via PRIME (see
- <option>hardware.nvidia.optimus_prime.enable</option>. This is not enabled
+ <option>hardware.nvidia.prime.sync.enable</option>. This is not enabled
by default because it is not officially supported by NVIDIA and would not
work with SLI.
'';
};
- hardware.nvidia.optimus_prime.enable = lib.mkOption {
- type = lib.types.bool;
+ hardware.nvidia.prime.nvidiaBusId = mkOption {
+ type = types.str;
+ default = "";
+ example = "PCI:1:0:0";
+ description = ''
+ Bus ID of the NVIDIA GPU. You can find it using lspci; for example if lspci
+ shows the NVIDIA GPU at "01:00.0", set this option to "PCI:1:0:0".
+ '';
+ };
+
+ hardware.nvidia.prime.intelBusId = mkOption {
+ type = types.str;
+ default = "";
+ example = "PCI:0:2:0";
+ description = ''
+ Bus ID of the Intel GPU. You can find it using lspci; for example if lspci
+ shows the Intel GPU at "00:02.0", set this option to "PCI:0:2:0".
+ '';
+ };
+
+ hardware.nvidia.prime.sync.enable = mkOption {
+ type = types.bool;
default = false;
description = ''
Enable NVIDIA Optimus support using the NVIDIA proprietary driver via PRIME.
@@ -66,8 +97,8 @@ in
be the only driver there.
If this is enabled, then the bus IDs of the NVIDIA and Intel GPUs have to be
- specified (<option>hardware.nvidia.optimus_prime.nvidiaBusId</option> and
- <option>hardware.nvidia.optimus_prime.intelBusId</option>).
+ specified (<option>hardware.nvidia.prime.nvidiaBusId</option> and
+ <option>hardware.nvidia.prime.intelBusId</option>).
If you enable this, you may want to also enable kernel modesetting for the
NVIDIA driver (<option>hardware.nvidia.modesetting.enable</option>) in order
@@ -79,31 +110,23 @@ in
'';
};
- hardware.nvidia.optimus_prime.allowExternalGpu = lib.mkOption {
- type = lib.types.bool;
+ hardware.nvidia.prime.sync.allowExternalGpu = mkOption {
+ type = types.bool;
default = false;
description = ''
Configure X to allow external NVIDIA GPUs when using optimus.
'';
};
- hardware.nvidia.optimus_prime.nvidiaBusId = lib.mkOption {
- type = lib.types.str;
- default = "";
- example = "PCI:1:0:0";
+ hardware.nvidia.prime.offload.enable = mkOption {
+ type = types.bool;
+ default = false;
description = ''
- Bus ID of the NVIDIA GPU. You can find it using lspci; for example if lspci
- shows the NVIDIA GPU at "01:00.0", set this option to "PCI:1:0:0".
- '';
- };
+ Enable render offload support using the NVIDIA proprietary driver via PRIME.
- hardware.nvidia.optimus_prime.intelBusId = lib.mkOption {
- type = lib.types.str;
- default = "";
- example = "PCI:0:2:0";
- description = ''
- Bus ID of the Intel GPU. You can find it using lspci; for example if lspci
- shows the Intel GPU at "00:02.0", set this option to "PCI:0:2:0".
+ If this is enabled, then the bus IDs of the NVIDIA and Intel GPUs have to be
+ specified (<option>hardware.nvidia.prime.nvidiaBusId</option> and
+ <option>hardware.nvidia.prime.intelBusId</option>).
'';
};
};
@@ -116,12 +139,19 @@ in
}
{
- assertion = !optimusCfg.enable ||
- (optimusCfg.nvidiaBusId != "" && optimusCfg.intelBusId != "");
+ assertion = primeEnabled -> pCfg.nvidiaBusId != "" && pCfg.intelBusId != "";
message = ''
- When NVIDIA Optimus via PRIME is enabled, the GPU bus IDs must configured.
+ When NVIDIA PRIME is enabled, the GPU bus IDs must configured.
'';
}
+ {
+ assertion = offloadCfg.enable -> versionAtLeast nvidia_x11.version "435.21";
+ message = "NVIDIA PRIME render offload is currently only supported on versions >= 435.21.";
+ }
+ {
+ assertion = !(syncCfg.enable && offloadCfg.enable);
+ message = "Only one NVIDIA PRIME solution may be used at a time.";
+ }
];
# If Optimus/PRIME is enabled, we:
@@ -136,36 +166,38 @@ in
# - Configure the display manager to run specific `xrandr` commands which will
# configure/enable displays connected to the Intel GPU.
- services.xserver.drivers = singleton {
+ services.xserver.useGlamor = mkDefault offloadCfg.enable;
+
+ services.xserver.drivers = optional primeEnabled {
+ name = "modesetting";
+ display = offloadCfg.enable;
+ deviceSection = ''
+ BusID "${pCfg.intelBusId}"
+ ${optionalString syncCfg.enable ''Option "AccelMethod" "none"''}
+ '';
+ } ++ singleton {
name = "nvidia";
modules = [ nvidia_x11.bin ];
- deviceSection = optionalString optimusCfg.enable
+ display = !offloadCfg.enable;
+ deviceSection = optionalString primeEnabled
''
- BusID "${optimusCfg.nvidiaBusId}"
- ${optionalString optimusCfg.allowExternalGpu "Option \"AllowExternalGpus\""}
+ BusID "${pCfg.nvidiaBusId}"
+ ${optionalString syncCfg.allowExternalGpu "Option \"AllowExternalGpus\""}
'';
screenSection =
''
Option "RandRRotation" "on"
- ${optionalString optimusCfg.enable "Option \"AllowEmptyInitialConfiguration\""}
+ ${optionalString syncCfg.enable "Option \"AllowEmptyInitialConfiguration\""}
'';
};
- services.xserver.extraConfig = optionalString optimusCfg.enable
- ''
- Section "Device"
- Identifier "nvidia-optimus-intel"
- Driver "modesetting"
- BusID "${optimusCfg.intelBusId}"
- Option "AccelMethod" "none"
- EndSection
- '';
- services.xserver.serverLayoutSection = optionalString optimusCfg.enable
- ''
- Inactive "nvidia-optimus-intel"
- '';
+ services.xserver.serverLayoutSection = optionalString syncCfg.enable ''
+ Inactive "Device-modesetting[0]"
+ '' + optionalString offloadCfg.enable ''
+ Option "AllowNVIDIAGPUScreens"
+ '';
- services.xserver.displayManager.setupCommands = optionalString optimusCfg.enable ''
+ services.xserver.displayManager.setupCommands = optionalString syncCfg.enable ''
# Added by nvidia configuration module for Optimus/PRIME.
${pkgs.xorg.xrandr}/bin/xrandr --setprovideroutputsource modesetting NVIDIA-0
${pkgs.xorg.xrandr}/bin/xrandr --auto
@@ -175,11 +207,13 @@ in
source = "${nvidia_x11.bin}/share/nvidia/nvidia-application-profiles-rc";
};
- hardware.opengl.package = nvidia_x11.out;
- hardware.opengl.package32 = nvidia_libs32;
+ hardware.opengl.package = mkIf (!offloadCfg.enable) nvidia_x11.out;
+ hardware.opengl.package32 = mkIf (!offloadCfg.enable) nvidia_libs32;
+ hardware.opengl.extraPackages = optional offloadCfg.enable nvidia_x11.out;
+ hardware.opengl.extraPackages32 = optional offloadCfg.enable nvidia_libs32;
environment.systemPackages = [ nvidia_x11.bin nvidia_x11.settings ]
- ++ lib.filter (p: p != null) [ nvidia_x11.persistenced ];
+ ++ filter (p: p != null) [ nvidia_x11.persistenced ];
systemd.tmpfiles.rules = optional config.virtualisation.docker.enableNvidia
"L+ /run/nvidia-docker/bin - - - - ${nvidia_x11.bin}/origBin"
@@ -190,10 +224,10 @@ in
# nvidia-uvm is required by CUDA applications.
boot.kernelModules = [ "nvidia-uvm" ] ++
- lib.optionals config.services.xserver.enable [ "nvidia" "nvidia_modeset" "nvidia_drm" ];
+ optionals config.services.xserver.enable [ "nvidia" "nvidia_modeset" "nvidia_drm" ];
# If requested enable modesetting via kernel parameter.
- boot.kernelParams = optional cfg.modesetting.enable "nvidia-drm.modeset=1";
+ boot.kernelParams = optional (offloadCfg.enable || cfg.modesetting.enable) "nvidia-drm.modeset=1";
# Create /dev/nvidia-uvm when the nvidia-uvm module is loaded.
services.udev.extraRules =
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/channel.nix b/nixpkgs/nixos/modules/installer/cd-dvd/channel.nix
index ab5e7c0645f..92164d65e53 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/channel.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/channel.nix
@@ -21,7 +21,9 @@ let
if [ ! -e $out/nixos/nixpkgs ]; then
ln -s . $out/nixos/nixpkgs
fi
- echo -n ${config.system.nixos.revision} > $out/nixos/.git-revision
+ ${optionalString (config.system.nixos.revision != null) ''
+ echo -n ${config.system.nixos.revision} > $out/nixos/.git-revision
+ ''}
echo -n ${config.system.nixos.versionSuffix} > $out/nixos/.version-suffix
echo ${config.system.nixos.versionSuffix} | sed -e s/pre// > $out/nixos/svn-revision
'';
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix
index e0b558dcb0d..fa19daf1328 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix
@@ -44,6 +44,9 @@ with lib;
pkgs.bvi # binary editor
pkgs.joe
+ # Include some version control tools.
+ pkgs.git
+
# Firefox for reading the manual.
pkgs.firefox
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix
index 23c3426bff0..62cbdbcfd17 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix
@@ -1,5 +1,4 @@
-# This module defines a NixOS installation CD that contains X11 and
-# GNOME 3.
+# This module defines a NixOS installation CD that contains GNOME.
{ lib, ... }:
@@ -10,10 +9,22 @@ with lib;
services.xserver.desktopManager.gnome3.enable = true;
- # Auto-login as root.
- services.xserver.displayManager.gdm.autoLogin = {
+ # Wayland can be problematic for some hardware like Nvidia graphics cards.
+ services.xserver.displayManager.defaultSession = "gnome-xorg";
+
+ services.xserver.displayManager.gdm = {
enable = true;
- user = "root";
+ # autoSuspend makes the machine automatically suspend after inactivity.
+ # It's possible someone could/try to ssh'd into the machine and obviously
+ # have issues because it's inactive.
+ # See:
+ # * https://github.com/NixOS/nixpkgs/pull/63790
+ # * https://gitlab.gnome.org/GNOME/gnome-control-center/issues/22
+ autoSuspend = false;
+ autoLogin = {
+ enable = true;
+ user = "nixos";
+ };
};
}
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix b/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix
index 11319e5f4f8..4558b4dc955 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -569,14 +569,18 @@ in
};
fileSystems."/nix/store" =
- { fsType = "unionfs-fuse";
- device = "unionfs";
- options = [ "allow_other" "cow" "nonempty" "chroot=/mnt-root" "max_files=32768" "hide_meta_files" "dirs=/nix/.rw-store=rw:/nix/.ro-store=ro" ];
+ { fsType = "overlay";
+ device = "overlay";
+ options = [
+ "lowerdir=/nix/.ro-store"
+ "upperdir=/nix/.rw-store/store"
+ "workdir=/nix/.rw-store/work"
+ ];
};
- boot.initrd.availableKernelModules = [ "squashfs" "iso9660" "uas" ];
+ boot.initrd.availableKernelModules = [ "squashfs" "iso9660" "uas" "overlay" ];
- boot.initrd.kernelModules = [ "loop" ];
+ boot.initrd.kernelModules = [ "loop" "overlay" ];
# Closures to be copied to the Nix store on the CD, namely the init
# script and the top-level system configuration directory.
diff --git a/nixpkgs/nixos/modules/installer/netboot/netboot.nix b/nixpkgs/nixos/modules/installer/netboot/netboot.nix
index 5146858cccf..95eba86bcb6 100644
--- a/nixpkgs/nixos/modules/installer/netboot/netboot.nix
+++ b/nixpkgs/nixos/modules/installer/netboot/netboot.nix
@@ -50,14 +50,18 @@ with lib;
};
fileSystems."/nix/store" =
- { fsType = "unionfs-fuse";
- device = "unionfs";
- options = [ "allow_other" "cow" "nonempty" "chroot=/mnt-root" "max_files=32768" "hide_meta_files" "dirs=/nix/.rw-store=rw:/nix/.ro-store=ro" ];
+ { fsType = "overlay";
+ device = "overlay";
+ options = [
+ "lowerdir=/nix/.ro-store"
+ "upperdir=/nix/.rw-store/store"
+ "workdir=/nix/.rw-store/work"
+ ];
};
- boot.initrd.availableKernelModules = [ "squashfs" ];
+ boot.initrd.availableKernelModules = [ "squashfs" "overlay" ];
- boot.initrd.kernelModules = [ "loop" ];
+ boot.initrd.kernelModules = [ "loop" "overlay" ];
# Closures to be copied to the Nix store, namely the init
# script and the top-level system configuration directory.
diff --git a/nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix b/nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix
index c2f2578733b..2068f27f1c9 100644
--- a/nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix
+++ b/nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix
@@ -1,6 +1,6 @@
{
- x86_64-linux = "/nix/store/0q5qnh10m2sfrriszc1ysmggw659q6qm-nix-2.3.2";
- i686-linux = "/nix/store/i7ad7r5d8a5b3l22hg4a1im2qq05y6vd-nix-2.3.2";
- aarch64-linux = "/nix/store/bv06pavfw0dbqzr8w3l7s71nx27gnxa0-nix-2.3.2";
- x86_64-darwin = "/nix/store/x6mnl1nij7y4v5ihlplr4k937ayr403r-nix-2.3.2";
+ x86_64-linux = "/nix/store/ddmmzn4ggz1f66lwxjy64n89864yj9w9-nix-2.3.3";
+ i686-linux = "/nix/store/5axys7hsggb4282dsbps5k5p0v59yv13-nix-2.3.3";
+ aarch64-linux = "/nix/store/k80nwvi19hxwbz3c9cxgp24f1jjxwmcc-nix-2.3.3";
+ x86_64-darwin = "/nix/store/lrnvapsqmf0ja6zfyx4cpxr7ahdr7f9b-nix-2.3.3";
}
diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix b/nixpkgs/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix
index c1028a0ad7e..90f0702f717 100644
--- a/nixpkgs/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix
+++ b/nixpkgs/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix
@@ -5,7 +5,7 @@
let nodes = import networkExpr; in
-with import ../../../../lib/testing.nix {
+with import ../../../../lib/testing-python.nix {
inherit system;
pkgs = import ../../../../.. { inherit system config; };
};
diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-enter.sh b/nixpkgs/nixos/modules/installer/tools/nixos-enter.sh
index 4680cd8ae95..1fdd4627a90 100644
--- a/nixpkgs/nixos/modules/installer/tools/nixos-enter.sh
+++ b/nixpkgs/nixos/modules/installer/tools/nixos-enter.sh
@@ -60,15 +60,15 @@ chmod 0755 "$mountPoint/dev" "$mountPoint/sys"
mount --rbind /dev "$mountPoint/dev"
mount --rbind /sys "$mountPoint/sys"
-# If silent, write both stdout and stderr of activation script to /dev/null
-# otherwise, write both streams to stderr of this process
-if [ "$silent" -eq 0 ]; then
- PIPE_TARGET="/dev/stderr"
-else
- PIPE_TARGET="/dev/null"
-fi
+(
+ # If silent, write both stdout and stderr of activation script to /dev/null
+ # otherwise, write both streams to stderr of this process
+ if [ "$silent" -eq 1 ]; then
+ exec 2>/dev/null
+ fi
-# Run the activation script. Set $LOCALE_ARCHIVE to supress some Perl locale warnings.
-LOCALE_ARCHIVE="$system/sw/lib/locale/locale-archive" chroot "$mountPoint" "$system/activate" >>$PIPE_TARGET 2>&1 || true
+ # Run the activation script. Set $LOCALE_ARCHIVE to supress some Perl locale warnings.
+ LOCALE_ARCHIVE="$system/sw/lib/locale/locale-archive" chroot "$mountPoint" "$system/activate" 1>&2 || true
+)
exec chroot "$mountPoint" "${command[@]}"
diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-option/nixos-option.cc b/nixpkgs/nixos/modules/installer/tools/nixos-option/nixos-option.cc
index 9b92dc829cd..1a7b07a74f8 100644
--- a/nixpkgs/nixos/modules/installer/tools/nixos-option/nixos-option.cc
+++ b/nixpkgs/nixos/modules/installer/tools/nixos-option/nixos-option.cc
@@ -131,12 +131,12 @@ bool isOption(Context & ctx, const Value & v)
if (v.type != tAttrs) {
return false;
}
- const auto & atualType = v.attrs->find(ctx.underscoreType);
- if (atualType == v.attrs->end()) {
+ const auto & actualType = v.attrs->find(ctx.underscoreType);
+ if (actualType == v.attrs->end()) {
return false;
}
try {
- Value evaluatedType = evaluateValue(ctx, *atualType->value);
+ Value evaluatedType = evaluateValue(ctx, *actualType->value);
if (evaluatedType.type != tString) {
return false;
}
@@ -197,9 +197,107 @@ void recurse(const std::function<bool(const std::string & path, std::variant<Val
}
}
-// Calls f on all the option names
-void mapOptions(const std::function<void(const std::string & path)> & f, Context & ctx, Value root)
+bool optionTypeIs(Context & ctx, Value & v, const std::string & soughtType)
{
+ try {
+ const auto & typeLookup = v.attrs->find(ctx.state.sType);
+ if (typeLookup == v.attrs->end()) {
+ return false;
+ }
+ Value type = evaluateValue(ctx, *typeLookup->value);
+ if (type.type != tAttrs) {
+ return false;
+ }
+ const auto & nameLookup = type.attrs->find(ctx.state.sName);
+ if (nameLookup == type.attrs->end()) {
+ return false;
+ }
+ Value name = evaluateValue(ctx, *nameLookup->value);
+ if (name.type != tString) {
+ return false;
+ }
+ return name.string.s == soughtType;
+ } catch (Error &) {
+ return false;
+ }
+}
+
+bool isAggregateOptionType(Context & ctx, Value & v)
+{
+ return optionTypeIs(ctx, v, "attrsOf") || optionTypeIs(ctx, v, "listOf") || optionTypeIs(ctx, v, "loaOf");
+}
+
+MakeError(OptionPathError, EvalError);
+
+Value getSubOptions(Context & ctx, Value & option)
+{
+ Value getSubOptions = evaluateValue(ctx, *findAlongAttrPath(ctx.state, "type.getSubOptions", ctx.autoArgs, option));
+ if (getSubOptions.type != tLambda) {
+ throw OptionPathError("Option's type.getSubOptions isn't a function");
+ }
+ Value emptyString{};
+ nix::mkString(emptyString, "");
+ Value v;
+ ctx.state.callFunction(getSubOptions, emptyString, v, nix::Pos{});
+ return v;
+}
+
+// Carefully walk an option path, looking for sub-options when a path walks past
+// an option value.
+struct FindAlongOptionPathRet
+{
+ Value option;
+ std::string path;
+};
+FindAlongOptionPathRet findAlongOptionPath(Context & ctx, const std::string & path)
+{
+ Strings tokens = parseAttrPath(path);
+ Value v = ctx.optionsRoot;
+ std::string processedPath;
+ for (auto i = tokens.begin(); i != tokens.end(); i++) {
+ const auto & attr = *i;
+ try {
+ bool lastAttribute = std::next(i) == tokens.end();
+ v = evaluateValue(ctx, v);
+ if (attr.empty()) {
+ throw OptionPathError("empty attribute name");
+ }
+ if (isOption(ctx, v) && optionTypeIs(ctx, v, "submodule")) {
+ v = getSubOptions(ctx, v);
+ }
+ if (isOption(ctx, v) && isAggregateOptionType(ctx, v)) {
+ auto subOptions = getSubOptions(ctx, v);
+ if (lastAttribute && subOptions.attrs->empty()) {
+ break;
+ }
+ v = subOptions;
+ // Note that we've consumed attr, but didn't actually use it. This is the path component that's looked
+ // up in the list or attribute set that doesn't name an option -- the "root" in "users.users.root.name".
+ } else if (v.type != tAttrs) {
+ throw OptionPathError("Value is %s while a set was expected", showType(v));
+ } else {
+ const auto & next = v.attrs->find(ctx.state.symbols.create(attr));
+ if (next == v.attrs->end()) {
+ throw OptionPathError("Attribute not found", attr, path);
+ }
+ v = *next->value;
+ }
+ processedPath = appendPath(processedPath, attr);
+ } catch (OptionPathError & e) {
+ throw OptionPathError("At '%s' in path '%s': %s", attr, path, e.msg());
+ }
+ }
+ return {v, processedPath};
+}
+
+// Calls f on all the option names at or below the option described by `path`.
+// Note that "the option described by `path`" is not trivial -- if path describes a value inside an aggregate
+// option (such as users.users.root), the *option* described by that path is one path component shorter
+// (eg: users.users), which results in f being called on sibling-paths (eg: users.users.nixbld1). If f
+// doesn't want these, it must do its own filtering.
+void mapOptions(const std::function<void(const std::string & path)> & f, Context & ctx, const std::string & path)
+{
+ auto root = findAlongOptionPath(ctx, path);
recurse(
[f, &ctx](const std::string & path, std::variant<Value, std::exception_ptr> v) {
bool isOpt = std::holds_alternative<std::exception_ptr>(v) || isOption(ctx, std::get<Value>(v));
@@ -208,7 +306,7 @@ void mapOptions(const std::function<void(const std::string & path)> & f, Context
}
return !isOpt;
},
- ctx, root, "");
+ ctx, root.option, root.path);
}
// Calls f on all the config values inside one option.
@@ -294,9 +392,11 @@ void printAttrs(Context & ctx, Out & out, Value & v, const std::string & path)
Out attrsOut(out, "{", "}", v.attrs->size());
for (const auto & a : v.attrs->lexicographicOrder()) {
std::string name = a->name;
- attrsOut << name << " = ";
- printValue(ctx, attrsOut, *a->value, appendPath(path, name));
- attrsOut << ";" << Out::sep;
+ if (!forbiddenRecursionName(name)) {
+ attrsOut << name << " = ";
+ printValue(ctx, attrsOut, *a->value, appendPath(path, name));
+ attrsOut << ";" << Out::sep;
+ }
}
}
@@ -380,17 +480,26 @@ void printConfigValue(Context & ctx, Out & out, const std::string & path, std::v
out << ";\n";
}
-void printAll(Context & ctx, Out & out)
+// Replace with std::starts_with when C++20 is available
+bool starts_with(const std::string & s, const std::string & prefix)
+{
+ return s.size() >= prefix.size() &&
+ std::equal(s.begin(), std::next(s.begin(), prefix.size()), prefix.begin(), prefix.end());
+}
+
+void printRecursive(Context & ctx, Out & out, const std::string & path)
{
mapOptions(
- [&ctx, &out](const std::string & optionPath) {
+ [&ctx, &out, &path](const std::string & optionPath) {
mapConfigValuesInOption(
- [&ctx, &out](const std::string & configPath, std::variant<Value, std::exception_ptr> v) {
- printConfigValue(ctx, out, configPath, v);
+ [&ctx, &out, &path](const std::string & configPath, std::variant<Value, std::exception_ptr> v) {
+ if (starts_with(configPath, path)) {
+ printConfigValue(ctx, out, configPath, v);
+ }
},
optionPath, ctx);
},
- ctx, ctx.optionsRoot);
+ ctx, path);
}
void printAttr(Context & ctx, Out & out, const std::string & path, Value & root)
@@ -450,95 +559,17 @@ void printListing(Out & out, Value & v)
}
}
-bool optionTypeIs(Context & ctx, Value & v, const std::string & soughtType)
-{
- try {
- const auto & typeLookup = v.attrs->find(ctx.state.sType);
- if (typeLookup == v.attrs->end()) {
- return false;
- }
- Value type = evaluateValue(ctx, *typeLookup->value);
- if (type.type != tAttrs) {
- return false;
- }
- const auto & nameLookup = type.attrs->find(ctx.state.sName);
- if (nameLookup == type.attrs->end()) {
- return false;
- }
- Value name = evaluateValue(ctx, *nameLookup->value);
- if (name.type != tString) {
- return false;
- }
- return name.string.s == soughtType;
- } catch (Error &) {
- return false;
- }
-}
-
-bool isAggregateOptionType(Context & ctx, Value & v)
-{
- return optionTypeIs(ctx, v, "attrsOf") || optionTypeIs(ctx, v, "listOf") || optionTypeIs(ctx, v, "loaOf");
-}
-
-MakeError(OptionPathError, EvalError);
-
-Value getSubOptions(Context & ctx, Value & option)
-{
- Value getSubOptions = evaluateValue(ctx, *findAlongAttrPath(ctx.state, "type.getSubOptions", ctx.autoArgs, option));
- if (getSubOptions.type != tLambda) {
- throw OptionPathError("Option's type.getSubOptions isn't a function");
- }
- Value emptyString{};
- nix::mkString(emptyString, "");
- Value v;
- ctx.state.callFunction(getSubOptions, emptyString, v, nix::Pos{});
- return v;
-}
-
-// Carefully walk an option path, looking for sub-options when a path walks past
-// an option value.
-Value findAlongOptionPath(Context & ctx, const std::string & path)
-{
- Strings tokens = parseAttrPath(path);
- Value v = ctx.optionsRoot;
- for (auto i = tokens.begin(); i != tokens.end(); i++) {
- const auto & attr = *i;
- try {
- bool lastAttribute = std::next(i) == tokens.end();
- v = evaluateValue(ctx, v);
- if (attr.empty()) {
- throw OptionPathError("empty attribute name");
- }
- if (isOption(ctx, v) && optionTypeIs(ctx, v, "submodule")) {
- v = getSubOptions(ctx, v);
- }
- if (isOption(ctx, v) && isAggregateOptionType(ctx, v) && !lastAttribute) {
- v = getSubOptions(ctx, v);
- // Note that we've consumed attr, but didn't actually use it. This is the path component that's looked
- // up in the list or attribute set that doesn't name an option -- the "root" in "users.users.root.name".
- } else if (v.type != tAttrs) {
- throw OptionPathError("Value is %s while a set was expected", showType(v));
- } else {
- const auto & next = v.attrs->find(ctx.state.symbols.create(attr));
- if (next == v.attrs->end()) {
- throw OptionPathError("Attribute not found", attr, path);
- }
- v = *next->value;
- }
- } catch (OptionPathError & e) {
- throw OptionPathError("At '%s' in path '%s': %s", attr, path, e.msg());
- }
- }
- return v;
-}
-
void printOne(Context & ctx, Out & out, const std::string & path)
{
try {
- Value option = findAlongOptionPath(ctx, path);
+ auto result = findAlongOptionPath(ctx, path);
+ Value & option = result.option;
option = evaluateValue(ctx, option);
+ if (path != result.path) {
+ out << "Note: showing " << result.path << " instead of " << path << "\n";
+ }
if (isOption(ctx, option)) {
- printOption(ctx, out, path, option);
+ printOption(ctx, out, result.path, option);
} else {
printListing(out, option);
}
@@ -552,7 +583,7 @@ void printOne(Context & ctx, Out & out, const std::string & path)
int main(int argc, char ** argv)
{
- bool all = false;
+ bool recursive = false;
std::string path = ".";
std::string optionsExpr = "(import <nixpkgs/nixos> {}).options";
std::string configExpr = "(import <nixpkgs/nixos> {}).config";
@@ -568,8 +599,8 @@ int main(int argc, char ** argv)
nix::showManPage("nixos-option");
} else if (*arg == "--version") {
nix::printVersion("nixos-option");
- } else if (*arg == "--all") {
- all = true;
+ } else if (*arg == "-r" || *arg == "--recursive") {
+ recursive = true;
} else if (*arg == "--path") {
path = nix::getArg(*arg, arg, end);
} else if (*arg == "--options_expr") {
@@ -598,18 +629,12 @@ int main(int argc, char ** argv)
Context ctx{*state, *myArgs.getAutoArgs(*state), optionsRoot, configRoot};
Out out(std::cout);
- if (all) {
- if (!args.empty()) {
- throw UsageError("--all cannot be used with arguments");
- }
- printAll(ctx, out);
- } else {
- if (args.empty()) {
- printOne(ctx, out, "");
- }
- for (const auto & arg : args) {
- printOne(ctx, out, arg);
- }
+ auto print = recursive ? printRecursive : printOne;
+ if (args.empty()) {
+ print(ctx, out, "");
+ }
+ for (const auto & arg : args) {
+ print(ctx, out, arg);
}
ctx.state.printStats();
diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-rebuild.sh b/nixpkgs/nixos/modules/installer/tools/nixos-rebuild.sh
index 61b4af11027..354274478a3 100644
--- a/nixpkgs/nixos/modules/installer/tools/nixos-rebuild.sh
+++ b/nixpkgs/nixos/modules/installer/tools/nixos-rebuild.sh
@@ -3,6 +3,9 @@
if [ -x "@shell@" ]; then export SHELL="@shell@"; fi;
set -e
+set -o pipefail
+
+export PATH=@path@:$PATH
showSyntax() {
exec man nixos-rebuild
@@ -13,6 +16,7 @@ showSyntax() {
# Parse the command line.
origArgs=("$@")
extraBuildFlags=()
+lockFlags=()
action=
buildNix=1
fast=
@@ -58,7 +62,7 @@ while [ "$#" -gt 0 ]; do
j="$1"; shift 1
extraBuildFlags+=("$i" "$j")
;;
- --show-trace|--keep-failed|-K|--keep-going|-k|--verbose|-v|-vv|-vvv|-vvvv|-vvvvv|--fallback|--repair|--no-build-output|-Q|-j*)
+ --show-trace|--keep-failed|-K|--keep-going|-k|--verbose|-v|-vv|-vvv|-vvvv|-vvvvv|--fallback|--repair|--no-build-output|-Q|-j*|-L|--refresh|--no-net)
extraBuildFlags+=("$i")
;;
--option)
@@ -91,10 +95,24 @@ while [ "$#" -gt 0 ]; do
shift 1
;;
--use-remote-sudo)
- # note the trailing space
maybeSudo=(sudo --)
+ ;;
+ --flake)
+ flake="$1"
shift 1
;;
+ --recreate-lock-file|--no-update-lock-file|--no-write-lock-file|--no-registries|--commit-lock-file)
+ lockFlags+=("$i")
+ ;;
+ --update-input)
+ j="$1"; shift 1
+ lockFlags+=("$i" "$j")
+ ;;
+ --override-input)
+ j="$1"; shift 1
+ k="$1"; shift 1
+ lockFlags+=("$i" "$j" "$k")
+ ;;
*)
echo "$0: unknown option \`$i'"
exit 1
@@ -204,7 +222,7 @@ fi
# If ‘--upgrade’ is given, run ‘nix-channel --update nixos’.
-if [ -n "$upgrade" -a -z "$_NIXOS_REBUILD_REEXEC" ]; then
+if [[ -n $upgrade && -z $_NIXOS_REBUILD_REEXEC && -z $flake ]]; then
nix-channel --update nixos
# If there are other channels that contain a file called
@@ -227,8 +245,15 @@ if [ -z "$_NIXOS_REBUILD_REEXEC" ]; then
export PATH=@nix@/bin:$PATH
fi
+# Use /etc/nixos/flake.nix if it exists. It can be a symlink to the
+# actual flake.
+if [[ -z $flake && -e /etc/nixos/flake.nix ]]; then
+ flake="$(dirname "$(readlink -f /etc/nixos/flake.nix)")"
+fi
+
# Re-execute nixos-rebuild from the Nixpkgs tree.
-if [ -z "$_NIXOS_REBUILD_REEXEC" -a -n "$canRun" -a -z "$fast" ]; then
+# FIXME: get nixos-rebuild from $flake.
+if [[ -z $_NIXOS_REBUILD_REEXEC && -n $canRun && -z $fast && -z $flake ]]; then
if p=$(nix-build --no-out-link --expr 'with import <nixpkgs/nixos> {}; config.system.build.nixos-rebuild' "${extraBuildFlags[@]}"); then
export _NIXOS_REBUILD_REEXEC=1
exec $p/bin/nixos-rebuild "${origArgs[@]}"
@@ -236,10 +261,37 @@ if [ -z "$_NIXOS_REBUILD_REEXEC" -a -n "$canRun" -a -z "$fast" ]; then
fi
fi
+# For convenience, use the hostname as the default configuration to
+# build from the flake.
+if [[ -n $flake ]]; then
+ if [[ $flake =~ ^(.*)\#([^\#\"]*)$ ]]; then
+ flake="${BASH_REMATCH[1]}"
+ flakeAttr="${BASH_REMATCH[2]}"
+ fi
+ if [[ -z $flakeAttr ]]; then
+ read -r hostname < /proc/sys/kernel/hostname
+ if [[ -z $hostname ]]; then
+ hostname=default
+ fi
+ flakeAttr="nixosConfigurations.\"$hostname\""
+ else
+ flakeAttr="nixosConfigurations.\"$flakeAttr\""
+ fi
+fi
+
+# Resolve the flake.
+if [[ -n $flake ]]; then
+ flake=$(nix flake info --json "${extraBuildFlags[@]}" "${lockFlags[@]}" -- "$flake" | jq -r .url)
+fi
+
# Find configuration.nix and open editor instead of building.
if [ "$action" = edit ]; then
- NIXOS_CONFIG=${NIXOS_CONFIG:-$(nix-instantiate --find-file nixos-config)}
- exec "${EDITOR:-nano}" "$NIXOS_CONFIG"
+ if [[ -z $flake ]]; then
+ NIXOS_CONFIG=${NIXOS_CONFIG:-$(nix-instantiate --find-file nixos-config)}
+ exec "${EDITOR:-nano}" "$NIXOS_CONFIG"
+ else
+ exec nix edit "${lockFlags[@]}" -- "$flake#$flakeAttr"
+ fi
exit 1
fi
@@ -298,7 +350,7 @@ prebuiltNix() {
remotePATH=
-if [ -n "$buildNix" ]; then
+if [[ -n $buildNix && -z $flake ]]; then
echo "building Nix..." >&2
nixDrv=
if ! nixDrv="$(nix-instantiate '<nixpkgs/nixos>' --add-root $tmpDir/nix.drv --indirect -A config.nix.package.out "${extraBuildFlags[@]}")"; then
@@ -339,7 +391,7 @@ fi
# Update the version suffix if we're building from Git (so that
# nixos-version shows something useful).
-if [ -n "$canRun" ]; then
+if [[ -n $canRun && -z $flake ]]; then
if nixpkgs=$(nix-instantiate --find-file nixpkgs "${extraBuildFlags[@]}"); then
suffix=$($SHELL $nixpkgs/nixos/modules/installer/tools/get-version-suffix "${extraBuildFlags[@]}" || true)
if [ -n "$suffix" ]; then
@@ -360,15 +412,37 @@ fi
if [ -z "$rollback" ]; then
echo "building the system configuration..." >&2
if [ "$action" = switch -o "$action" = boot ]; then
- pathToConfig="$(nixBuild '<nixpkgs/nixos>' --no-out-link -A system "${extraBuildFlags[@]}")"
+ if [[ -z $flake ]]; then
+ pathToConfig="$(nixBuild '<nixpkgs/nixos>' --no-out-link -A system "${extraBuildFlags[@]}")"
+ else
+ outLink=$tmpDir/result
+ nix build "$flake#$flakeAttr.config.system.build.toplevel" \
+ "${extraBuildFlags[@]}" "${lockFlags[@]}" --out-link $outLink
+ pathToConfig="$(readlink -f $outLink)"
+ fi
copyToTarget "$pathToConfig"
targetHostCmd nix-env -p "$profile" --set "$pathToConfig"
elif [ "$action" = test -o "$action" = build -o "$action" = dry-build -o "$action" = dry-activate ]; then
- pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A system -k "${extraBuildFlags[@]}")"
+ if [[ -z $flake ]]; then
+ pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A system -k "${extraBuildFlags[@]}")"
+ else
+ nix build "$flake#$flakeAttr.config.system.build.toplevel" "${extraBuildFlags[@]}" "${lockFlags[@]}"
+ pathToConfig="$(readlink -f ./result)"
+ fi
elif [ "$action" = build-vm ]; then
- pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A vm -k "${extraBuildFlags[@]}")"
+ if [[ -z $flake ]]; then
+ pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A vm -k "${extraBuildFlags[@]}")"
+ else
+ echo "$0: 'build-vm' is not supported with '--flake'" >&2
+ exit 1
+ fi
elif [ "$action" = build-vm-with-bootloader ]; then
- pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A vmWithBootLoader -k "${extraBuildFlags[@]}")"
+ if [[ -z $flake ]]; then
+ pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A vmWithBootLoader -k "${extraBuildFlags[@]}")"
+ else
+ echo "$0: 'build-vm-with-bootloader' is not supported with '--flake'" >&2
+ exit 1
+ fi
else
showSyntax
fi
diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-version.sh b/nixpkgs/nixos/modules/installer/tools/nixos-version.sh
index 190c49a33ec..fb0fe26116a 100644
--- a/nixpkgs/nixos/modules/installer/tools/nixos-version.sh
+++ b/nixpkgs/nixos/modules/installer/tools/nixos-version.sh
@@ -6,8 +6,17 @@ case "$1" in
exit 1
;;
--hash|--revision)
+ if ! [[ @revision@ =~ ^[0-9a-f]+$ ]]; then
+ echo "$0: Nixpkgs commit hash is unknown"
+ exit 1
+ fi
echo "@revision@"
;;
+ --json)
+ cat <<EOF
+@json@
+EOF
+ ;;
*)
echo "@version@ (@codeName@)"
;;
diff --git a/nixpkgs/nixos/modules/installer/tools/tools.nix b/nixpkgs/nixos/modules/installer/tools/tools.nix
index 5df9c23e6b6..833865e99bb 100644
--- a/nixpkgs/nixos/modules/installer/tools/tools.nix
+++ b/nixpkgs/nixos/modules/installer/tools/tools.nix
@@ -31,6 +31,7 @@ let
nix = config.nix.package.out;
nix_x86_64_linux = fallback.x86_64-linux;
nix_i686_linux = fallback.i686-linux;
+ path = makeBinPath [ pkgs.jq ];
};
nixos-generate-config = makeProg {
@@ -47,6 +48,14 @@ let
name = "nixos-version";
src = ./nixos-version.sh;
inherit (config.system.nixos) version codeName revision;
+ inherit (config.system) configurationRevision;
+ json = builtins.toJSON ({
+ nixosVersion = config.system.nixos.version;
+ } // optionalAttrs (config.system.nixos.revision != null) {
+ nixpkgsRevision = config.system.nixos.revision;
+ } // optionalAttrs (config.system.configurationRevision != null) {
+ configurationRevision = config.system.configurationRevision;
+ });
};
nixos-enter = makeProg {
diff --git a/nixpkgs/nixos/modules/misc/ids.nix b/nixpkgs/nixos/modules/misc/ids.nix
index bedd87a368e..85e5534e906 100644
--- a/nixpkgs/nixos/modules/misc/ids.nix
+++ b/nixpkgs/nixos/modules/misc/ids.nix
@@ -133,7 +133,7 @@ in
tcpcryptd = 93; # tcpcryptd uses a hard-coded uid. We patch it in Nixpkgs to match this choice.
firebird = 95;
#keys = 96; # unused
- #haproxy = 97; # DynamicUser as of 2019-11-08
+ #haproxy = 97; # dynamically allocated as of 2020-03-11
mongodb = 98;
openldap = 99;
#users = 100; # unused
@@ -299,7 +299,7 @@ in
couchpotato = 267;
gogs = 268;
pdns-recursor = 269;
- kresd = 270;
+ #kresd = 270; # switched to "knot-resolver" with dynamic ID
rpc = 271;
geoip = 272;
fcron = 273;
@@ -448,7 +448,7 @@ in
#tcpcryptd = 93; # unused
firebird = 95;
keys = 96;
- #haproxy = 97; # DynamicUser as of 2019-11-08
+ #haproxy = 97; # dynamically allocated as of 2020-03-11
#mongodb = 98; # unused
openldap = 99;
munin = 102;
@@ -600,7 +600,7 @@ in
headphones = 266;
couchpotato = 267;
gogs = 268;
- kresd = 270;
+ #kresd = 270; # switched to "knot-resolver" with dynamic ID
#rpc = 271; # unused
#geoip = 272; # unused
fcron = 273;
diff --git a/nixpkgs/nixos/modules/misc/locate.nix b/nixpkgs/nixos/modules/misc/locate.nix
index 552535c253e..dc668796c78 100644
--- a/nixpkgs/nixos/modules/misc/locate.nix
+++ b/nixpkgs/nixos/modules/misc/locate.nix
@@ -131,13 +131,6 @@ in {
++ optional (isFindutils && cfg.pruneNames != []) "findutils locate does not support pruning by directory component"
++ optional (isFindutils && cfg.pruneBindMounts) "findutils locate does not support skipping bind mounts";
- # directory creation needs to be separated from main service
- # because ReadWritePaths fails when the directory doesn't already exist
- systemd.tmpfiles.rules =
- let dir = dirOf cfg.output; in
- mkIf (dir != "/var/cache")
- [ "d ${dir} 0755 root root -" ];
-
systemd.services.update-locatedb =
{ description = "Update Locate Database";
path = mkIf (!isMLocate) [ pkgs.su ];
diff --git a/nixpkgs/nixos/modules/misc/nixpkgs.nix b/nixpkgs/nixos/modules/misc/nixpkgs.nix
index afb74581e23..011d493c153 100644
--- a/nixpkgs/nixos/modules/misc/nixpkgs.nix
+++ b/nixpkgs/nixos/modules/misc/nixpkgs.nix
@@ -216,6 +216,14 @@ in
Ignored when <code>nixpkgs.pkgs</code> is set.
'';
};
+
+ initialSystem = mkOption {
+ type = types.str;
+ internal = true;
+ description = ''
+ Preserved value of <literal>system</literal> passed to <literal>eval-config.nix</literal>.
+ '';
+ };
};
config = {
diff --git a/nixpkgs/nixos/modules/misc/version.nix b/nixpkgs/nixos/modules/misc/version.nix
index 8a85035ceb7..9557def622d 100644
--- a/nixpkgs/nixos/modules/misc/version.nix
+++ b/nixpkgs/nixos/modules/misc/version.nix
@@ -4,10 +4,6 @@ with lib;
let
cfg = config.system.nixos;
-
- gitRepo = "${toString pkgs.path}/.git";
- gitRepoValid = lib.pathIsGitRepo gitRepo;
- gitCommitId = lib.substring 0 7 (commitIdFromGitRepo gitRepo);
in
{
@@ -42,8 +38,8 @@ in
nixos.revision = mkOption {
internal = true;
- type = types.str;
- default = trivial.revisionWithDefault "master";
+ type = types.nullOr types.str;
+ default = trivial.revisionWithDefault null;
description = "The Git revision from which this NixOS configuration was built.";
};
@@ -84,6 +80,12 @@ in
description = "Default NixOS channel to which the root user is subscribed.";
};
+ configurationRevision = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description = "The Git revision of the top-level flake from which this configuration was built.";
+ };
+
};
config = {
@@ -92,8 +94,6 @@ in
# These defaults are set here rather than up there so that
# changing them would not rebuild the manual
version = mkDefault (cfg.release + cfg.versionSuffix);
- revision = mkIf gitRepoValid (mkDefault gitCommitId);
- versionSuffix = mkIf gitRepoValid (mkDefault (".git." + gitCommitId));
};
# Generate /etc/os-release. See
diff --git a/nixpkgs/nixos/modules/module-list.nix b/nixpkgs/nixos/modules/module-list.nix
index 29dbc39ac7e..60aa10f03a3 100644
--- a/nixpkgs/nixos/modules/module-list.nix
+++ b/nixpkgs/nixos/modules/module-list.nix
@@ -41,7 +41,6 @@
./hardware/acpilight.nix
./hardware/all-firmware.nix
./hardware/bladeRF.nix
- ./hardware/brightnessctl.nix
./hardware/brillo.nix
./hardware/ckb-next.nix
./hardware/cpu/amd-microcode.nix
@@ -98,6 +97,7 @@
./programs/autojump.nix
./programs/bandwhich.nix
./programs/bash/bash.nix
+ ./programs/bash-my-aws.nix
./programs/bcc.nix
./programs/browserpass.nix
./programs/captive-browser.nix
@@ -200,6 +200,7 @@
./security/wrappers/default.nix
./security/sudo.nix
./security/systemd-confinement.nix
+ ./security/tpm2.nix
./services/admin/oxidized.nix
./services/admin/salt/master.nix
./services/admin/salt/minion.nix
@@ -228,6 +229,8 @@
./services/backup/restic.nix
./services/backup/restic-rest-server.nix
./services/backup/rsnapshot.nix
+ ./services/backup/sanoid.nix
+ ./services/backup/syncoid.nix
./services/backup/tarsnap.nix
./services/backup/tsm.nix
./services/backup/zfs-replication.nix
@@ -245,12 +248,13 @@
./services/cluster/kubernetes/proxy.nix
./services/cluster/kubernetes/scheduler.nix
./services/computing/boinc/client.nix
- ./services/computing/torque/server.nix
- ./services/computing/torque/mom.nix
+ ./services/computing/foldingathome/client.nix
./services/computing/slurm/slurm.nix
+ ./services/computing/torque/mom.nix
+ ./services/computing/torque/server.nix
./services/continuous-integration/buildbot/master.nix
./services/continuous-integration/buildbot/worker.nix
- ./services/continuous-integration/buildkite-agent.nix
+ ./services/continuous-integration/buildkite-agents.nix
./services/continuous-integration/hail.nix
./services/continuous-integration/hydra/default.nix
./services/continuous-integration/gitlab-runner.nix
@@ -295,6 +299,7 @@
./services/desktops/geoclue2.nix
./services/desktops/gsignond.nix
./services/desktops/gvfs.nix
+ ./services/desktops/malcontent.nix
./services/desktops/pipewire.nix
./services/desktops/gnome3/at-spi2-core.nix
./services/desktops/gnome3/chrome-gnome-shell.nix
@@ -400,8 +405,10 @@
./services/mail/rspamd.nix
./services/mail/rss2email.nix
./services/mail/roundcube.nix
+ ./services/mail/sympa.nix
./services/mail/nullmailer.nix
./services/misc/airsonic.nix
+ ./services/misc/ankisyncd.nix
./services/misc/apache-kafka.nix
./services/misc/autofs.nix
./services/misc/autorandr.nix
@@ -427,7 +434,6 @@
./services/misc/ethminer.nix
./services/misc/exhibitor.nix
./services/misc/felix.nix
- ./services/misc/folding-at-home.nix
./services/misc/freeswitch.nix
./services/misc/fstrim.nix
./services/misc/gammu-smsd.nix
@@ -529,6 +535,7 @@
./services/monitoring/prometheus/alertmanager.nix
./services/monitoring/prometheus/exporters.nix
./services/monitoring/prometheus/pushgateway.nix
+ ./services/monitoring/prometheus/xmpp-alerts.nix
./services/monitoring/riemann.nix
./services/monitoring/riemann-dash.nix
./services/monitoring/riemann-tools.nix
@@ -590,7 +597,7 @@
./services/networking/dhcpd.nix
./services/networking/dnscache.nix
./services/networking/dnschain.nix
- ./services/networking/dnscrypt-proxy.nix
+ ./services/networking/dnscrypt-proxy2.nix
./services/networking/dnscrypt-wrapper.nix
./services/networking/dnsdist.nix
./services/networking/dnsmasq.nix
@@ -657,6 +664,7 @@
./services/networking/ngircd.nix
./services/networking/nghttpx/default.nix
./services/networking/nix-serve.nix
+ ./services/networking/nix-store-gcs-proxy.nix
./services/networking/nixops-dns.nix
./services/networking/nntp-proxy.nix
./services/networking/nsd.nix
@@ -703,6 +711,7 @@
./services/networking/shorewall6.nix
./services/networking/shout.nix
./services/networking/sniproxy.nix
+ ./services/networking/smartdns.nix
./services/networking/smokeping.nix
./services/networking/softether.nix
./services/networking/spacecookie.nix
@@ -720,6 +729,7 @@
./services/networking/syncthing.nix
./services/networking/syncthing-relay.nix
./services/networking/syncplay.nix
+ ./services/networking/tailscale.nix
./services/networking/tcpcrypt.nix
./services/networking/teamspeak3.nix
./services/networking/tedicross.nix
@@ -804,6 +814,7 @@
./services/ttys/agetty.nix
./services/ttys/gpm.nix
./services/ttys/kmscon.nix
+ ./services/wayland/cage.nix
./services/web-apps/atlassian/confluence.nix
./services/web-apps/atlassian/crowd.nix
./services/web-apps/atlassian/jira.nix
@@ -813,9 +824,11 @@
./services/web-apps/dokuwiki.nix
./services/web-apps/frab.nix
./services/web-apps/gotify-server.nix
+ ./services/web-apps/grocy.nix
./services/web-apps/icingaweb2/icingaweb2.nix
./services/web-apps/icingaweb2/module-monitoring.nix
./services/web-apps/ihatemoney
+ ./services/web-apps/jirafeau.nix
./services/web-apps/limesurvey.nix
./services/web-apps/mattermost.nix
./services/web-apps/mediawiki.nix
diff --git a/nixpkgs/nixos/modules/programs/bash-my-aws.nix b/nixpkgs/nixos/modules/programs/bash-my-aws.nix
new file mode 100644
index 00000000000..15e429a7549
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/bash-my-aws.nix
@@ -0,0 +1,25 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+ prg = config.programs;
+ cfg = prg.bash-my-aws;
+
+ initScript = ''
+ eval $(${pkgs.bash-my-aws}/bin/bma-init)
+ '';
+in
+ {
+ options = {
+ programs.bash-my-aws = {
+ enable = mkEnableOption "bash-my-aws";
+ };
+ };
+
+ config = mkIf cfg.enable {
+ environment.systemPackages = with pkgs; [ bash-my-aws ];
+
+ programs.bash.interactiveShellInit = initScript;
+ };
+ }
diff --git a/nixpkgs/nixos/modules/programs/bash/bash.nix b/nixpkgs/nixos/modules/programs/bash/bash.nix
index 366c07c0a35..be964ce7f3f 100644
--- a/nixpkgs/nixos/modules/programs/bash/bash.nix
+++ b/nixpkgs/nixos/modules/programs/bash/bash.nix
@@ -32,6 +32,10 @@ let
fi
'';
+ lsColors = optionalString cfg.enableLsColors ''
+ eval "$(${pkgs.coreutils}/bin/dircolors -b)"
+ '';
+
bashAliases = concatStringsSep "\n" (
mapAttrsFlatten (k: v: "alias ${k}=${escapeShellArg v}")
(filterAttrs (k: v: v != null) cfg.shellAliases)
@@ -127,6 +131,14 @@ in
type = types.bool;
};
+ enableLsColors = mkOption {
+ default = true;
+ description = ''
+ Enable extra colors in directory listings.
+ '';
+ type = types.bool;
+ };
+
};
};
@@ -156,6 +168,7 @@ in
${cfg.promptInit}
${bashCompletion}
+ ${lsColors}
${bashAliases}
${cfge.interactiveShellInit}
diff --git a/nixpkgs/nixos/modules/programs/firejail.nix b/nixpkgs/nixos/modules/programs/firejail.nix
index 74c3e4425a7..484f9eb4440 100644
--- a/nixpkgs/nixos/modules/programs/firejail.nix
+++ b/nixpkgs/nixos/modules/programs/firejail.nix
@@ -5,28 +5,34 @@ with lib;
let
cfg = config.programs.firejail;
- wrappedBins = pkgs.stdenv.mkDerivation {
- name = "firejail-wrapped-binaries";
- nativeBuildInputs = with pkgs; [ makeWrapper ];
- buildCommand = ''
+ wrappedBins = pkgs.runCommand "firejail-wrapped-binaries"
+ { preferLocalBuild = true;
+ allowSubstitutes = false;
+ }
+ ''
mkdir -p $out/bin
${lib.concatStringsSep "\n" (lib.mapAttrsToList (command: binary: ''
- cat <<_EOF >$out/bin/${command}
- #!${pkgs.stdenv.shell} -e
- /run/wrappers/bin/firejail ${binary} "\$@"
- _EOF
- chmod 0755 $out/bin/${command}
+ cat <<_EOF >$out/bin/${command}
+ #! ${pkgs.runtimeShell} -e
+ exec /run/wrappers/bin/firejail ${binary} "\$@"
+ _EOF
+ chmod 0755 $out/bin/${command}
'') cfg.wrappedBinaries)}
'';
- };
in {
options.programs.firejail = {
enable = mkEnableOption "firejail";
wrappedBinaries = mkOption {
- type = types.attrs;
+ type = types.attrsOf types.path;
default = {};
+ example = literalExample ''
+ {
+ firefox = "''${lib.getBin pkgs.firefox}/bin/firefox";
+ mpv = "''${lib.getBin pkgs.mpv}/bin/mpv";
+ }
+ '';
description = ''
Wrap the binaries in firejail and place them in the global path.
</para>
@@ -41,7 +47,7 @@ in {
config = mkIf cfg.enable {
security.wrappers.firejail.source = "${lib.getBin pkgs.firejail}/bin/firejail";
- environment.systemPackages = [ wrappedBins ];
+ environment.systemPackages = [ pkgs.firejail ] ++ [ wrappedBins ];
};
meta.maintainers = with maintainers; [ peterhoeg ];
diff --git a/nixpkgs/nixos/modules/programs/fish_completion-generator.patch b/nixpkgs/nixos/modules/programs/fish_completion-generator.patch
index a8c797d185a..997f38c5066 100644
--- a/nixpkgs/nixos/modules/programs/fish_completion-generator.patch
+++ b/nixpkgs/nixos/modules/programs/fish_completion-generator.patch
@@ -1,11 +1,13 @@
--- a/create_manpage_completions.py
+++ b/create_manpage_completions.py
-@@ -776,8 +776,6 @@ def parse_manpage_at_path(manpage_path, output_directory):
-
+@@ -844,10 +844,6 @@ def parse_manpage_at_path(manpage_path, output_directory):
+
built_command_output.insert(0, "# " + CMDNAME)
-
+
- # Output the magic word Autogenerated so we can tell if we can overwrite this
-- built_command_output.insert(1, "# Autogenerated from man page " + manpage_path)
+- built_command_output.insert(
+- 1, "# Autogenerated from man page " + manpage_path
+- )
# built_command_output.insert(2, "# using " + parser.__class__.__name__) # XXX MISATTRIBUTES THE CULPABILE PARSER! Was really using Type2 but reporting TypeDeroffManParser
-
+
for line in built_command_output:
diff --git a/nixpkgs/nixos/modules/programs/sway.nix b/nixpkgs/nixos/modules/programs/sway.nix
index 7e646f8737d..364debddb0f 100644
--- a/nixpkgs/nixos/modules/programs/sway.nix
+++ b/nixpkgs/nixos/modules/programs/sway.nix
@@ -88,10 +88,10 @@ in {
default = with pkgs; [
swaylock swayidle
xwayland alacritty dmenu
- rxvt_unicode # For backward compatibility (old default terminal)
+ rxvt-unicode # For backward compatibility (old default terminal)
];
defaultText = literalExample ''
- with pkgs; [ swaylock swayidle xwayland rxvt_unicode dmenu ];
+ with pkgs; [ swaylock swayidle xwayland rxvt-unicode dmenu ];
'';
example = literalExample ''
with pkgs; [
diff --git a/nixpkgs/nixos/modules/programs/tmux.nix b/nixpkgs/nixos/modules/programs/tmux.nix
index ed077e3daa7..c39908751d2 100644
--- a/nixpkgs/nixos/modules/programs/tmux.nix
+++ b/nixpkgs/nixos/modules/programs/tmux.nix
@@ -52,7 +52,7 @@ let
set -s escape-time ${toString cfg.escapeTime}
set -g history-limit ${toString cfg.historyLimit}
- ${cfg.extraTmuxConf}
+ ${cfg.extraConfig}
'';
in {
@@ -102,7 +102,7 @@ in {
description = "Time in milliseconds for which tmux waits after an escape is input.";
};
- extraTmuxConf = mkOption {
+ extraConfig = mkOption {
default = "";
description = ''
Additional contents of /etc/tmux.conf
@@ -181,4 +181,8 @@ in {
};
};
};
+
+ imports = [
+ (lib.mkRenamedOptionModule [ "programs" "tmux" "extraTmuxConf" ] [ "programs" "tmux" "extraConfig" ])
+ ];
}
diff --git a/nixpkgs/nixos/modules/programs/zsh/zsh.nix b/nixpkgs/nixos/modules/programs/zsh/zsh.nix
index c66c29ed45f..930cc1987a3 100644
--- a/nixpkgs/nixos/modules/programs/zsh/zsh.nix
+++ b/nixpkgs/nixos/modules/programs/zsh/zsh.nix
@@ -15,6 +15,24 @@ let
(filterAttrs (k: v: v != null) cfg.shellAliases)
);
+ zshStartupNotes = ''
+ # Note that generated /etc/zprofile and /etc/zshrc files do a lot of
+ # non-standard setup to make zsh usable with no configuration by default.
+ #
+ # Which means that unless you explicitly meticulously override everything
+ # generated, interactions between your ~/.zshrc and these files are likely
+ # to be rather surprising.
+ #
+ # Note however, that you can disable loading of the generated /etc/zprofile
+ # and /etc/zshrc (you can't disable loading of /etc/zshenv, but it is
+ # designed to not set anything surprising) by setting `no_global_rcs` option
+ # in ~/.zshenv:
+ #
+ # echo setopt no_global_rcs >> ~/.zshenv
+ #
+ # See "STARTUP/SHUTDOWN FILES" section of zsh(1) for more info.
+ '';
+
in
{
@@ -69,6 +87,10 @@ in
promptInit = mkOption {
default = ''
+ # Note that to manually override this in ~/.zshrc you should run `prompt off`
+ # before setting your PS1 and etc. Otherwise this will likely to interact with
+ # your ~/.zshrc configuration in unexpected ways as the default prompt sets
+ # a lot of different prompt variables.
autoload -U promptinit && promptinit && prompt walters && setopt prompt_sp
'';
description = ''
@@ -100,7 +122,8 @@ in
];
example = [ "EXTENDED_HISTORY" "RM_STAR_WAIT" ];
description = ''
- Configure zsh options.
+ Configure zsh options. See
+ <citerefentry><refentrytitle>zshoptions</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
'';
};
@@ -139,14 +162,21 @@ in
# This file is read for all shells.
# Only execute this file once per shell.
- # But don't clobber the environment of interactive non-login children!
if [ -n "$__ETC_ZSHENV_SOURCED" ]; then return; fi
- export __ETC_ZSHENV_SOURCED=1
+ __ETC_ZSHENV_SOURCED=1
if [ -z "$__NIXOS_SET_ENVIRONMENT_DONE" ]; then
. ${config.system.build.setEnvironment}
fi
+ HELPDIR="${pkgs.zsh}/share/zsh/$ZSH_VERSION/help"
+
+ # Tell zsh how to find installed completions.
+ for p in ''${(z)NIX_PROFILES}; do
+ fpath+=($p/share/zsh/site-functions $p/share/zsh/$ZSH_VERSION/functions $p/share/zsh/vendor-completions)
+ done
+
+ # Setup custom shell init stuff.
${cfge.shellInit}
${cfg.shellInit}
@@ -161,11 +191,14 @@ in
''
# /etc/zprofile: DO NOT EDIT -- this file has been generated automatically.
# This file is read for login shells.
+ #
+ ${zshStartupNotes}
# Only execute this file once per shell.
if [ -n "$__ETC_ZPROFILE_SOURCED" ]; then return; fi
__ETC_ZPROFILE_SOURCED=1
+ # Setup custom login shell init stuff.
${cfge.loginShellInit}
${cfg.loginShellInit}
@@ -180,38 +213,44 @@ in
''
# /etc/zshrc: DO NOT EDIT -- this file has been generated automatically.
# This file is read for interactive shells.
+ #
+ ${zshStartupNotes}
# Only execute this file once per shell.
if [ -n "$__ETC_ZSHRC_SOURCED" -o -n "$NOSYSZSHRC" ]; then return; fi
__ETC_ZSHRC_SOURCED=1
- . /etc/zinputrc
+ ${optionalString (cfg.setOptions != []) ''
+ # Set zsh options.
+ setopt ${concatStringsSep " " cfg.setOptions}
+ ''}
- # Don't export these, otherwise other shells (bash) will try to use same histfile
+ # Setup command line history.
+ # Don't export these, otherwise other shells (bash) will try to use same HISTFILE.
SAVEHIST=${toString cfg.histSize}
HISTSIZE=${toString cfg.histSize}
HISTFILE=${cfg.histFile}
- HELPDIR="${pkgs.zsh}/share/zsh/$ZSH_VERSION/help"
-
- # Tell zsh how to find installed completions
- for p in ''${(z)NIX_PROFILES}; do
- fpath+=($p/share/zsh/site-functions $p/share/zsh/$ZSH_VERSION/functions $p/share/zsh/vendor-completions)
- done
+ # Configure sane keyboard defaults.
+ . /etc/zinputrc
- ${optionalString cfg.enableGlobalCompInit "autoload -U compinit && compinit"}
+ ${optionalString cfg.enableGlobalCompInit ''
+ # Enable autocompletion.
+ autoload -U compinit && compinit
+ ''}
+ # Setup custom interactive shell init stuff.
${cfge.interactiveShellInit}
${cfg.interactiveShellInit}
- ${optionalString (cfg.setOptions != []) "setopt ${concatStringsSep " " cfg.setOptions}"}
-
+ # Setup aliases.
${zshAliases}
+ # Setup prompt.
${cfg.promptInit}
- # Need to disable features to support TRAMP
+ # Disable some features to support TRAMP.
if [ "$TERM" = dumb ]; then
unsetopt zle prompt_cr prompt_subst
unset RPS1 RPROMPT
diff --git a/nixpkgs/nixos/modules/rename.nix b/nixpkgs/nixos/modules/rename.nix
index dbe687d8e22..410db8fd84e 100644
--- a/nixpkgs/nixos/modules/rename.nix
+++ b/nixpkgs/nixos/modules/rename.nix
@@ -21,12 +21,12 @@ with lib;
(mkRemovedOptionModule [ "services" "firefox" "syncserver" "group" ] "")
(mkRemovedOptionModule [ "services" "winstone" ] "The corresponding package was removed from nixpkgs.")
(mkRemovedOptionModule [ "networking" "vpnc" ] "Use environment.etc.\"vpnc/service.conf\" instead.")
- (mkRemovedOptionModule [ "environment.blcr.enable" ] "The BLCR module has been removed")
- (mkRemovedOptionModule [ "services.beegfsEnable" ] "The BeeGFS module has been removed")
- (mkRemovedOptionModule [ "services.beegfs" ] "The BeeGFS module has been removed")
- (mkRemovedOptionModule [ "services.osquery" ] "The osquery module has been removed")
- (mkRemovedOptionModule [ "services.fourStore" ] "The fourStore module has been removed")
- (mkRemovedOptionModule [ "services.fourStoreEndpoint" ] "The fourStoreEndpoint module has been removed")
+ (mkRemovedOptionModule [ "environment" "blcr" "enable" ] "The BLCR module has been removed")
+ (mkRemovedOptionModule [ "services" "beegfsEnable" ] "The BeeGFS module has been removed")
+ (mkRemovedOptionModule [ "services" "beegfs" ] "The BeeGFS module has been removed")
+ (mkRemovedOptionModule [ "services" "osquery" ] "The osquery module has been removed")
+ (mkRemovedOptionModule [ "services" "fourStore" ] "The fourStore module has been removed")
+ (mkRemovedOptionModule [ "services" "fourStoreEndpoint" ] "The fourStoreEndpoint module has been removed")
(mkRemovedOptionModule [ "programs" "way-cooler" ] ("way-cooler is abandoned by its author: " +
"https://way-cooler.org/blog/2020/01/09/way-cooler-post-mortem.html"))
(mkRemovedOptionModule [ "services" "xserver" "multitouch" ] ''
@@ -41,6 +41,13 @@ with lib;
LightDM. Please use the services.xserver.displayManager.lightdm.autoLogin options
instead, or any other display manager in NixOS as they all support auto-login.
'')
+ (mkRemovedOptionModule [ "services" "dnscrypt-proxy" ] "Use services.dnscrypt-proxy2 instead")
+ (mkRemovedOptionModule ["hardware" "brightnessctl" ] ''
+ The brightnessctl module was removed because newer versions of
+ brightnessctl don't require the udev rules anymore (they can use the
+ systemd-logind API). Instead of using the module you can now
+ simply add the brightnessctl package to environment.systemPackages.
+ '')
# Do NOT add any option renames here, see top of the file
];
diff --git a/nixpkgs/nixos/modules/security/acme.nix b/nixpkgs/nixos/modules/security/acme.nix
index 890c421b0ea..b787a767539 100644
--- a/nixpkgs/nixos/modules/security/acme.nix
+++ b/nixpkgs/nixos/modules/security/acme.nix
@@ -1,7 +1,5 @@
{ config, lib, pkgs, ... }:
-
with lib;
-
let
cfg = config.security.acme;
@@ -9,7 +7,8 @@ let
certOpts = { name, ... }: {
options = {
webroot = mkOption {
- type = types.str;
+ type = types.nullOr types.str;
+ default = null;
example = "/var/lib/acme/acme-challenges";
description = ''
Where the webroot of the HTTP vhost is located.
@@ -38,7 +37,7 @@ let
email = mkOption {
type = types.nullOr types.str;
- default = null;
+ default = cfg.email;
description = "Contact email address for the CA to be able to reach you.";
};
@@ -76,20 +75,6 @@ let
'';
};
- plugins = mkOption {
- type = types.listOf (types.enum [
- "cert.der" "cert.pem" "chain.pem" "external.sh"
- "fullchain.pem" "full.pem" "key.der" "key.pem" "account_key.json" "account_reg.json"
- ]);
- default = [ "fullchain.pem" "full.pem" "key.pem" "account_key.json" "account_reg.json" ];
- description = ''
- Plugins to enable. With default settings simp_le will
- store public certificate bundle in <filename>fullchain.pem</filename>,
- private key in <filename>key.pem</filename> and those two previous
- files combined in <filename>full.pem</filename> in its state directory.
- '';
- };
-
directory = mkOption {
type = types.str;
readOnly = true;
@@ -111,6 +96,67 @@ let
own server roots if needed.
'';
};
+
+ keyType = mkOption {
+ type = types.str;
+ default = "ec384";
+ description = ''
+ Key type to use for private keys.
+ For an up to date list of supported values check the --key-type option
+ at https://go-acme.github.io/lego/usage/cli/#usage.
+ '';
+ };
+
+ dnsProvider = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "route53";
+ description = ''
+ DNS Challenge provider. For a list of supported providers, see the "code"
+ field of the DNS providers listed at https://go-acme.github.io/lego/dns/.
+ '';
+ };
+
+ credentialsFile = mkOption {
+ type = types.path;
+ description = ''
+ Path to an EnvironmentFile for the cert's service containing any required and
+ optional environment variables for your selected dnsProvider.
+ To find out what values you need to set, consult the documentation at
+ https://go-acme.github.io/lego/dns/ for the corresponding dnsProvider.
+ '';
+ example = "/var/src/secrets/example.org-route53-api-token";
+ };
+
+ dnsPropagationCheck = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Toggles lego DNS propagation check, which is used alongside DNS-01
+ challenge to ensure the DNS entries required are available.
+ '';
+ };
+
+ ocspMustStaple = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Turns on the OCSP Must-Staple TLS extension.
+ Make sure you know what you're doing! See:
+ <itemizedlist>
+ <listitem><para><link xlink:href="https://blog.apnic.net/2019/01/15/is-the-web-ready-for-ocsp-must-staple/" /></para></listitem>
+ <listitem><para><link xlink:href="https://blog.hboeck.de/archives/886-The-Problem-with-OCSP-Stapling-and-Must-Staple-and-why-Certificate-Revocation-is-still-broken.html" /></para></listitem>
+ </itemizedlist>
+ '';
+ };
+
+ extraLegoRenewFlags = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ description = ''
+ Additional flags to pass to lego renew.
+ '';
+ };
};
};
@@ -130,19 +176,26 @@ in
(mkRemovedOptionModule [ "security" "acme" "directory"] "ACME Directory is now hardcoded to /var/lib/acme and its permisisons are managed by systemd. See https://github.com/NixOS/nixpkgs/issues/53852 for more info.")
(mkRemovedOptionModule [ "security" "acme" "preDelay"] "This option has been removed. If you want to make sure that something executes before certificates are provisioned, add a RequiredBy=acme-\${cert}.service to the service you want to execute before the cert renewal")
(mkRemovedOptionModule [ "security" "acme" "activationDelay"] "This option has been removed. If you want to make sure that something executes before certificates are provisioned, add a RequiredBy=acme-\${cert}.service to the service you want to execute before the cert renewal")
+ (mkChangedOptionModule [ "security" "acme" "validMin"] [ "security" "acme" "validMinDays"] (config: config.security.acme.validMin / (24 * 3600)))
];
options = {
security.acme = {
- validMin = mkOption {
+ validMinDays = mkOption {
type = types.int;
- default = 30 * 24 * 3600;
- description = "Minimum remaining validity before renewal in seconds.";
+ default = 30;
+ description = "Minimum remaining validity before renewal in days.";
+ };
+
+ email = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description = "Contact email address for the CA to be able to reach you.";
};
renewInterval = mkOption {
type = types.str;
- default = "weekly";
+ default = "daily";
description = ''
Systemd calendar expression when to check for renewal. See
<citerefentry><refentrytitle>systemd.time</refentrytitle>
@@ -173,6 +226,15 @@ in
'';
};
+ acceptTerms = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Accept the CA's terms of service. The default provier is Let's Encrypt,
+ you can find their ToS at https://letsencrypt.org/repository/
+ '';
+ };
+
certs = mkOption {
default = { };
type = with types; attrsOf (submodule certOpts);
@@ -204,27 +266,59 @@ in
config = mkMerge [
(mkIf (cfg.certs != { }) {
+ assertions = let
+ certs = (mapAttrsToList (k: v: v) cfg.certs);
+ in [
+ {
+ assertion = all (certOpts: certOpts.dnsProvider == null || certOpts.webroot == null) certs;
+ message = ''
+ Options `security.acme.certs.<name>.dnsProvider` and
+ `security.acme.certs.<name>.webroot` are mutually exclusive.
+ '';
+ }
+ {
+ assertion = cfg.email != null || all (certOpts: certOpts.email != null) certs;
+ message = ''
+ You must define `security.acme.certs.<name>.email` or
+ `security.acme.email` to register with the CA.
+ '';
+ }
+ {
+ assertion = cfg.acceptTerms;
+ message = ''
+ You must accept the CA's terms of service before using
+ the ACME module by setting `security.acme.acceptTerms`
+ to `true`. For Let's Encrypt's ToS see https://letsencrypt.org/repository/
+ '';
+ }
+ ];
+
systemd.services = let
services = concatLists servicesLists;
servicesLists = mapAttrsToList certToServices cfg.certs;
certToServices = cert: data:
let
+ # StateDirectory must be relative, and will be created under /var/lib by systemd
lpath = "acme/${cert}";
- rights = if data.allowKeysForGroup then "750" else "700";
- cmdline = [ "-v" "-d" data.domain "--default_root" data.webroot "--valid_min" cfg.validMin ]
- ++ optionals (data.email != null) [ "--email" data.email ]
- ++ concatMap (p: [ "-f" p ]) data.plugins
- ++ concatLists (mapAttrsToList (name: root: [ "-d" (if root == null then name else "${name}:${root}")]) data.extraDomains)
+ apath = "/var/lib/${lpath}";
+ spath = "/var/lib/acme/.lego";
+ fileMode = if data.allowKeysForGroup then "640" else "600";
+ globalOpts = [ "-d" data.domain "--email" data.email "--path" "." "--key-type" data.keyType ]
+ ++ optionals (cfg.acceptTerms) [ "--accept-tos" ]
+ ++ optionals (data.dnsProvider != null && !data.dnsPropagationCheck) [ "--dns.disable-cp" ]
+ ++ concatLists (mapAttrsToList (name: root: [ "-d" name ]) data.extraDomains)
+ ++ (if data.dnsProvider != null then [ "--dns" data.dnsProvider ] else [ "--http" "--http.webroot" data.webroot ])
++ optionals (cfg.server != null || data.server != null) ["--server" (if data.server == null then cfg.server else data.server)];
+ certOpts = optionals data.ocspMustStaple [ "--must-staple" ];
+ runOpts = escapeShellArgs (globalOpts ++ [ "run" ] ++ certOpts);
+ renewOpts = escapeShellArgs (globalOpts ++
+ [ "renew" "--days" (toString cfg.validMinDays) ] ++
+ certOpts ++ data.extraLegoRenewFlags);
acmeService = {
description = "Renew ACME Certificate for ${cert}";
after = [ "network.target" "network-online.target" ];
wants = [ "network-online.target" ];
- # simp_le uses requests, which uses certifi under the hood,
- # which doesn't respect the system trust store.
- # At least in the acme test, we provision a fake CA, impersonating the LE endpoint.
- # REQUESTS_CA_BUNDLE is a way to teach python requests to use something else
- environment.REQUESTS_CA_BUNDLE = "/etc/ssl/certs/ca-certificates.crt";
+ wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
# With RemainAfterExit the service is considered active even
@@ -233,18 +327,38 @@ in
# the permissions of the StateDirectory get adjusted
# according to the specified group
RemainAfterExit = true;
- SuccessExitStatus = [ "0" "1" ];
User = data.user;
Group = data.group;
PrivateTmp = true;
- StateDirectory = lpath;
- StateDirectoryMode = rights;
- WorkingDirectory = "/var/lib/${lpath}";
- ExecStart = "${pkgs.simp_le}/bin/simp_le ${escapeShellArgs cmdline}";
+ StateDirectory = "acme/.lego ${lpath}";
+ StateDirectoryMode = if data.allowKeysForGroup then "750" else "700";
+ WorkingDirectory = spath;
+ # Only try loading the credentialsFile if the dns challenge is enabled
+ EnvironmentFile = if data.dnsProvider != null then data.credentialsFile else null;
+ ExecStart = pkgs.writeScript "acme-start" ''
+ #!${pkgs.runtimeShell} -e
+ ${pkgs.lego}/bin/lego ${renewOpts} || ${pkgs.lego}/bin/lego ${runOpts}
+ '';
ExecStartPost =
let
+ keyName = builtins.replaceStrings ["*"] ["_"] data.domain;
script = pkgs.writeScript "acme-post-start" ''
#!${pkgs.runtimeShell} -e
+ cd ${apath}
+
+ # Test that existing cert is older than new cert
+ KEY=${spath}/certificates/${keyName}.key
+ if [ -e $KEY -a $KEY -nt key.pem ]; then
+ cp -p ${spath}/certificates/${keyName}.key key.pem
+ cp -p ${spath}/certificates/${keyName}.crt fullchain.pem
+ cp -p ${spath}/certificates/${keyName}.issuer.crt chain.pem
+ ln -sf fullchain.pem cert.pem
+ cat key.pem fullchain.pem > full.pem
+ fi
+
+ chmod ${fileMode} *.pem
+ chown '${data.user}:${data.group}' *.pem
+
${data.postRun}
'';
in
@@ -276,17 +390,17 @@ in
-out $workdir/server.crt
# Copy key to destination
- cp $workdir/server.key /var/lib/${lpath}/key.pem
+ cp $workdir/server.key ${apath}/key.pem
# Create fullchain.pem (same format as "simp_le ... -f fullchain.pem" creates)
- cat $workdir/{server.crt,ca.crt} > "/var/lib/${lpath}/fullchain.pem"
+ cat $workdir/{server.crt,ca.crt} > "${apath}/fullchain.pem"
# Create full.pem for e.g. lighttpd
- cat $workdir/{server.key,server.crt,ca.crt} > "/var/lib/${lpath}/full.pem"
+ cat $workdir/{server.key,server.crt,ca.crt} > "${apath}/full.pem"
# Give key acme permissions
- chown '${data.user}:${data.group}' "/var/lib/${lpath}/"{key,fullchain,full}.pem
- chmod ${rights} "/var/lib/${lpath}/"{key,fullchain,full}.pem
+ chown '${data.user}:${data.group}' "${apath}/"{key,fullchain,full}.pem
+ chmod ${fileMode} "${apath}/"{key,fullchain,full}.pem
'';
serviceConfig = {
Type = "oneshot";
@@ -297,7 +411,7 @@ in
};
unitConfig = {
# Do not create self-signed key when key already exists
- ConditionPathExists = "!/var/lib/${lpath}/key.pem";
+ ConditionPathExists = "!${apath}/key.pem";
};
};
in (
@@ -309,10 +423,19 @@ in
servicesAttr;
systemd.tmpfiles.rules =
- flip mapAttrsToList cfg.certs
- (cert: data: "d ${data.webroot}/.well-known/acme-challenge - ${data.user} ${data.group}");
-
- systemd.timers = flip mapAttrs' cfg.certs (cert: data: nameValuePair
+ map (data: "d ${data.webroot}/.well-known/acme-challenge - ${data.user} ${data.group}") (filter (data: data.webroot != null) (attrValues cfg.certs));
+
+ systemd.timers = let
+ # Allow systemd to pick a convenient time within the day
+ # to run the check.
+ # This allows the coalescing of multiple timer jobs.
+ # We divide by the number of certificates so that if you
+ # have many certificates, the renewals are distributed over
+ # the course of the day to avoid rate limits.
+ numCerts = length (attrNames cfg.certs);
+ _24hSecs = 60 * 60 * 24;
+ AccuracySec = "${toString (_24hSecs / numCerts)}s";
+ in flip mapAttrs' cfg.certs (cert: data: nameValuePair
("acme-${cert}")
({
description = "Renew ACME Certificate for ${cert}";
@@ -321,8 +444,9 @@ in
OnCalendar = cfg.renewInterval;
Unit = "acme-${cert}.service";
Persistent = "yes";
- AccuracySec = "5m";
- RandomizedDelaySec = "1h";
+ inherit AccuracySec;
+ # Skew randomly within the day, per https://letsencrypt.org/docs/integration-guide/.
+ RandomizedDelaySec = "24h";
};
})
);
@@ -334,7 +458,7 @@ in
];
meta = {
- maintainers = with lib.maintainers; [ abbradar fpletz globin ];
+ maintainers = with lib.maintainers; [ abbradar fpletz globin m1cr0man ];
doc = ./acme.xml;
};
}
diff --git a/nixpkgs/nixos/modules/security/acme.xml b/nixpkgs/nixos/modules/security/acme.xml
index 9d0a1995e0f..2b29c117484 100644
--- a/nixpkgs/nixos/modules/security/acme.xml
+++ b/nixpkgs/nixos/modules/security/acme.xml
@@ -7,7 +7,7 @@
<para>
NixOS supports automatic domain validation &amp; certificate retrieval and
renewal using the ACME protocol. This is currently only implemented by and
- for Let's Encrypt. The alternative ACME client <literal>simp_le</literal> is
+ for Let's Encrypt. The alternative ACME client <literal>lego</literal> is
used under the hood.
</para>
<section xml:id="module-security-acme-prerequisites">
diff --git a/nixpkgs/nixos/modules/security/duosec.nix b/nixpkgs/nixos/modules/security/duosec.nix
index 78a82b7154e..c686a6861d0 100644
--- a/nixpkgs/nixos/modules/security/duosec.nix
+++ b/nixpkgs/nixos/modules/security/duosec.nix
@@ -12,7 +12,7 @@ let
ikey=${cfg.ikey}
skey=${cfg.skey}
host=${cfg.host}
- ${optionalString (cfg.group != "") ("group="+cfg.group)}
+ ${optionalString (cfg.groups != "") ("groups="+cfg.groups)}
failmode=${cfg.failmode}
pushinfo=${boolToStr cfg.pushinfo}
autopush=${boolToStr cfg.autopush}
@@ -42,6 +42,10 @@ let
};
in
{
+ imports = [
+ (mkRenamedOptionModule [ "security" "duosec" "group" ] [ "security" "duosec" "groups" ])
+ ];
+
options = {
security.duosec = {
ssh.enable = mkOption {
@@ -71,10 +75,16 @@ in
description = "Duo API hostname.";
};
- group = mkOption {
+ groups = mkOption {
type = types.str;
default = "";
- description = "Use Duo authentication for users only in this group.";
+ example = "users,!wheel,!*admin guests";
+ description = ''
+ If specified, Duo authentication is required only for users
+ whose primary group or supplementary group list matches one
+ of the space-separated pattern lists. Refer to
+ <link xlink:href="https://duo.com/docs/duounix"/> for details.
+ '';
};
failmode = mkOption {
diff --git a/nixpkgs/nixos/modules/security/google_oslogin.nix b/nixpkgs/nixos/modules/security/google_oslogin.nix
index 246419b681a..6f9962e1d62 100644
--- a/nixpkgs/nixos/modules/security/google_oslogin.nix
+++ b/nixpkgs/nixos/modules/security/google_oslogin.nix
@@ -59,10 +59,8 @@ in
exec ${package}/bin/google_authorized_keys "$@"
'';
};
- services.openssh.extraConfig = ''
- AuthorizedKeysCommand /etc/ssh/authorized_keys_command_google_oslogin %u
- AuthorizedKeysCommandUser nobody
- '';
+ services.openssh.authorizedKeysCommand = "/etc/ssh/authorized_keys_command_google_oslogin %u";
+ services.openssh.authorizedKeysCommandUser = "nobody";
};
}
diff --git a/nixpkgs/nixos/modules/security/rngd.nix b/nixpkgs/nixos/modules/security/rngd.nix
index d9d6d9c9f25..cffa1a5849f 100644
--- a/nixpkgs/nixos/modules/security/rngd.nix
+++ b/nixpkgs/nixos/modules/security/rngd.nix
@@ -37,14 +37,24 @@ in
after = [ "dev-random.device" ];
+ # Clean shutdown without DefaultDependencies
+ conflicts = [ "shutdown.target" ];
+ before = [
+ "sysinit.target"
+ "shutdown.target"
+ ];
+
description = "Hardware RNG Entropy Gatherer Daemon";
+ # rngd may have to start early to avoid entropy starvation during boot with encrypted swap
+ unitConfig.DefaultDependencies = false;
serviceConfig = {
ExecStart = "${pkgs.rng-tools}/sbin/rngd -f"
+ optionalString cfg.debug " -d";
+ # PrivateTmp would introduce a circular dependency if /tmp is on tmpfs and swap is encrypted,
+ # thus depending on rngd before swap, while swap depends on rngd to avoid entropy starvation.
NoNewPrivileges = true;
PrivateNetwork = true;
- PrivateTmp = true;
ProtectSystem = "full";
ProtectHome = true;
};
diff --git a/nixpkgs/nixos/modules/security/sudo.nix b/nixpkgs/nixos/modules/security/sudo.nix
index d899806ef05..e3e43177def 100644
--- a/nixpkgs/nixos/modules/security/sudo.nix
+++ b/nixpkgs/nixos/modules/security/sudo.nix
@@ -71,23 +71,25 @@ in
this is the case when configuration options are merged.
'';
default = [];
- example = [
- # Allow execution of any command by all users in group sudo,
- # requiring a password.
- { groups = [ "sudo" ]; commands = [ "ALL" ]; }
-
- # Allow execution of "/home/root/secret.sh" by user `backup`, `database`
- # and the group with GID `1006` without a password.
- { users = [ "backup" "database" ]; groups = [ 1006 ];
- commands = [ { command = "/home/root/secret.sh"; options = [ "SETENV" "NOPASSWD" ]; } ]; }
-
- # Allow all users of group `bar` to run two executables as user `foo`
- # with arguments being pre-set.
- { groups = [ "bar" ]; runAs = "foo";
- commands =
- [ "/home/baz/cmd1.sh hello-sudo"
- { command = ''/home/baz/cmd2.sh ""''; options = [ "SETENV" ]; } ]; }
- ];
+ example = literalExample ''
+ [
+ # Allow execution of any command by all users in group sudo,
+ # requiring a password.
+ { groups = [ "sudo" ]; commands = [ "ALL" ]; }
+
+ # Allow execution of "/home/root/secret.sh" by user `backup`, `database`
+ # and the group with GID `1006` without a password.
+ { users = [ "backup" "database" ]; groups = [ 1006 ];
+ commands = [ { command = "/home/root/secret.sh"; options = [ "SETENV" "NOPASSWD" ]; } ]; }
+
+ # Allow all users of group `bar` to run two executables as user `foo`
+ # with arguments being pre-set.
+ { groups = [ "bar" ]; runAs = "foo";
+ commands =
+ [ "/home/baz/cmd1.sh hello-sudo"
+ { command = '''/home/baz/cmd2.sh ""'''; options = [ "SETENV" ]; } ]; }
+ ]
+ '';
type = with types; listOf (submodule {
options = {
users = mkOption {
diff --git a/nixpkgs/nixos/modules/security/tpm2.nix b/nixpkgs/nixos/modules/security/tpm2.nix
new file mode 100644
index 00000000000..13804fb82cb
--- /dev/null
+++ b/nixpkgs/nixos/modules/security/tpm2.nix
@@ -0,0 +1,185 @@
+{ lib, pkgs, config, ... }:
+let
+ cfg = config.security.tpm2;
+
+ # This snippet is taken from tpm2-tss/dist/tpm-udev.rules, but modified to allow custom user/groups
+ # The idea is that the tssUser is allowed to acess the TPM and kernel TPM resource manager, while
+ # the tssGroup is only allowed to access the kernel resource manager
+ # Therefore, if either of the two are null, the respective part isn't generated
+ udevRules = tssUser: tssGroup: ''
+ ${lib.optionalString (tssUser != null) ''KERNEL=="tpm[0-9]*", MODE="0660", OWNER="${tssUser}"''}
+ ${lib.optionalString (tssUser != null || tssGroup != null)
+ ''KERNEL=="tpmrm[0-9]*", MODE="0660"''
+ + lib.optionalString (tssUser != null) '', OWNER="${tssUser}"''
+ + lib.optionalString (tssGroup != null) '', GROUP="${tssGroup}"''
+ }
+ '';
+
+in {
+ options.security.tpm2 = {
+ enable = lib.mkEnableOption "Trusted Platform Module 2 support";
+
+ tssUser = lib.mkOption {
+ description = ''
+ Name of the tpm device-owner and service user, set if applyUdevRules is
+ set.
+ '';
+ type = lib.types.nullOr lib.types.str;
+ default = if cfg.abrmd.enable then "tss" else "root";
+ defaultText = ''"tss" when using the userspace resource manager,'' +
+ ''"root" otherwise'';
+ };
+
+ tssGroup = lib.mkOption {
+ description = ''
+ Group of the tpm kernel resource manager (tpmrm) device-group, set if
+ applyUdevRules is set.
+ '';
+ type = lib.types.nullOr lib.types.str;
+ default = "tss";
+ };
+
+ applyUdevRules = lib.mkOption {
+ description = ''
+ Whether to make the /dev/tpm[0-9] devices accessible by the tssUser, or
+ the /dev/tpmrm[0-9] by tssGroup respectively
+ '';
+ type = lib.types.bool;
+ default = true;
+ };
+
+ abrmd = {
+ enable = lib.mkEnableOption ''
+ Trusted Platform 2 userspace resource manager daemon
+ '';
+
+ package = lib.mkOption {
+ description = "tpm2-abrmd package to use";
+ type = lib.types.package;
+ default = pkgs.tpm2-abrmd;
+ defaultText = "pkgs.tpm2-abrmd";
+ };
+ };
+
+ pkcs11 = {
+ enable = lib.mkEnableOption ''
+ TPM2 PKCS#11 tool and shared library in system path
+ (<literal>/run/current-system/sw/lib/libtpm2_pkcs11.so</literal>)
+ '';
+
+ package = lib.mkOption {
+ description = "tpm2-pkcs11 package to use";
+ type = lib.types.package;
+ default = pkgs.tpm2-pkcs11;
+ defaultText = "pkgs.tpm2-pkcs11";
+ };
+ };
+
+ tctiEnvironment = {
+ enable = lib.mkOption {
+ description = ''
+ Set common TCTI environment variables to the specified value.
+ The variables are
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>TPM2TOOLS_TCTI</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>TPM2_PKCS11_TCTI</literal>
+ </para>
+ </listitem>
+ </itemizedlist>
+ '';
+ type = lib.types.bool;
+ default = false;
+ };
+
+ interface = lib.mkOption {
+ description = ''
+ The name of the TPM command transmission interface (TCTI) library to
+ use.
+ '';
+ type = lib.types.enum [ "tabrmd" "device" ];
+ default = "device";
+ };
+
+ deviceConf = lib.mkOption {
+ description = ''
+ Configuration part of the device TCTI, e.g. the path to the TPM device.
+ Applies if interface is set to "device".
+ The format is specified in the
+ <link xlink:href="https://github.com/tpm2-software/tpm2-tools/blob/master/man/common/tcti.md#tcti-options">
+ tpm2-tools repository</link>.
+ '';
+ type = lib.types.str;
+ default = "/dev/tpmrm0";
+ };
+
+ tabrmdConf = lib.mkOption {
+ description = ''
+ Configuration part of the tabrmd TCTI, like the D-Bus bus name.
+ Applies if interface is set to "tabrmd".
+ The format is specified in the
+ <link xlink:href="https://github.com/tpm2-software/tpm2-tools/blob/master/man/common/tcti.md#tcti-options">
+ tpm2-tools repository</link>.
+ '';
+ type = lib.types.str;
+ default = "bus_name=com.intel.tss2.Tabrmd";
+ };
+ };
+ };
+
+ config = lib.mkIf cfg.enable (lib.mkMerge [
+ {
+ # PKCS11 tools and library
+ environment.systemPackages = lib.mkIf cfg.pkcs11.enable [
+ (lib.getBin cfg.pkcs11.package)
+ (lib.getLib cfg.pkcs11.package)
+ ];
+
+ services.udev.extraRules = lib.mkIf cfg.applyUdevRules
+ (udevRules cfg.tssUser cfg.tssGroup);
+
+ # Create the tss user and group only if the default value is used
+ users.users.${cfg.tssUser} = lib.mkIf (cfg.tssUser == "tss") {
+ isSystemUser = true;
+ };
+ users.groups.${cfg.tssGroup} = lib.mkIf (cfg.tssGroup == "tss") {};
+
+ environment.variables = lib.mkIf cfg.tctiEnvironment.enable (
+ lib.attrsets.genAttrs [
+ "TPM2TOOLS_TCTI"
+ "TPM2_PKCS11_TCTI"
+ ] (_: ''${cfg.tctiEnvironment.interface}:${
+ if cfg.tctiEnvironment.interface == "tabrmd" then
+ cfg.tctiEnvironment.tabrmdConf
+ else
+ cfg.tctiEnvironment.deviceConf
+ }'')
+ );
+ }
+
+ (lib.mkIf cfg.abrmd.enable {
+ systemd.services."tpm2-abrmd" = {
+ wantedBy = [ "multi-user.target" ];
+ serviceConfig = {
+ Type = "dbus";
+ Restart = "always";
+ RestartSec = 30;
+ BusName = "com.intel.tss2.Tabrmd";
+ StandardOutput = "syslog";
+ ExecStart = "${cfg.abrmd.package}/bin/tpm2-abrmd";
+ User = "tss";
+ Group = "nogroup";
+ };
+ };
+
+ services.dbus.packages = lib.singleton cfg.abrmd.package;
+ })
+ ]);
+
+ meta.maintainers = with lib.maintainers; [ lschuermann ];
+}
diff --git a/nixpkgs/nixos/modules/services/audio/alsa.nix b/nixpkgs/nixos/modules/services/audio/alsa.nix
index 990398e6546..3fe76a16540 100644
--- a/nixpkgs/nixos/modules/services/audio/alsa.nix
+++ b/nixpkgs/nixos/modules/services/audio/alsa.nix
@@ -91,11 +91,7 @@ in
environment.systemPackages = [ alsaUtils ];
environment.etc = mkIf (!pulseaudioEnabled && config.sound.extraConfig != "")
- [
- { source = pkgs.writeText "asound.conf" config.sound.extraConfig;
- target = "asound.conf";
- }
- ];
+ { "asound.conf".text = config.sound.extraConfig; };
# ALSA provides a udev rule for restoring volume settings.
services.udev.packages = [ alsaUtils ];
diff --git a/nixpkgs/nixos/modules/services/audio/mopidy.nix b/nixpkgs/nixos/modules/services/audio/mopidy.nix
index a534b692f17..d30c227db42 100644
--- a/nixpkgs/nixos/modules/services/audio/mopidy.nix
+++ b/nixpkgs/nixos/modules/services/audio/mopidy.nix
@@ -13,11 +13,11 @@ let
mopidyEnv = buildEnv {
name = "mopidy-with-extensions-${mopidy.version}";
paths = closePropagation cfg.extensionPackages;
- pathsToLink = [ "/${python.sitePackages}" ];
+ pathsToLink = [ "/${python3.sitePackages}" ];
buildInputs = [ makeWrapper ];
postBuild = ''
makeWrapper ${mopidy}/bin/mopidy $out/bin/mopidy \
- --prefix PYTHONPATH : $out/${python.sitePackages}
+ --prefix PYTHONPATH : $out/${python3.sitePackages}
'';
};
in {
diff --git a/nixpkgs/nixos/modules/services/backup/restic.nix b/nixpkgs/nixos/modules/services/backup/restic.nix
index 7e8e91e4b9c..2388f1d6ca1 100644
--- a/nixpkgs/nixos/modules/services/backup/restic.nix
+++ b/nixpkgs/nixos/modules/services/backup/restic.nix
@@ -103,6 +103,34 @@ in
Create the repository if it doesn't exist.
'';
};
+
+ pruneOpts = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ description = ''
+ A list of options (--keep-* et al.) for 'restic forget
+ --prune', to automatically prune old snapshots. The
+ 'forget' command is run *after* the 'backup' command, so
+ keep that in mind when constructing the --keep-* options.
+ '';
+ example = [
+ "--keep-daily 7"
+ "--keep-weekly 5"
+ "--keep-monthly 12"
+ "--keep-yearly 75"
+ ];
+ };
+
+ dynamicFilesFrom = mkOption {
+ type = with types; nullOr str;
+ default = null;
+ description = ''
+ A script that produces a list of files to back up. The
+ results of this command are given to the '--files-from'
+ option.
+ '';
+ example = "find /home/matt/git -type d -name .git";
+ };
};
}));
default = {};
@@ -134,25 +162,41 @@ in
let
extraOptions = concatMapStrings (arg: " -o ${arg}") backup.extraOptions;
resticCmd = "${pkgs.restic}/bin/restic${extraOptions}";
+ filesFromTmpFile = "/run/restic-backups-${name}/includes";
+ backupPaths = if (backup.dynamicFilesFrom == null)
+ then concatStringsSep " " backup.paths
+ else "--files-from ${filesFromTmpFile}";
+ pruneCmd = optionals (builtins.length backup.pruneOpts > 0) [
+ ( resticCmd + " forget --prune " + (concatStringsSep " " backup.pruneOpts) )
+ ( resticCmd + " check" )
+ ];
in nameValuePair "restic-backups-${name}" ({
environment = {
RESTIC_PASSWORD_FILE = backup.passwordFile;
RESTIC_REPOSITORY = backup.repository;
};
- path = with pkgs; [
- openssh
- ];
+ path = [ pkgs.openssh ];
restartIfChanged = false;
serviceConfig = {
Type = "oneshot";
- ExecStart = "${resticCmd} backup ${concatStringsSep " " backup.extraBackupArgs} ${concatStringsSep " " backup.paths}";
+ ExecStart = [ "${resticCmd} backup ${concatStringsSep " " backup.extraBackupArgs} ${backupPaths}" ] ++ pruneCmd;
User = backup.user;
+ RuntimeDirectory = "restic-backups-${name}";
} // optionalAttrs (backup.s3CredentialsFile != null) {
EnvironmentFile = backup.s3CredentialsFile;
};
- } // optionalAttrs backup.initialize {
+ } // optionalAttrs (backup.initialize || backup.dynamicFilesFrom != null) {
preStart = ''
- ${resticCmd} snapshots || ${resticCmd} init
+ ${optionalString (backup.initialize) ''
+ ${resticCmd} snapshots || ${resticCmd} init
+ ''}
+ ${optionalString (backup.dynamicFilesFrom != null) ''
+ ${pkgs.writeScript "dynamicFilesFromScript" backup.dynamicFilesFrom} > ${filesFromTmpFile}
+ ''}
+ '';
+ } // optionalAttrs (backup.dynamicFilesFrom != null) {
+ postStart = ''
+ rm ${filesFromTmpFile}
'';
})
) config.services.restic.backups;
diff --git a/nixpkgs/nixos/modules/services/backup/sanoid.nix b/nixpkgs/nixos/modules/services/backup/sanoid.nix
new file mode 100644
index 00000000000..0472fb4ba1e
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/backup/sanoid.nix
@@ -0,0 +1,213 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.sanoid;
+
+ datasetSettingsType = with types;
+ (attrsOf (nullOr (oneOf [ str int bool (listOf str) ]))) // {
+ description = "dataset/template options";
+ };
+
+ # Default values from https://github.com/jimsalterjrs/sanoid/blob/master/sanoid.defaults.conf
+
+ commonOptions = {
+ hourly = mkOption {
+ description = "Number of hourly snapshots.";
+ type = types.ints.unsigned;
+ default = 48;
+ };
+
+ daily = mkOption {
+ description = "Number of daily snapshots.";
+ type = types.ints.unsigned;
+ default = 90;
+ };
+
+ monthly = mkOption {
+ description = "Number of monthly snapshots.";
+ type = types.ints.unsigned;
+ default = 6;
+ };
+
+ yearly = mkOption {
+ description = "Number of yearly snapshots.";
+ type = types.ints.unsigned;
+ default = 0;
+ };
+
+ autoprune = mkOption {
+ description = "Whether to automatically prune old snapshots.";
+ type = types.bool;
+ default = true;
+ };
+
+ autosnap = mkOption {
+ description = "Whether to automatically take snapshots.";
+ type = types.bool;
+ default = true;
+ };
+
+ settings = mkOption {
+ description = ''
+ Free-form settings for this template/dataset. See
+ <link xlink:href="https://github.com/jimsalterjrs/sanoid/blob/master/sanoid.defaults.conf"/>
+ for allowed values.
+ '';
+ type = datasetSettingsType;
+ };
+ };
+
+ commonConfig = config: {
+ settings = {
+ hourly = mkDefault config.hourly;
+ daily = mkDefault config.daily;
+ monthly = mkDefault config.monthly;
+ yearly = mkDefault config.yearly;
+ autoprune = mkDefault config.autoprune;
+ autosnap = mkDefault config.autosnap;
+ };
+ };
+
+ datasetOptions = {
+ useTemplate = mkOption {
+ description = "Names of the templates to use for this dataset.";
+ type = (types.listOf (types.enum (attrNames cfg.templates))) // {
+ description = "list of template names";
+ };
+ default = [];
+ };
+
+ recursive = mkOption {
+ description = "Whether to recursively snapshot dataset children.";
+ type = types.bool;
+ default = false;
+ };
+
+ processChildrenOnly = mkOption {
+ description = "Whether to only snapshot child datasets if recursing.";
+ type = types.bool;
+ default = false;
+ };
+ };
+
+ datasetConfig = config: {
+ settings = {
+ use_template = mkDefault config.useTemplate;
+ recursive = mkDefault config.recursive;
+ process_children_only = mkDefault config.processChildrenOnly;
+ };
+ };
+
+ # Extract pool names from configured datasets
+ pools = unique (map (d: head (builtins.match "([^/]+).*" d)) (attrNames cfg.datasets));
+
+ configFile = let
+ mkValueString = v:
+ if builtins.isList v then concatStringsSep "," v
+ else generators.mkValueStringDefault {} v;
+
+ mkKeyValue = k: v: if v == null then ""
+ else generators.mkKeyValueDefault { inherit mkValueString; } "=" k v;
+ in generators.toINI { inherit mkKeyValue; } cfg.settings;
+
+ configDir = pkgs.writeTextDir "sanoid.conf" configFile;
+
+in {
+
+ # Interface
+
+ options.services.sanoid = {
+ enable = mkEnableOption "Sanoid ZFS snapshotting service";
+
+ interval = mkOption {
+ type = types.str;
+ default = "hourly";
+ example = "daily";
+ description = ''
+ Run sanoid at this interval. The default is to run hourly.
+
+ The format is described in
+ <citerefentry><refentrytitle>systemd.time</refentrytitle>
+ <manvolnum>7</manvolnum></citerefentry>.
+ '';
+ };
+
+ datasets = mkOption {
+ type = types.attrsOf (types.submodule ({ config, ... }: {
+ options = commonOptions // datasetOptions;
+ config = mkMerge [ (commonConfig config) (datasetConfig config) ];
+ }));
+ default = {};
+ description = "Datasets to snapshot.";
+ };
+
+ templates = mkOption {
+ type = types.attrsOf (types.submodule ({ config, ... }: {
+ options = commonOptions;
+ config = commonConfig config;
+ }));
+ default = {};
+ description = "Templates for datasets.";
+ };
+
+ settings = mkOption {
+ type = types.attrsOf datasetSettingsType;
+ description = ''
+ Free-form settings written directly to the config file. See
+ <link xlink:href="https://github.com/jimsalterjrs/sanoid/blob/master/sanoid.defaults.conf"/>
+ for allowed values.
+ '';
+ };
+
+ extraArgs = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ example = [ "--verbose" "--readonly" "--debug" ];
+ description = ''
+ Extra arguments to pass to sanoid. See
+ <link xlink:href="https://github.com/jimsalterjrs/sanoid/#sanoid-command-line-options"/>
+ for allowed options.
+ '';
+ };
+ };
+
+ # Implementation
+
+ config = mkIf cfg.enable {
+ services.sanoid.settings = mkMerge [
+ (mapAttrs' (d: v: nameValuePair ("template_" + d) v.settings) cfg.templates)
+ (mapAttrs (d: v: v.settings) cfg.datasets)
+ ];
+
+ systemd.services.sanoid = {
+ description = "Sanoid snapshot service";
+ serviceConfig = {
+ ExecStartPre = map (pool: lib.escapeShellArgs [
+ "+/run/booted-system/sw/bin/zfs" "allow"
+ "sanoid" "snapshot,mount,destroy" pool
+ ]) pools;
+ ExecStart = lib.escapeShellArgs ([
+ "${pkgs.sanoid}/bin/sanoid"
+ "--cron"
+ "--configdir" configDir
+ ] ++ cfg.extraArgs);
+ ExecStopPost = map (pool: lib.escapeShellArgs [
+ "+/run/booted-system/sw/bin/zfs" "unallow" "sanoid" pool
+ ]) pools;
+ User = "sanoid";
+ Group = "sanoid";
+ DynamicUser = true;
+ RuntimeDirectory = "sanoid";
+ CacheDirectory = "sanoid";
+ };
+ # Prevents missing snapshots during DST changes
+ environment.TZ = "UTC";
+ after = [ "zfs.target" ];
+ startAt = cfg.interval;
+ };
+ };
+
+ meta.maintainers = with maintainers; [ lopsided98 ];
+ }
diff --git a/nixpkgs/nixos/modules/services/backup/syncoid.nix b/nixpkgs/nixos/modules/services/backup/syncoid.nix
new file mode 100644
index 00000000000..53787a0182a
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/backup/syncoid.nix
@@ -0,0 +1,168 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.syncoid;
+in {
+
+ # Interface
+
+ options.services.syncoid = {
+ enable = mkEnableOption "Syncoid ZFS synchronization service";
+
+ interval = mkOption {
+ type = types.str;
+ default = "hourly";
+ example = "*-*-* *:15:00";
+ description = ''
+ Run syncoid at this interval. The default is to run hourly.
+
+ The format is described in
+ <citerefentry><refentrytitle>systemd.time</refentrytitle>
+ <manvolnum>7</manvolnum></citerefentry>.
+ '';
+ };
+
+ user = mkOption {
+ type = types.str;
+ default = "root";
+ example = "backup";
+ description = ''
+ The user for the service. Sudo or ZFS privilege delegation must be
+ configured to use a user other than root.
+ '';
+ };
+
+ sshKey = mkOption {
+ type = types.nullOr types.path;
+ # Prevent key from being copied to store
+ apply = mapNullable toString;
+ default = null;
+ description = ''
+ SSH private key file to use to login to the remote system. Can be
+ overridden in individual commands.
+ '';
+ };
+
+ commonArgs = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ example = [ "--no-sync-snap" ];
+ description = ''
+ Arguments to add to every syncoid command, unless disabled for that
+ command. See
+ <link xlink:href="https://github.com/jimsalterjrs/sanoid/#syncoid-command-line-options"/>
+ for available options.
+ '';
+ };
+
+ commands = mkOption {
+ type = types.attrsOf (types.submodule ({ name, ... }: {
+ options = {
+ source = mkOption {
+ type = types.str;
+ example = "pool/dataset";
+ description = ''
+ Source ZFS dataset. Can be either local or remote. Defaults to
+ the attribute name.
+ '';
+ };
+
+ target = mkOption {
+ type = types.str;
+ example = "user@server:pool/dataset";
+ description = ''
+ Target ZFS dataset. Can be either local
+ (<replaceable>pool/dataset</replaceable>) or remote
+ (<replaceable>user@server:pool/dataset</replaceable>).
+ '';
+ };
+
+ recursive = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to also transfer child datasets.
+ '';
+ };
+
+ sshKey = mkOption {
+ type = types.nullOr types.path;
+ # Prevent key from being copied to store
+ apply = mapNullable toString;
+ description = ''
+ SSH private key file to use to login to the remote system.
+ Defaults to <option>services.syncoid.sshKey</option> option.
+ '';
+ };
+
+ sendOptions = mkOption {
+ type = types.separatedString " ";
+ default = "";
+ example = "Lc e";
+ description = ''
+ Advanced options to pass to zfs send. Options are specified
+ without their leading dashes and separated by spaces.
+ '';
+ };
+
+ recvOptions = mkOption {
+ type = types.separatedString " ";
+ default = "";
+ example = "ux recordsize o compression=lz4";
+ description = ''
+ Advanced options to pass to zfs recv. Options are specified
+ without their leading dashes and separated by spaces.
+ '';
+ };
+
+ useCommonArgs = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether to add the configured common arguments to this command.
+ '';
+ };
+
+ extraArgs = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ example = [ "--sshport 2222" ];
+ description = "Extra syncoid arguments for this command.";
+ };
+ };
+ config = {
+ source = mkDefault name;
+ sshKey = mkDefault cfg.sshKey;
+ };
+ }));
+ default = {};
+ example."pool/test".target = "root@target:pool/test";
+ description = "Syncoid commands to run.";
+ };
+ };
+
+ # Implementation
+
+ config = mkIf cfg.enable {
+ systemd.services.syncoid = {
+ description = "Syncoid ZFS synchronization service";
+ script = concatMapStringsSep "\n" (c: lib.escapeShellArgs
+ ([ "${pkgs.sanoid}/bin/syncoid" ]
+ ++ (optionals c.useCommonArgs cfg.commonArgs)
+ ++ (optional c.recursive "-r")
+ ++ (optionals (c.sshKey != null) [ "--sshkey" c.sshKey ])
+ ++ c.extraArgs
+ ++ [ "--sendoptions" c.sendOptions
+ "--recvoptions" c.recvOptions
+ c.source c.target
+ ])) (attrValues cfg.commands);
+ after = [ "zfs.target" ];
+ serviceConfig.User = cfg.user;
+ startAt = cfg.interval;
+ };
+ };
+
+ meta.maintainers = with maintainers; [ lopsided98 ];
+ }
diff --git a/nixpkgs/nixos/modules/services/computing/foldingathome/client.nix b/nixpkgs/nixos/modules/services/computing/foldingathome/client.nix
new file mode 100644
index 00000000000..9f99af48c48
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/computing/foldingathome/client.nix
@@ -0,0 +1,81 @@
+{ config, lib, pkgs, ... }:
+with lib;
+let
+ cfg = config.services.foldingathome;
+
+ args =
+ ["--team" "${toString cfg.team}"]
+ ++ lib.optionals (cfg.user != null) ["--user" cfg.user]
+ ++ cfg.extraArgs
+ ;
+in
+{
+ imports = [
+ (mkRenamedOptionModule [ "services" "foldingAtHome" ] [ "services" "foldingathome" ])
+ (mkRenamedOptionModule [ "services" "foldingathome" "nickname" ] [ "services" "foldingathome" "user" ])
+ (mkRemovedOptionModule [ "services" "foldingathome" "config" ] ''
+ Use <literal>services.foldingathome.extraArgs instead<literal>
+ '')
+ ];
+ options.services.foldingathome = {
+ enable = mkEnableOption "Enable the Folding@home client";
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.fahclient;
+ defaultText = "pkgs.fahclient";
+ description = ''
+ Which Folding@home client to use.
+ '';
+ };
+
+ user = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description = ''
+ The user associated with the reported computation results. This will
+ be used in the ranking statistics.
+ '';
+ };
+
+ team = mkOption {
+ type = types.int;
+ default = 236565;
+ description = ''
+ The team ID associated with the reported computation results. This
+ will be used in the ranking statistics.
+
+ By default, use the NixOS folding@home team ID is being used.
+ '';
+ };
+
+ extraArgs = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ description = ''
+ Extra startup options for the FAHClient. Run
+ <literal>FAHClient --help</literal> to find all the available options.
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ systemd.services.foldingathome = {
+ description = "Folding@home client";
+ after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ script = ''
+ exec ${cfg.package}/bin/FAHClient ${lib.escapeShellArgs args}
+ '';
+ serviceConfig = {
+ DynamicUser = true;
+ StateDirectory = "foldingathome";
+ WorkingDirectory = "%S/foldingathome";
+ };
+ };
+ };
+
+ meta = {
+ maintainers = with lib.maintainers; [ zimbatm ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/computing/slurm/slurm.nix b/nixpkgs/nixos/modules/services/computing/slurm/slurm.nix
index c70d999ca96..050872e933f 100644
--- a/nixpkgs/nixos/modules/services/computing/slurm/slurm.nix
+++ b/nixpkgs/nixos/modules/services/computing/slurm/slurm.nix
@@ -355,6 +355,7 @@ in
ExecStart = "${wrappedSlurm}/bin/slurmd";
PIDFile = "/run/slurmd.pid";
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+ LimitMEMLOCK = "infinity";
};
preStart = ''
diff --git a/nixpkgs/nixos/modules/services/continuous-integration/buildkite-agent.nix b/nixpkgs/nixos/modules/services/continuous-integration/buildkite-agents.nix
index 58bce654941..c17d89c387a 100644
--- a/nixpkgs/nixos/modules/services/continuous-integration/buildkite-agent.nix
+++ b/nixpkgs/nixos/modules/services/continuous-integration/buildkite-agents.nix
@@ -3,7 +3,7 @@
with lib;
let
- cfg = config.services.buildkite-agent;
+ cfg = config.services.buildkite-agents;
mkHookOption = { name, description, example ? null }: {
inherit name;
@@ -15,7 +15,7 @@ let
};
mkHookOptions = hooks: listToAttrs (map mkHookOption hooks);
- hooksDir = let
+ hooksDir = cfg: let
mkHookEntry = name: value: ''
cat > $out/${name} <<'EOF'
#! ${pkgs.runtimeShell}
@@ -29,12 +29,13 @@ let
${concatStringsSep "\n" (mapAttrsToList mkHookEntry (filterAttrs (n: v: v != null) cfg.hooks))}
'';
-in
-
-{
- options = {
- services.buildkite-agent = {
- enable = mkEnableOption "buildkite-agent";
+ buildkiteOptions = { name ? "", config, ... }: {
+ options = {
+ enable = mkOption {
+ default = true;
+ type = types.bool;
+ description = "Whether to enable this buildkite agent";
+ };
package = mkOption {
default = pkgs.buildkite-agent;
@@ -44,7 +45,7 @@ in
};
dataDir = mkOption {
- default = "/var/lib/buildkite-agent";
+ default = "/var/lib/buildkite-agent-${name}";
description = "The workdir for the agent";
type = types.str;
};
@@ -68,9 +69,9 @@ in
name = mkOption {
type = types.str;
- default = "%hostname-%n";
+ default = "%hostname-${name}-%n";
description = ''
- The name of the agent.
+ The name of the agent as seen in the buildkite dashboard.
'';
};
@@ -166,11 +167,11 @@ in
hooksPath = mkOption {
type = types.path;
- default = hooksDir;
- defaultText = "generated from services.buildkite-agent.hooks";
+ default = hooksDir config;
+ defaultText = "generated from services.buildkite-agents.<name>.hooks";
description = ''
Path to the directory storing the hooks.
- Consider using <option>services.buildkite-agent.hooks.&lt;name&gt;</option>
+ Consider using <option>services.buildkite-agents.&lt;name&gt;.hooks.&lt;name&gt;</option>
instead.
'';
};
@@ -184,24 +185,38 @@ in
};
};
};
+ enabledAgents = lib.filterAttrs (n: v: v.enable) cfg;
+ mapAgents = function: lib.mkMerge (lib.mapAttrsToList function enabledAgents);
+in
+{
+ options.services.buildkite-agents = mkOption {
+ type = types.attrsOf (types.submodule buildkiteOptions);
+ default = {};
+ description = ''
+ Attribute set of buildkite agents.
+ The attribute key is combined with the hostname and a unique integer to
+ create the final agent name. This can be overridden by setting the `name`
+ attribute.
+ '';
+ };
- config = mkIf config.services.buildkite-agent.enable {
- users.users.buildkite-agent = {
- name = "buildkite-agent";
+ config.users.users = mapAgents (name: cfg: {
+ "buildkite-agent-${name}" = {
+ name = "buildkite-agent-${name}";
home = cfg.dataDir;
createHome = true;
description = "Buildkite agent user";
extraGroups = [ "keys" ];
isSystemUser = true;
};
+ });
- environment.systemPackages = [ cfg.package ];
-
- systemd.services.buildkite-agent =
+ config.systemd.services = mapAgents (name: cfg: {
+ "buildkite-agent-${name}" =
{ description = "Buildkite Agent";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
- path = cfg.runtimePackages ++ [ pkgs.coreutils ];
+ path = cfg.runtimePackages ++ [ cfg.package pkgs.coreutils ];
environment = config.networking.proxy.envVars // {
HOME = cfg.dataDir;
NIX_REMOTE = "daemon";
@@ -230,8 +245,8 @@ in
'';
serviceConfig =
- { ExecStart = "${cfg.package}/bin/buildkite-agent start --config /var/lib/buildkite-agent/buildkite-agent.cfg";
- User = "buildkite-agent";
+ { ExecStart = "${cfg.package}/bin/buildkite-agent start --config ${cfg.dataDir}/buildkite-agent.cfg";
+ User = "buildkite-agent-${name}";
RestartSec = 5;
Restart = "on-failure";
TimeoutSec = 10;
@@ -240,22 +255,18 @@ in
KillMode = "mixed";
};
};
+ });
- assertions = [
- { assertion = cfg.hooksPath == hooksDir || all (v: v == null) (attrValues cfg.hooks);
+ config.assertions = mapAgents (name: cfg: [
+ { assertion = cfg.hooksPath == (hooksDir cfg) || all (v: v == null) (attrValues cfg.hooks);
message = ''
- Options `services.buildkite-agent.hooksPath' and
- `services.buildkite-agent.hooks.<name>' are mutually exclusive.
+ Options `services.buildkite-agents.${name}.hooksPath' and
+ `services.buildkite-agents.${name}.hooks.<name>' are mutually exclusive.
'';
}
- ];
- };
+ ]);
+
imports = [
- (mkRenamedOptionModule [ "services" "buildkite-agent" "token" ] [ "services" "buildkite-agent" "tokenPath" ])
- (mkRenamedOptionModule [ "services" "buildkite-agent" "openssh" "privateKey" ] [ "services" "buildkite-agent" "privateSshKeyPath" ])
- (mkRenamedOptionModule [ "services" "buildkite-agent" "openssh" "privateKeyPath" ] [ "services" "buildkite-agent" "privateSshKeyPath" ])
- (mkRemovedOptionModule [ "services" "buildkite-agent" "openssh" "publicKey" ] "SSH public keys aren't necessary to clone private repos.")
- (mkRemovedOptionModule [ "services" "buildkite-agent" "openssh" "publicKeyPath" ] "SSH public keys aren't necessary to clone private repos.")
- (mkRenamedOptionModule [ "services" "buildkite-agent" "meta-data"] [ "services" "buildkite-agent" "tags" ])
+ (mkRemovedOptionModule [ "services" "buildkite-agent"] "services.buildkite-agent has been upgraded from version 2 to version 3 and moved to an attribute set at services.buildkite-agents. Please consult the 20.03 release notes for more information.")
];
}
diff --git a/nixpkgs/nixos/modules/services/databases/mysql.nix b/nixpkgs/nixos/modules/services/databases/mysql.nix
index 8d520b82fb5..248bf0ebc91 100644
--- a/nixpkgs/nixos/modules/services/databases/mysql.nix
+++ b/nixpkgs/nixos/modules/services/databases/mysql.nix
@@ -21,6 +21,11 @@ let
installOptions =
"${mysqldOptions} ${lib.optionalString isMysqlAtLeast57 "--insecure"}";
+ settingsFile = pkgs.writeText "my.cnf" (
+ generators.toINI { listsAsDuplicateKeys = true; } cfg.settings +
+ optionalString (cfg.extraOptions != null) "[mysqld]\n${cfg.extraOptions}"
+ );
+
in
{
@@ -76,9 +81,64 @@ in
description = "Location where MySQL stores its table files";
};
+ configFile = mkOption {
+ type = types.path;
+ default = settingsFile;
+ defaultText = "settingsFile";
+ description = ''
+ Override the configuration file used by MySQL. By default,
+ NixOS generates one automatically from <option>services.mysql.settings</option>.
+ '';
+ example = literalExample ''
+ pkgs.writeText "my.cnf" '''
+ [mysqld]
+ datadir = /var/lib/mysql
+ bind-address = 127.0.0.1
+ port = 3336
+ plugin-load-add = auth_socket.so
+
+ !includedir /etc/mysql/conf.d/
+ ''';
+ '';
+ };
+
+ settings = mkOption {
+ type = with types; attrsOf (attrsOf (oneOf [ bool int str (listOf str) ]));
+ default = {};
+ description = ''
+ MySQL configuration. Refer to
+ <link xlink:href="https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html"/>,
+ <link xlink:href="https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html"/>,
+ and <link xlink:href="https://mariadb.com/kb/en/server-system-variables/"/>
+ for details on supported values.
+
+ <note>
+ <para>
+ MySQL configuration options such as <literal>--quick</literal> should be treated as
+ boolean options and provided values such as <literal>true</literal>, <literal>false</literal>,
+ <literal>1</literal>, or <literal>0</literal>. See the provided example below.
+ </para>
+ </note>
+ '';
+ example = literalExample ''
+ {
+ mysqld = {
+ key_buffer_size = "6G";
+ table_cache = 1600;
+ log-error = "/var/log/mysql_err.log";
+ plugin-load-add = [ "server_audit" "ed25519=auth_ed25519" ];
+ };
+ mysqldump = {
+ quick = true;
+ max_allowed_packet = "16M";
+ };
+ }
+ '';
+ };
+
extraOptions = mkOption {
- type = types.lines;
- default = "";
+ type = with types; nullOr lines;
+ default = null;
example = ''
key_buffer_size = 6G
table_cache = 1600
@@ -252,10 +312,27 @@ in
config = mkIf config.services.mysql.enable {
+ warnings = optional (cfg.extraOptions != null) "services.mysql.`extraOptions` is deprecated, please use services.mysql.`settings`.";
+
services.mysql.dataDir =
mkDefault (if versionAtLeast config.system.stateVersion "17.09" then "/var/lib/mysql"
else "/var/mysql");
+ services.mysql.settings.mysqld = mkMerge [
+ {
+ datadir = cfg.dataDir;
+ bind-address = mkIf (cfg.bind != null) cfg.bind;
+ port = cfg.port;
+ plugin-load-add = optional (cfg.ensureUsers != []) "auth_socket.so";
+ }
+ (mkIf (cfg.replication.role == "master" || cfg.replication.role == "slave") {
+ log-bin = "mysql-bin-${toString cfg.replication.serverId}";
+ log-bin-index = "mysql-bin-${toString cfg.replication.serverId}.index";
+ relay-log = "mysql-relay-bin";
+ server-id = cfg.replication.serverId;
+ })
+ ];
+
users.users.mysql = {
description = "MySQL server user";
group = "mysql";
@@ -266,25 +343,7 @@ in
environment.systemPackages = [mysql];
- environment.etc."my.cnf".text =
- ''
- [mysqld]
- port = ${toString cfg.port}
- datadir = ${cfg.dataDir}
- ${optionalString (cfg.bind != null) "bind-address = ${cfg.bind}" }
- ${optionalString (cfg.replication.role == "master" || cfg.replication.role == "slave")
- ''
- log-bin=mysql-bin-${toString cfg.replication.serverId}
- log-bin-index=mysql-bin-${toString cfg.replication.serverId}.index
- relay-log=mysql-relay-bin
- server-id = ${toString cfg.replication.serverId}
- ''}
- ${optionalString (cfg.ensureUsers != [])
- ''
- plugin-load-add = auth_socket.so
- ''}
- ${cfg.extraOptions}
- '';
+ environment.etc."my.cnf".source = cfg.configFile;
systemd.tmpfiles.rules = [
"d '${cfg.dataDir}' 0700 ${cfg.user} mysql -"
@@ -297,7 +356,7 @@ in
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
- restartTriggers = [ config.environment.etc."my.cnf".source ];
+ restartTriggers = [ cfg.configFile ];
unitConfig.RequiresMountsFor = "${cfg.dataDir}";
diff --git a/nixpkgs/nixos/modules/services/databases/postgresql.nix b/nixpkgs/nixos/modules/services/databases/postgresql.nix
index c8fdd89d0d8..0b79a996dc7 100644
--- a/nixpkgs/nixos/modules/services/databases/postgresql.nix
+++ b/nixpkgs/nixos/modules/services/databases/postgresql.nix
@@ -20,7 +20,9 @@ let
listen_addresses = '${if cfg.enableTCPIP then "*" else "localhost"}'
port = ${toString cfg.port}
${cfg.extraConfig}
- '';
+ '';
+
+ groupAccessAvailable = versionAtLeast postgresql.version "11.0";
in
@@ -88,6 +90,16 @@ in
'';
};
+ initdbArgs = mkOption {
+ type = with types; listOf str;
+ default = [];
+ example = [ "--data-checksums" "--allow-group-access" ];
+ description = ''
+ Additional arguments passed to <literal>initdb</literal> during data dir
+ initialisation.
+ '';
+ };
+
initialScript = mkOption {
type = types.nullOr types.path;
default = null;
@@ -220,7 +232,7 @@ in
###### implementation
- config = mkIf config.services.postgresql.enable {
+ config = mkIf cfg.enable {
services.postgresql.package =
# Note: when changing the default, make it conditional on
@@ -232,13 +244,14 @@ in
else throw "postgresql_9_4 was removed, please upgrade your postgresql version.");
services.postgresql.dataDir =
- mkDefault (if versionAtLeast config.system.stateVersion "17.09" then "/var/lib/postgresql/${config.services.postgresql.package.psqlSchema}"
- else "/var/db/postgresql");
+ mkDefault (if versionAtLeast config.system.stateVersion "17.09"
+ then "/var/lib/postgresql/${cfg.package.psqlSchema}"
+ else "/var/db/postgresql");
services.postgresql.authentication = mkAfter
''
# Generated file; do not edit!
- local all all ident
+ local all all peer
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
'';
@@ -284,7 +297,7 @@ in
''
# Initialise the database.
if ! test -e ${cfg.dataDir}/PG_VERSION; then
- initdb -U ${cfg.superUser}
+ initdb -U ${cfg.superUser} ${concatStringsSep " " cfg.initdbArgs}
# See postStart!
touch "${cfg.dataDir}/.first_startup"
fi
@@ -293,8 +306,12 @@ in
ln -sfn "${pkgs.writeText "recovery.conf" cfg.recoveryConfig}" \
"${cfg.dataDir}/recovery.conf"
''}
+ ${optionalString (!groupAccessAvailable) ''
+ # postgresql pre 11.0 doesn't start if state directory mode is group accessible
+ chmod 0700 "${cfg.dataDir}"
+ ''}
- exec postgres
+ exec postgres
'';
serviceConfig =
@@ -303,7 +320,7 @@ in
Group = "postgres";
PermissionsStartOnly = true;
RuntimeDirectory = "postgresql";
- Type = if lib.versionAtLeast cfg.package.version "9.6"
+ Type = if versionAtLeast cfg.package.version "9.6"
then "notify"
else "simple";
@@ -352,5 +369,5 @@ in
};
meta.doc = ./postgresql.xml;
- meta.maintainers = with lib.maintainers; [ thoughtpolice ];
+ meta.maintainers = with lib.maintainers; [ thoughtpolice danbst ];
}
diff --git a/nixpkgs/nixos/modules/services/databases/redis.nix b/nixpkgs/nixos/modules/services/databases/redis.nix
index 70895fa53e4..5c817422aae 100644
--- a/nixpkgs/nixos/modules/services/databases/redis.nix
+++ b/nixpkgs/nixos/modules/services/databases/redis.nix
@@ -150,10 +150,20 @@ in
requirePass = mkOption {
type = with types; nullOr str;
default = null;
- description = "Password for database (STORED PLAIN TEXT, WORLD-READABLE IN NIX STORE)";
+ description = ''
+ Password for database (STORED PLAIN TEXT, WORLD-READABLE IN NIX STORE).
+ Use requirePassFile to store it outside of the nix store in a dedicated file.
+ '';
example = "letmein!";
};
+ requirePassFile = mkOption {
+ type = with types; nullOr path;
+ default = null;
+ description = "File with password for the database.";
+ example = "/run/keys/redis-password";
+ };
+
appendOnly = mkOption {
type = types.bool;
default = false;
@@ -192,6 +202,10 @@ in
###### implementation
config = mkIf config.services.redis.enable {
+ assertions = [{
+ assertion = cfg.requirePass != null -> cfg.requirePassFile == null;
+ message = "You can only set one services.redis.requirePass or services.redis.requirePassFile";
+ }];
boot.kernel.sysctl = (mkMerge [
{ "vm.nr_hugepages" = "0"; }
( mkIf cfg.vmOverCommit { "vm.overcommit_memory" = "1"; } )
@@ -208,21 +222,26 @@ in
environment.systemPackages = [ cfg.package ];
- systemd.services.redis =
- { description = "Redis Server";
+ systemd.services.redis = {
+ description = "Redis Server";
- wantedBy = [ "multi-user.target" ];
- after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network.target" ];
- serviceConfig = {
- ExecStart = "${cfg.package}/bin/redis-server ${redisConfig}";
- RuntimeDirectory = "redis";
- StateDirectory = "redis";
- Type = "notify";
- User = "redis";
- };
- };
+ preStart = ''
+ install -m 600 ${redisConfig} /run/redis/redis.conf
+ '' + optionalString (cfg.requirePassFile != null) ''
+ password=$(cat ${escapeShellArg cfg.requirePassFile})
+ echo "requirePass $password" >> /run/redis/redis.conf
+ '';
+ serviceConfig = {
+ ExecStart = "${cfg.package}/bin/redis-server /run/redis/redis.conf";
+ RuntimeDirectory = "redis";
+ StateDirectory = "redis";
+ Type = "notify";
+ User = "redis";
+ };
+ };
};
-
}
diff --git a/nixpkgs/nixos/modules/services/desktops/malcontent.nix b/nixpkgs/nixos/modules/services/desktops/malcontent.nix
new file mode 100644
index 00000000000..416464cbe08
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/desktops/malcontent.nix
@@ -0,0 +1,32 @@
+# Malcontent daemon.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+
+ ###### interface
+
+ options = {
+
+ services.malcontent = {
+
+ enable = mkEnableOption "Malcontent";
+
+ };
+
+ };
+
+
+ ###### implementation
+
+ config = mkIf config.services.malcontent.enable {
+
+ environment.systemPackages = [ pkgs.malcontent ];
+
+ services.dbus.packages = [ pkgs.malcontent ];
+
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/development/jupyter/default.nix b/nixpkgs/nixos/modules/services/development/jupyter/default.nix
index f20860af6e1..e598b018645 100644
--- a/nixpkgs/nixos/modules/services/development/jupyter/default.nix
+++ b/nixpkgs/nixos/modules/services/development/jupyter/default.nix
@@ -118,15 +118,15 @@ in {
in {
displayName = "Python 3 for machine learning";
argv = [
- "$ {env.interpreter}"
+ "''${env.interpreter}"
"-m"
"ipykernel_launcher"
"-f"
"{connection_file}"
];
language = "python";
- logo32 = "$ {env.sitePackages}/ipykernel/resources/logo-32x32.png";
- logo64 = "$ {env.sitePackages}/ipykernel/resources/logo-64x64.png";
+ logo32 = "''${env.sitePackages}/ipykernel/resources/logo-32x32.png";
+ logo64 = "''${env.sitePackages}/ipykernel/resources/logo-64x64.png";
};
}
'';
diff --git a/nixpkgs/nixos/modules/services/hardware/fwupd.nix b/nixpkgs/nixos/modules/services/hardware/fwupd.nix
index 51877970a8b..e586af25c2b 100644
--- a/nixpkgs/nixos/modules/services/hardware/fwupd.nix
+++ b/nixpkgs/nixos/modules/services/hardware/fwupd.nix
@@ -53,7 +53,7 @@ in {
blacklistPlugins = mkOption {
type = types.listOf types.str;
- default = [ "test" ];
+ default = [];
example = [ "udev" ];
description = ''
Allow blacklisting specific plugins
@@ -91,6 +91,9 @@ in {
###### implementation
config = mkIf cfg.enable {
+ # Disable test related plug-ins implicitly so that users do not have to care about them.
+ services.fwupd.blacklistPlugins = cfg.package.defaultBlacklistedPlugins;
+
environment.systemPackages = [ cfg.package ];
environment.etc = {
diff --git a/nixpkgs/nixos/modules/services/hardware/irqbalance.nix b/nixpkgs/nixos/modules/services/hardware/irqbalance.nix
index b139154432c..c79e0eb83ec 100644
--- a/nixpkgs/nixos/modules/services/hardware/irqbalance.nix
+++ b/nixpkgs/nixos/modules/services/hardware/irqbalance.nix
@@ -13,18 +13,12 @@ in
config = mkIf cfg.enable {
- systemd.services = {
- irqbalance = {
- description = "irqbalance daemon";
- path = [ pkgs.irqbalance ];
- serviceConfig =
- { ExecStart = "${pkgs.irqbalance}/bin/irqbalance --foreground"; };
- wantedBy = [ "multi-user.target" ];
- };
- };
-
environment.systemPackages = [ pkgs.irqbalance ];
+ systemd.services.irqbalance.wantedBy = ["multi-user.target"];
+
+ systemd.packages = [ pkgs.irqbalance ];
+
};
}
diff --git a/nixpkgs/nixos/modules/services/hardware/tlp.nix b/nixpkgs/nixos/modules/services/hardware/tlp.nix
index 955a6067799..3962d7b1598 100644
--- a/nixpkgs/nixos/modules/services/hardware/tlp.nix
+++ b/nixpkgs/nixos/modules/services/hardware/tlp.nix
@@ -1,39 +1,26 @@
{ config, lib, pkgs, ... }:
-
with lib;
-
let
-
-cfg = config.services.tlp;
-
-enableRDW = config.networking.networkmanager.enable;
-
-tlp = pkgs.tlp.override {
- inherit enableRDW;
-};
-
-# XXX: We can't use writeTextFile + readFile here because it triggers
-# TLP build to get the .drv (even on --dry-run).
-confFile = pkgs.runCommand "tlp"
- { config = cfg.extraConfig;
- passAsFile = [ "config" ];
- preferLocalBuild = true;
- }
- ''
- cat ${tlp}/etc/default/tlp > $out
- cat $configPath >> $out
- '';
-
+ cfg = config.services.tlp;
+ enableRDW = config.networking.networkmanager.enable;
+ tlp = pkgs.tlp.override { inherit enableRDW; };
+ # TODO: Use this for having proper parameters in the future
+ mkTlpConfig = tlpConfig: generators.toKeyValue {
+ mkKeyValue = generators.mkKeyValueDefault {
+ mkValueString = val:
+ if isInt val then toString val
+ else if isString val then val
+ else if true == val then "1"
+ else if false == val then "0"
+ else if isList val then "\"" + (concatStringsSep " " val) + "\""
+ else err "invalid value provided to mkTlpConfig:" (toString val);
+ } "=";
+ } tlpConfig;
in
-
{
-
###### interface
-
options = {
-
services.tlp = {
-
enable = mkOption {
type = types.bool;
default = false;
@@ -45,77 +32,64 @@ in
default = "";
description = "Additional configuration variables for TLP";
};
-
};
-
};
-
###### implementation
-
config = mkIf cfg.enable {
+ boot.kernelModules = [ "msr" ];
- powerManagement.scsiLinkPolicy = null;
- powerManagement.cpuFreqGovernor = null;
- powerManagement.cpufreq.max = null;
- powerManagement.cpufreq.min = null;
+ environment.etc = {
+ "tlp.conf".text = cfg.extraConfig;
+ } // optionalAttrs enableRDW {
+ "NetworkManager/dispatcher.d/99tlp-rdw-nm".source =
+ "${tlp}/etc/NetworkManager/dispatcher.d/99tlp-rdw-nm";
+ };
- systemd.sockets.systemd-rfkill.enable = false;
+ environment.systemPackages = [ tlp ];
- systemd.services = {
- "systemd-rfkill@".enable = false;
- systemd-rfkill.enable = false;
+ # FIXME: When the config is parametrized we need to move these into a
+ # conditional on the relevant options being enabled.
+ powerManagement = {
+ scsiLinkPolicy = null;
+ cpuFreqGovernor = null;
+ cpufreq.max = null;
+ cpufreq.min = null;
+ };
- tlp = {
- description = "TLP system startup/shutdown";
+ services.udev.packages = [ tlp ];
- after = [ "multi-user.target" ];
+ systemd = {
+ packages = [ tlp ];
+ # XXX: These must always be disabled/masked according to [1].
+ #
+ # [1]: https://github.com/linrunner/TLP/blob/a9ada09e0821f275ce5f93dc80a4d81a7ff62ae4/tlp-stat.in#L319
+ sockets.systemd-rfkill.enable = false;
+ services.systemd-rfkill.enable = false;
+
+ services.tlp = {
+ # XXX: The service should reload whenever the configuration changes,
+ # otherwise newly set power options remain inactive until reboot (or
+ # manual unit restart.)
+ restartTriggers = [ config.environment.etc."tlp.conf".source ];
+ # XXX: When using systemd.packages (which we do above) the [Install]
+ # section of systemd units does not work (citation needed) so we manually
+ # enforce it here.
wantedBy = [ "multi-user.target" ];
- before = [ "shutdown.target" ];
- restartTriggers = [ confFile ];
-
- serviceConfig = {
- Type = "oneshot";
- RemainAfterExit = true;
- ExecStart = "${tlp}/bin/tlp init start";
- ExecStop = "${tlp}/bin/tlp init stop";
- };
};
- tlp-sleep = {
- description = "TLP suspend/resume";
-
- wantedBy = [ "sleep.target" ];
+ services.tlp-sleep = {
+ # XXX: When using systemd.packages (which we do above) the [Install]
+ # section of systemd units does not work (citation needed) so we manually
+ # enforce it here.
before = [ "sleep.target" ];
-
- unitConfig = {
- StopWhenUnneeded = true;
- };
-
- serviceConfig = {
- Type = "oneshot";
- RemainAfterExit = true;
- ExecStart = "${tlp}/bin/tlp suspend";
- ExecStop = "${tlp}/bin/tlp resume";
- };
+ wantedBy = [ "sleep.target" ];
+ # XXX: `tlp suspend` requires /var/lib/tlp to exist in order to save
+ # some stuff in there. There is no way, that I know of, to do this in
+ # the package itself, so we do it here instead making sure the unit
+ # won't fail due to the save dir not existing.
+ serviceConfig.StateDirectory = "tlp";
};
};
-
- services.udev.packages = [ tlp ];
-
- environment.etc =
- {
- "default/tlp".source = confFile;
- } // optionalAttrs enableRDW {
- "NetworkManager/dispatcher.d/99tlp-rdw-nm" = {
- source = "${tlp}/etc/NetworkManager/dispatcher.d/99tlp-rdw-nm";
- };
- };
-
- environment.systemPackages = [ tlp ];
-
- boot.kernelModules = [ "msr" ];
-
};
-
}
diff --git a/nixpkgs/nixos/modules/services/mail/dovecot.nix b/nixpkgs/nixos/modules/services/mail/dovecot.nix
index b5ed2c594f7..230a2ae3f82 100644
--- a/nixpkgs/nixos/modules/services/mail/dovecot.nix
+++ b/nixpkgs/nixos/modules/services/mail/dovecot.nix
@@ -14,18 +14,34 @@ let
base_dir = ${baseDir}
protocols = ${concatStringsSep " " cfg.protocols}
sendmail_path = /run/wrappers/bin/sendmail
+ # defining mail_plugins must be done before the first protocol {} filter because of https://doc.dovecot.org/configuration_manual/config_file/config_file_syntax/#variable-expansion
+ mail_plugins = $mail_plugins ${concatStringsSep " " cfg.mailPlugins.globally.enable}
''
- (if cfg.sslServerCert == null then ''
- ssl = no
- disable_plaintext_auth = no
- '' else ''
- ssl_cert = <${cfg.sslServerCert}
- ssl_key = <${cfg.sslServerKey}
- ${optionalString (cfg.sslCACert != null) ("ssl_ca = <" + cfg.sslCACert)}
- ssl_dh = <${config.security.dhparams.params.dovecot2.path}
- disable_plaintext_auth = yes
- '')
+ (
+ concatStringsSep "\n" (
+ mapAttrsToList (
+ protocol: plugins: ''
+ protocol ${protocol} {
+ mail_plugins = $mail_plugins ${concatStringsSep " " plugins.enable}
+ }
+ ''
+ ) cfg.mailPlugins.perProtocol
+ )
+ )
+
+ (
+ if cfg.sslServerCert == null then ''
+ ssl = no
+ disable_plaintext_auth = no
+ '' else ''
+ ssl_cert = <${cfg.sslServerCert}
+ ssl_key = <${cfg.sslServerKey}
+ ${optionalString (cfg.sslCACert != null) ("ssl_ca = <" + cfg.sslCACert)}
+ ssl_dh = <${config.security.dhparams.params.dovecot2.path}
+ disable_plaintext_auth = yes
+ ''
+ )
''
default_internal_user = ${cfg.user}
@@ -45,55 +61,58 @@ let
}
''
- (optionalString cfg.enablePAM ''
- userdb {
- driver = passwd
- }
-
- passdb {
- driver = pam
- args = ${optionalString cfg.showPAMFailure "failure_show_msg=yes"} dovecot2
- }
- '')
+ (
+ optionalString cfg.enablePAM ''
+ userdb {
+ driver = passwd
+ }
- (optionalString (cfg.sieveScripts != {}) ''
- plugin {
- ${concatStringsSep "\n" (mapAttrsToList (to: from: "sieve_${to} = ${stateDir}/sieve/${to}") cfg.sieveScripts)}
- }
- '')
+ passdb {
+ driver = pam
+ args = ${optionalString cfg.showPAMFailure "failure_show_msg=yes"} dovecot2
+ }
+ ''
+ )
- (optionalString (cfg.mailboxes != []) ''
- protocol imap {
- namespace inbox {
- inbox=yes
- ${concatStringsSep "\n" (map mailboxConfig cfg.mailboxes)}
+ (
+ optionalString (cfg.sieveScripts != {}) ''
+ plugin {
+ ${concatStringsSep "\n" (mapAttrsToList (to: from: "sieve_${to} = ${stateDir}/sieve/${to}") cfg.sieveScripts)}
}
- }
- '')
-
- (optionalString cfg.enableQuota ''
- mail_plugins = $mail_plugins quota
- service quota-status {
- executable = ${dovecotPkg}/libexec/dovecot/quota-status -p postfix
- inet_listener {
- port = ${cfg.quotaPort}
+ ''
+ )
+
+ (
+ optionalString (cfg.mailboxes != []) ''
+ protocol imap {
+ namespace inbox {
+ inbox=yes
+ ${concatStringsSep "\n" (map mailboxConfig cfg.mailboxes)}
+ }
+ }
+ ''
+ )
+
+ (
+ optionalString cfg.enableQuota ''
+ service quota-status {
+ executable = ${dovecotPkg}/libexec/dovecot/quota-status -p postfix
+ inet_listener {
+ port = ${cfg.quotaPort}
+ }
+ client_limit = 1
}
- client_limit = 1
- }
-
- protocol imap {
- mail_plugins = $mail_plugins imap_quota
- }
- plugin {
- quota_rule = *:storage=${cfg.quotaGlobalPerUser}
- quota = maildir:User quota # per virtual mail user quota # BUG/FIXME broken, we couldn't get this working
- quota_status_success = DUNNO
- quota_status_nouser = DUNNO
- quota_status_overquota = "552 5.2.2 Mailbox is full"
- quota_grace = 10%%
- }
- '')
+ plugin {
+ quota_rule = *:storage=${cfg.quotaGlobalPerUser}
+ quota = maildir:User quota # per virtual mail user quota # BUG/FIXME broken, we couldn't get this working
+ quota_status_success = DUNNO
+ quota_status_nouser = DUNNO
+ quota_status_overquota = "552 5.2.2 Mailbox is full"
+ quota_grace = 10%%
+ }
+ ''
+ )
cfg.extraConfig
];
@@ -107,7 +126,7 @@ let
mailbox "${mailbox.name}" {
auto = ${toString mailbox.auto}
'' + optionalString (mailbox.specialUse != null) ''
- special_use = \${toString mailbox.specialUse}
+ special_use = \${toString mailbox.specialUse}
'' + "}";
mailboxes = { ... }: {
@@ -160,7 +179,7 @@ in
protocols = mkOption {
type = types.listOf types.str;
- default = [ ];
+ default = [];
description = "Additional listeners to start when Dovecot is enabled.";
};
@@ -183,6 +202,43 @@ in
description = "Additional entries to put verbatim into Dovecot's config file.";
};
+ mailPlugins =
+ let
+ plugins = hint: types.submodule {
+ options = {
+ enable = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ description = "mail plugins to enable as a list of strings to append to the ${hint} <literal>$mail_plugins</literal> configuration variable";
+ };
+ };
+ };
+ in
+ mkOption {
+ type = with types; submodule {
+ options = {
+ globally = mkOption {
+ description = "Additional entries to add to the mail_plugins variable for all protocols";
+ type = plugins "top-level";
+ example = { enable = [ "virtual" ]; };
+ default = { enable = []; };
+ };
+ perProtocol = mkOption {
+ description = "Additional entries to add to the mail_plugins variable, per protocol";
+ type = attrsOf (plugins "corresponding per-protocol");
+ default = {};
+ example = { imap = [ "imap_acl" ]; };
+ };
+ };
+ };
+ description = "Additional entries to add to the mail_plugins variable, globally and per protocol";
+ example = {
+ globally.enable = [ "acl" ];
+ perProtocol.imap.enable = [ "imap_acl" ];
+ };
+ default = { globally.enable = []; perProtocol = {}; };
+ };
+
configFile = mkOption {
type = types.nullOr types.path;
default = null;
@@ -305,27 +361,33 @@ in
enable = true;
params.dovecot2 = {};
};
- services.dovecot2.protocols =
- optional cfg.enableImap "imap"
- ++ optional cfg.enablePop3 "pop3"
- ++ optional cfg.enableLmtp "lmtp";
+ services.dovecot2.protocols =
+ optional cfg.enableImap "imap"
+ ++ optional cfg.enablePop3 "pop3"
+ ++ optional cfg.enableLmtp "lmtp";
+
+ services.dovecot2.mailPlugins = mkIf cfg.enableQuota {
+ globally.enable = [ "quota" ];
+ perProtocol.imap.enable = [ "imap_quota" ];
+ };
users.users = {
dovenull =
- { uid = config.ids.uids.dovenull2;
+ {
+ uid = config.ids.uids.dovenull2;
description = "Dovecot user for untrusted logins";
group = "dovenull";
};
} // optionalAttrs (cfg.user == "dovecot2") {
dovecot2 =
- { uid = config.ids.uids.dovecot2;
- description = "Dovecot user";
- group = cfg.group;
- };
+ {
+ uid = config.ids.uids.dovecot2;
+ description = "Dovecot user";
+ group = cfg.group;
+ };
} // optionalAttrs (cfg.createMailUser && cfg.mailUser != null) {
${cfg.mailUser} =
- { description = "Virtual Mail User"; } //
- optionalAttrs (cfg.mailGroup != null)
+ { description = "Virtual Mail User"; } // optionalAttrs (cfg.mailGroup != null)
{ group = cfg.mailGroup; };
};
@@ -334,7 +396,7 @@ in
} // optionalAttrs (cfg.group == "dovecot2") {
dovecot2.gid = config.ids.gids.dovecot2;
} // optionalAttrs (cfg.createMailUser && cfg.mailGroup != null) {
- ${cfg.mailGroup} = { };
+ ${cfg.mailGroup} = {};
};
environment.etc."dovecot/modules".source = modulesDir;
@@ -363,15 +425,19 @@ in
rm -rf ${stateDir}/sieve
'' + optionalString (cfg.sieveScripts != {}) ''
mkdir -p ${stateDir}/sieve
- ${concatStringsSep "\n" (mapAttrsToList (to: from: ''
- if [ -d '${from}' ]; then
- mkdir '${stateDir}/sieve/${to}'
- cp -p "${from}/"*.sieve '${stateDir}/sieve/${to}'
- else
- cp -p '${from}' '${stateDir}/sieve/${to}'
- fi
- ${pkgs.dovecot_pigeonhole}/bin/sievec '${stateDir}/sieve/${to}'
- '') cfg.sieveScripts)}
+ ${concatStringsSep "\n" (
+ mapAttrsToList (
+ to: from: ''
+ if [ -d '${from}' ]; then
+ mkdir '${stateDir}/sieve/${to}'
+ cp -p "${from}/"*.sieve '${stateDir}/sieve/${to}'
+ else
+ cp -p '${from}' '${stateDir}/sieve/${to}'
+ fi
+ ${pkgs.dovecot_pigeonhole}/bin/sievec '${stateDir}/sieve/${to}'
+ ''
+ ) cfg.sieveScripts
+ )}
chown -R '${cfg.mailUser}:${cfg.mailGroup}' '${stateDir}/sieve'
'';
};
@@ -379,17 +445,21 @@ in
environment.systemPackages = [ dovecotPkg ];
assertions = [
- { assertion = intersectLists cfg.protocols [ "pop3" "imap" ] != [];
+ {
+ assertion = intersectLists cfg.protocols [ "pop3" "imap" ] != [];
message = "dovecot needs at least one of the IMAP or POP3 listeners enabled";
}
- { assertion = (cfg.sslServerCert == null) == (cfg.sslServerKey == null)
- && (cfg.sslCACert != null -> !(cfg.sslServerCert == null || cfg.sslServerKey == null));
+ {
+ assertion = (cfg.sslServerCert == null) == (cfg.sslServerKey == null)
+ && (cfg.sslCACert != null -> !(cfg.sslServerCert == null || cfg.sslServerKey == null));
message = "dovecot needs both sslServerCert and sslServerKey defined for working crypto";
}
- { assertion = cfg.showPAMFailure -> cfg.enablePAM;
+ {
+ assertion = cfg.showPAMFailure -> cfg.enablePAM;
message = "dovecot is configured with showPAMFailure while enablePAM is disabled";
}
- { assertion = cfg.sieveScripts != {} -> (cfg.mailUser != null && cfg.mailGroup != null);
+ {
+ assertion = cfg.sieveScripts != {} -> (cfg.mailUser != null && cfg.mailGroup != null);
message = "dovecot requires mailUser and mailGroup to be set when sieveScripts is set";
}
];
diff --git a/nixpkgs/nixos/modules/services/mail/mailman.nix b/nixpkgs/nixos/modules/services/mail/mailman.nix
index 43dc185cdd7..f5e78b18293 100644
--- a/nixpkgs/nixos/modules/services/mail/mailman.nix
+++ b/nixpkgs/nixos/modules/services/mail/mailman.nix
@@ -265,6 +265,11 @@ in {
'';
serviceConfig = {
Type = "oneshot";
+ # RemainAfterExit makes restartIfChanged work for this service, so
+ # downstream services will get updated automatically when things like
+ # services.mailman.hyperkitty.baseUrl change. Otherwise users have to
+ # restart things manually, which is confusing.
+ RemainAfterExit = "yes";
};
};
@@ -282,6 +287,9 @@ in {
serviceConfig = {
User = cfg.webUser;
Type = "oneshot";
+ # Similar to mailman-settings.service, this makes restartTriggers work
+ # properly for this service.
+ RemainAfterExit = "yes";
WorkingDirectory = "/var/lib/mailman-web";
};
};
diff --git a/nixpkgs/nixos/modules/services/mail/sympa.nix b/nixpkgs/nixos/modules/services/mail/sympa.nix
new file mode 100644
index 00000000000..c3ae9d4255b
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/mail/sympa.nix
@@ -0,0 +1,596 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.sympa;
+ dataDir = "/var/lib/sympa";
+ user = "sympa";
+ group = "sympa";
+ pkg = pkgs.sympa;
+ fqdns = attrNames cfg.domains;
+ usingNginx = cfg.web.enable && cfg.web.server == "nginx";
+ mysqlLocal = cfg.database.createLocally && cfg.database.type == "MySQL";
+ pgsqlLocal = cfg.database.createLocally && cfg.database.type == "PostgreSQL";
+
+ sympaSubServices = [
+ "sympa-archive.service"
+ "sympa-bounce.service"
+ "sympa-bulk.service"
+ "sympa-task.service"
+ ];
+
+ # common for all services including wwsympa
+ commonServiceConfig = {
+ StateDirectory = "sympa";
+ ProtectHome = true;
+ ProtectSystem = "full";
+ ProtectKernelTunables = true;
+ ProtectKernelModules = true;
+ ProtectControlGroups = true;
+ };
+
+ # wwsympa has its own service config
+ sympaServiceConfig = srv: {
+ Type = "simple";
+ Restart = "always";
+ ExecStart = "${pkg}/bin/${srv}.pl --foreground";
+ PIDFile = "/run/sympa/${srv}.pid";
+ User = user;
+ Group = group;
+
+ # avoid duplicating log messageges in journal
+ StandardError = "null";
+ } // commonServiceConfig;
+
+ configVal = value:
+ if isBool value then
+ if value then "on" else "off"
+ else toString value;
+ configGenerator = c: concatStrings (flip mapAttrsToList c (key: val: "${key}\t${configVal val}\n"));
+
+ mainConfig = pkgs.writeText "sympa.conf" (configGenerator cfg.settings);
+ robotConfig = fqdn: domain: pkgs.writeText "${fqdn}-robot.conf" (configGenerator domain.settings);
+
+ transport = pkgs.writeText "transport.sympa" (concatStringsSep "\n" (flip map fqdns (domain: ''
+ ${domain} error:User unknown in recipient table
+ sympa@${domain} sympa:sympa@${domain}
+ listmaster@${domain} sympa:listmaster@${domain}
+ bounce@${domain} sympabounce:sympa@${domain}
+ abuse-feedback-report@${domain} sympabounce:sympa@${domain}
+ '')));
+
+ virtual = pkgs.writeText "virtual.sympa" (concatStringsSep "\n" (flip map fqdns (domain: ''
+ sympa-request@${domain} postmaster@localhost
+ sympa-owner@${domain} postmaster@localhost
+ '')));
+
+ listAliases = pkgs.writeText "list_aliases.tt2" ''
+ #--- [% list.name %]@[% list.domain %]: list transport map created at [% date %]
+ [% list.name %]@[% list.domain %] sympa:[% list.name %]@[% list.domain %]
+ [% list.name %]-request@[% list.domain %] sympa:[% list.name %]-request@[% list.domain %]
+ [% list.name %]-editor@[% list.domain %] sympa:[% list.name %]-editor@[% list.domain %]
+ #[% list.name %]-subscribe@[% list.domain %] sympa:[% list.name %]-subscribe@[%list.domain %]
+ [% list.name %]-unsubscribe@[% list.domain %] sympa:[% list.name %]-unsubscribe@[% list.domain %]
+ [% list.name %][% return_path_suffix %]@[% list.domain %] sympabounce:[% list.name %]@[% list.domain %]
+ '';
+
+ enabledFiles = filterAttrs (n: v: v.enable) cfg.settingsFile;
+in
+{
+
+ ###### interface
+ options.services.sympa = with types; {
+
+ enable = mkEnableOption "Sympa mailing list manager";
+
+ lang = mkOption {
+ type = str;
+ default = "en_US";
+ example = "cs";
+ description = ''
+ Default Sympa language.
+ See <link xlink:href='https://github.com/sympa-community/sympa/tree/sympa-6.2/po/sympa' />
+ for available options.
+ '';
+ };
+
+ listMasters = mkOption {
+ type = listOf str;
+ example = [ "postmaster@sympa.example.org" ];
+ description = ''
+ The list of the email addresses of the listmasters
+ (users authorized to perform global server commands).
+ '';
+ };
+
+ mainDomain = mkOption {
+ type = nullOr str;
+ default = null;
+ example = "lists.example.org";
+ description = ''
+ Main domain to be used in <filename>sympa.conf</filename>.
+ If <literal>null</literal>, one of the <option>services.sympa.domains</option> is chosen for you.
+ '';
+ };
+
+ domains = mkOption {
+ type = attrsOf (submodule ({ name, config, ... }: {
+ options = {
+ webHost = mkOption {
+ type = nullOr str;
+ default = null;
+ example = "archive.example.org";
+ description = ''
+ Domain part of the web interface URL (no web interface for this domain if <literal>null</literal>).
+ DNS record of type A (or AAAA or CNAME) has to exist with this value.
+ '';
+ };
+ webLocation = mkOption {
+ type = str;
+ default = "/";
+ example = "/sympa";
+ description = "URL path part of the web interface.";
+ };
+ settings = mkOption {
+ type = attrsOf (oneOf [ str int bool ]);
+ default = {};
+ example = {
+ default_max_list_members = 3;
+ };
+ description = ''
+ The <filename>robot.conf</filename> configuration file as key value set.
+ See <link xlink:href='https://sympa-community.github.io/gpldoc/man/sympa.conf.5.html' />
+ for list of configuration parameters.
+ '';
+ };
+ };
+
+ config.settings = mkIf (cfg.web.enable && config.webHost != null) {
+ wwsympa_url = mkDefault "https://${config.webHost}${strings.removeSuffix "/" config.webLocation}";
+ };
+ }));
+
+ description = ''
+ Email domains handled by this instance. There have
+ to be MX records for keys of this attribute set.
+ '';
+ example = literalExample ''
+ {
+ "lists.example.org" = {
+ webHost = "lists.example.org";
+ webLocation = "/";
+ };
+ "sympa.example.com" = {
+ webHost = "example.com";
+ webLocation = "/sympa";
+ };
+ }
+ '';
+ };
+
+ database = {
+ type = mkOption {
+ type = enum [ "SQLite" "PostgreSQL" "MySQL" ];
+ default = "SQLite";
+ example = "MySQL";
+ description = "Database engine to use.";
+ };
+
+ host = mkOption {
+ type = nullOr str;
+ default = null;
+ description = ''
+ Database host address.
+
+ For MySQL, use <literal>localhost</literal> to connect using Unix domain socket.
+
+ For PostgreSQL, use path to directory (e.g. <filename>/run/postgresql</filename>)
+ to connect using Unix domain socket located in this directory.
+
+ Use <literal>null</literal> to fall back on Sympa default, or when using
+ <option>services.sympa.database.createLocally</option>.
+ '';
+ };
+
+ port = mkOption {
+ type = nullOr port;
+ default = null;
+ description = "Database port. Use <literal>null</literal> for default port.";
+ };
+
+ name = mkOption {
+ type = str;
+ default = if cfg.database.type == "SQLite" then "${dataDir}/sympa.sqlite" else "sympa";
+ defaultText = ''if database.type == "SQLite" then "${dataDir}/sympa.sqlite" else "sympa"'';
+ description = ''
+ Database name. When using SQLite this must be an absolute
+ path to the database file.
+ '';
+ };
+
+ user = mkOption {
+ type = nullOr str;
+ default = user;
+ description = "Database user. The system user name is used as a default.";
+ };
+
+ passwordFile = mkOption {
+ type = nullOr path;
+ default = null;
+ example = "/run/keys/sympa-dbpassword";
+ description = ''
+ A file containing the password for <option>services.sympa.database.user</option>.
+ '';
+ };
+
+ createLocally = mkOption {
+ type = bool;
+ default = true;
+ description = "Whether to create a local database automatically.";
+ };
+ };
+
+ web = {
+ enable = mkOption {
+ type = bool;
+ default = true;
+ description = "Whether to enable Sympa web interface.";
+ };
+
+ server = mkOption {
+ type = enum [ "nginx" "none" ];
+ default = "nginx";
+ description = ''
+ The webserver used for the Sympa web interface. Set it to `none` if you want to configure it yourself.
+ Further nginx configuration can be done by adapting
+ <option>services.nginx.virtualHosts.<replaceable>name</replaceable></option>.
+ '';
+ };
+
+ https = mkOption {
+ type = bool;
+ default = true;
+ description = ''
+ Whether to use HTTPS. When nginx integration is enabled, this option forces SSL and enables ACME.
+ Please note that Sympa web interface always uses https links even when this option is disabled.
+ '';
+ };
+
+ fcgiProcs = mkOption {
+ type = ints.positive;
+ default = 2;
+ description = "Number of FastCGI processes to fork.";
+ };
+ };
+
+ mta = {
+ type = mkOption {
+ type = enum [ "postfix" "none" ];
+ default = "postfix";
+ description = ''
+ Mail transfer agent (MTA) integration. Use <literal>none</literal> if you want to configure it yourself.
+
+ The <literal>postfix</literal> integration sets up local Postfix instance that will pass incoming
+ messages from configured domains to Sympa. You still need to configure at least outgoing message
+ handling using e.g. <option>services.postfix.relayHost</option>.
+ '';
+ };
+ };
+
+ settings = mkOption {
+ type = attrsOf (oneOf [ str int bool ]);
+ default = {};
+ example = literalExample ''
+ {
+ default_home = "lists";
+ viewlogs_page_size = 50;
+ }
+ '';
+ description = ''
+ The <filename>sympa.conf</filename> configuration file as key value set.
+ See <link xlink:href='https://sympa-community.github.io/gpldoc/man/sympa.conf.5.html' />
+ for list of configuration parameters.
+ '';
+ };
+
+ settingsFile = mkOption {
+ type = attrsOf (submodule ({ name, config, ... }: {
+ options = {
+ enable = mkOption {
+ type = bool;
+ default = true;
+ description = "Whether this file should be generated. This option allows specific files to be disabled.";
+ };
+ text = mkOption {
+ default = null;
+ type = nullOr lines;
+ description = "Text of the file.";
+ };
+ source = mkOption {
+ type = path;
+ description = "Path of the source file.";
+ };
+ };
+
+ config.source = mkIf (config.text != null) (mkDefault (pkgs.writeText "sympa-${baseNameOf name}" config.text));
+ }));
+ default = {};
+ example = literalExample ''
+ {
+ "list_data/lists.example.org/help" = {
+ text = "subject This list provides help to users";
+ };
+ }
+ '';
+ description = "Set of files to be linked in <filename>${dataDir}</filename>.";
+ };
+ };
+
+ ###### implementation
+
+ config = mkIf cfg.enable {
+
+ services.sympa.settings = (mapAttrs (_: v: mkDefault v) {
+ domain = if cfg.mainDomain != null then cfg.mainDomain else head fqdns;
+ listmaster = concatStringsSep "," cfg.listMasters;
+ lang = cfg.lang;
+
+ home = "${dataDir}/list_data";
+ arc_path = "${dataDir}/arc";
+ bounce_path = "${dataDir}/bounce";
+
+ sendmail = "${pkgs.system-sendmail}/bin/sendmail";
+
+ db_type = cfg.database.type;
+ db_name = cfg.database.name;
+ }
+ // (optionalAttrs (cfg.database.host != null) {
+ db_host = cfg.database.host;
+ })
+ // (optionalAttrs mysqlLocal {
+ db_host = "localhost"; # use unix domain socket
+ })
+ // (optionalAttrs pgsqlLocal {
+ db_host = "/run/postgresql"; # use unix domain socket
+ })
+ // (optionalAttrs (cfg.database.port != null) {
+ db_port = cfg.database.port;
+ })
+ // (optionalAttrs (cfg.database.user != null) {
+ db_user = cfg.database.user;
+ })
+ // (optionalAttrs (cfg.mta.type == "postfix") {
+ sendmail_aliases = "${dataDir}/sympa_transport";
+ aliases_program = "${pkgs.postfix}/bin/postmap";
+ aliases_db_type = "hash";
+ })
+ // (optionalAttrs cfg.web.enable {
+ static_content_path = "${dataDir}/static_content";
+ css_path = "${dataDir}/static_content/css";
+ pictures_path = "${dataDir}/static_content/pictures";
+ mhonarc = "${pkgs.perlPackages.MHonArc}/bin/mhonarc";
+ }));
+
+ services.sympa.settingsFile = {
+ "virtual.sympa" = mkDefault { source = virtual; };
+ "transport.sympa" = mkDefault { source = transport; };
+ "etc/list_aliases.tt2" = mkDefault { source = listAliases; };
+ }
+ // (flip mapAttrs' cfg.domains (fqdn: domain:
+ nameValuePair "etc/${fqdn}/robot.conf" (mkDefault { source = robotConfig fqdn domain; })));
+
+ environment = {
+ systemPackages = [ pkg ];
+ };
+
+ users.users.${user} = {
+ description = "Sympa mailing list manager user";
+ group = group;
+ home = dataDir;
+ createHome = false;
+ isSystemUser = true;
+ };
+
+ users.groups.${group} = {};
+
+ assertions = [
+ { assertion = cfg.database.createLocally -> cfg.database.user == user;
+ message = "services.sympa.database.user must be set to ${user} if services.sympa.database.createLocally is set to true";
+ }
+ { assertion = cfg.database.createLocally -> cfg.database.passwordFile == null;
+ message = "a password cannot be specified if services.sympa.database.createLocally is set to true";
+ }
+ ];
+
+ systemd.tmpfiles.rules = [
+ "d ${dataDir} 0711 ${user} ${group} - -"
+ "d ${dataDir}/etc 0700 ${user} ${group} - -"
+ "d ${dataDir}/spool 0700 ${user} ${group} - -"
+ "d ${dataDir}/list_data 0700 ${user} ${group} - -"
+ "d ${dataDir}/arc 0700 ${user} ${group} - -"
+ "d ${dataDir}/bounce 0700 ${user} ${group} - -"
+ "f ${dataDir}/sympa_transport 0600 ${user} ${group} - -"
+
+ # force-copy static_content so it's up to date with package
+ # set permissions for wwsympa which needs write access (...)
+ "R ${dataDir}/static_content - - - - -"
+ "C ${dataDir}/static_content 0711 ${user} ${group} - ${pkg}/static_content"
+ "e ${dataDir}/static_content/* 0711 ${user} ${group} - -"
+
+ "d /run/sympa 0755 ${user} ${group} - -"
+ ]
+ ++ (flip concatMap fqdns (fqdn: [
+ "d ${dataDir}/etc/${fqdn} 0700 ${user} ${group} - -"
+ "d ${dataDir}/list_data/${fqdn} 0700 ${user} ${group} - -"
+ ]))
+ #++ (flip mapAttrsToList enabledFiles (k: v:
+ # "L+ ${dataDir}/${k} - - - - ${v.source}"
+ #))
+ ++ (concatLists (flip mapAttrsToList enabledFiles (k: v: [
+ # sympa doesn't handle symlinks well (e.g. fails to create locks)
+ # force-copy instead
+ "R ${dataDir}/${k} - - - - -"
+ "C ${dataDir}/${k} 0700 ${user} ${group} - ${v.source}"
+ ])));
+
+ systemd.services.sympa = {
+ description = "Sympa mailing list manager";
+
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network-online.target" ];
+ wants = sympaSubServices;
+ before = sympaSubServices;
+ serviceConfig = sympaServiceConfig "sympa_msg";
+
+ preStart = ''
+ umask 0077
+
+ cp -f ${mainConfig} ${dataDir}/etc/sympa.conf
+ ${optionalString (cfg.database.passwordFile != null) ''
+ chmod u+w ${dataDir}/etc/sympa.conf
+ echo -n "db_passwd " >> ${dataDir}/etc/sympa.conf
+ cat ${cfg.database.passwordFile} >> ${dataDir}/etc/sympa.conf
+ ''}
+
+ ${optionalString (cfg.mta.type == "postfix") ''
+ ${pkgs.postfix}/bin/postmap hash:${dataDir}/virtual.sympa
+ ${pkgs.postfix}/bin/postmap hash:${dataDir}/transport.sympa
+ ''}
+ ${pkg}/bin/sympa_newaliases.pl
+ ${pkg}/bin/sympa.pl --health_check
+ '';
+ };
+ systemd.services.sympa-archive = {
+ description = "Sympa mailing list manager (archiving)";
+ bindsTo = [ "sympa.service" ];
+ serviceConfig = sympaServiceConfig "archived";
+ };
+ systemd.services.sympa-bounce = {
+ description = "Sympa mailing list manager (bounce processing)";
+ bindsTo = [ "sympa.service" ];
+ serviceConfig = sympaServiceConfig "bounced";
+ };
+ systemd.services.sympa-bulk = {
+ description = "Sympa mailing list manager (message distribution)";
+ bindsTo = [ "sympa.service" ];
+ serviceConfig = sympaServiceConfig "bulk";
+ };
+ systemd.services.sympa-task = {
+ description = "Sympa mailing list manager (task management)";
+ bindsTo = [ "sympa.service" ];
+ serviceConfig = sympaServiceConfig "task_manager";
+ };
+
+ systemd.services.wwsympa = mkIf usingNginx {
+ wantedBy = [ "multi-user.target" ];
+ after = [ "sympa.service" ];
+ serviceConfig = {
+ Type = "forking";
+ PIDFile = "/run/sympa/wwsympa.pid";
+ Restart = "always";
+ ExecStart = ''${pkgs.spawn_fcgi}/bin/spawn-fcgi \
+ -u ${user} \
+ -g ${group} \
+ -U nginx \
+ -M 0600 \
+ -F ${toString cfg.web.fcgiProcs} \
+ -P /run/sympa/wwsympa.pid \
+ -s /run/sympa/wwsympa.socket \
+ -- ${pkg}/bin/wwsympa.fcgi
+ '';
+
+ } // commonServiceConfig;
+ };
+
+ services.nginx.enable = mkIf usingNginx true;
+ services.nginx.virtualHosts = mkIf usingNginx (let
+ vHosts = unique (remove null (mapAttrsToList (_k: v: v.webHost) cfg.domains));
+ hostLocations = host: map (v: v.webLocation) (filter (v: v.webHost == host) (attrValues cfg.domains));
+ httpsOpts = optionalAttrs cfg.web.https { forceSSL = mkDefault true; enableACME = mkDefault true; };
+ in
+ genAttrs vHosts (host: {
+ locations = genAttrs (hostLocations host) (loc: {
+ extraConfig = ''
+ include ${config.services.nginx.package}/conf/fastcgi_params;
+
+ fastcgi_pass unix:/run/sympa/wwsympa.socket;
+ fastcgi_split_path_info ^(${loc})(.*)$;
+
+ fastcgi_param PATH_INFO $fastcgi_path_info;
+ fastcgi_param SCRIPT_FILENAME ${pkg}/bin/wwsympa.fcgi;
+ '';
+ }) // {
+ "/static-sympa/".alias = "${dataDir}/static_content/";
+ };
+ } // httpsOpts));
+
+ services.postfix = mkIf (cfg.mta.type == "postfix") {
+ enable = true;
+ recipientDelimiter = "+";
+ config = {
+ virtual_alias_maps = [ "hash:${dataDir}/virtual.sympa" ];
+ virtual_mailbox_maps = [
+ "hash:${dataDir}/transport.sympa"
+ "hash:${dataDir}/sympa_transport"
+ "hash:${dataDir}/virtual.sympa"
+ ];
+ virtual_mailbox_domains = [ "hash:${dataDir}/transport.sympa" ];
+ transport_maps = [
+ "hash:${dataDir}/transport.sympa"
+ "hash:${dataDir}/sympa_transport"
+ ];
+ };
+ masterConfig = {
+ "sympa" = {
+ type = "unix";
+ privileged = true;
+ chroot = false;
+ command = "pipe";
+ args = [
+ "flags=hqRu"
+ "user=${user}"
+ "argv=${pkg}/bin/queue"
+ "\${nexthop}"
+ ];
+ };
+ "sympabounce" = {
+ type = "unix";
+ privileged = true;
+ chroot = false;
+ command = "pipe";
+ args = [
+ "flags=hqRu"
+ "user=${user}"
+ "argv=${pkg}/bin/bouncequeue"
+ "\${nexthop}"
+ ];
+ };
+ };
+ };
+
+ services.mysql = optionalAttrs mysqlLocal {
+ enable = true;
+ package = mkDefault pkgs.mariadb;
+ ensureDatabases = [ cfg.database.name ];
+ ensureUsers = [
+ { name = cfg.database.user;
+ ensurePermissions = { "${cfg.database.name}.*" = "ALL PRIVILEGES"; };
+ }
+ ];
+ };
+
+ services.postgresql = optionalAttrs pgsqlLocal {
+ enable = true;
+ ensureDatabases = [ cfg.database.name ];
+ ensureUsers = [
+ { name = cfg.database.user;
+ ensurePermissions = { "DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; };
+ }
+ ];
+ };
+
+ };
+
+ meta.maintainers = with maintainers; [ mmilata sorki ];
+}
diff --git a/nixpkgs/nixos/modules/services/misc/ankisyncd.nix b/nixpkgs/nixos/modules/services/misc/ankisyncd.nix
new file mode 100644
index 00000000000..5fc19649d3d
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/misc/ankisyncd.nix
@@ -0,0 +1,79 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.ankisyncd;
+
+ name = "ankisyncd";
+
+ stateDir = "/var/lib/${name}";
+
+ authDbPath = "${stateDir}/auth.db";
+
+ sessionDbPath = "${stateDir}/session.db";
+
+ configFile = pkgs.writeText "ankisyncd.conf" (lib.generators.toINI {} {
+ sync_app = {
+ host = cfg.host;
+ port = cfg.port;
+ data_root = stateDir;
+ auth_db_path = authDbPath;
+ session_db_path = sessionDbPath;
+
+ base_url = "/sync/";
+ base_media_url = "/msync/";
+ };
+ });
+in
+ {
+ options.services.ankisyncd = {
+ enable = mkEnableOption "ankisyncd";
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.ankisyncd;
+ defaultText = literalExample "pkgs.ankisyncd";
+ description = "The package to use for the ankisyncd command.";
+ };
+
+ host = mkOption {
+ type = types.str;
+ default = "localhost";
+ description = "ankisyncd host";
+ };
+
+ port = mkOption {
+ type = types.int;
+ default = 27701;
+ description = "ankisyncd port";
+ };
+
+ openFirewall = mkOption {
+ default = false;
+ type = types.bool;
+ description = "Whether to open the firewall for the specified port.";
+ };
+ };
+
+ config = mkIf cfg.enable {
+ networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ];
+
+ environment.etc."ankisyncd/ankisyncd.conf".source = configFile;
+
+ systemd.services.ankisyncd = {
+ description = "ankisyncd - Anki sync server";
+ after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ path = [ cfg.package ];
+
+ serviceConfig = {
+ Type = "simple";
+ DynamicUser = true;
+ StateDirectory = name;
+ ExecStart = "${cfg.package}/bin/ankisyncd";
+ Restart = "always";
+ };
+ };
+ };
+ }
diff --git a/nixpkgs/nixos/modules/services/misc/autorandr.nix b/nixpkgs/nixos/modules/services/misc/autorandr.nix
index 4708e16e2a6..cf7fb5f78d3 100644
--- a/nixpkgs/nixos/modules/services/misc/autorandr.nix
+++ b/nixpkgs/nixos/modules/services/misc/autorandr.nix
@@ -48,5 +48,5 @@ in {
};
- meta.maintainers = with maintainers; [ gnidorah ma27 ];
+ meta.maintainers = with maintainers; [ gnidorah ];
}
diff --git a/nixpkgs/nixos/modules/services/misc/disnix.nix b/nixpkgs/nixos/modules/services/misc/disnix.nix
index c21cb2afc3c..b7b6eb7cd66 100644
--- a/nixpkgs/nixos/modules/services/misc/disnix.nix
+++ b/nixpkgs/nixos/modules/services/misc/disnix.nix
@@ -61,10 +61,7 @@ in
++ optional cfg.useWebServiceInterface "${pkgs.dbus_java}/share/java/dbus.jar";
services.tomcat.webapps = optional cfg.useWebServiceInterface pkgs.DisnixWebService;
- users.groups = singleton
- { name = "disnix";
- gid = config.ids.gids.disnix;
- };
+ users.groups.disnix.gid = config.ids.gids.disnix;
systemd.services = {
disnix = mkIf cfg.enableMultiUser {
diff --git a/nixpkgs/nixos/modules/services/misc/folding-at-home.nix b/nixpkgs/nixos/modules/services/misc/folding-at-home.nix
deleted file mode 100644
index fd2ea3948f6..00000000000
--- a/nixpkgs/nixos/modules/services/misc/folding-at-home.nix
+++ /dev/null
@@ -1,67 +0,0 @@
-{ config, lib, pkgs, ... }:
-with lib;
-let
- stateDir = "/var/lib/foldingathome";
- cfg = config.services.foldingAtHome;
- fahUser = "foldingathome";
-in {
-
- ###### interface
-
- options = {
-
- services.foldingAtHome = {
-
- enable = mkOption {
- default = false;
- description = ''
- Whether to enable the Folding@Home to use idle CPU time.
- '';
- };
-
- nickname = mkOption {
- default = "Anonymous";
- description = ''
- A unique handle for statistics.
- '';
- };
-
- config = mkOption {
- default = "";
- description = ''
- Extra configuration. Contents will be added verbatim to the
- configuration file.
- '';
- };
-
- };
-
- };
-
- ###### implementation
-
- config = mkIf cfg.enable {
-
- users.users.${fahUser} =
- { uid = config.ids.uids.foldingathome;
- description = "Folding@Home user";
- home = stateDir;
- };
-
- systemd.services.foldingathome = {
- after = [ "network.target" ];
- wantedBy = [ "multi-user.target" ];
- preStart = ''
- mkdir -m 0755 -p ${stateDir}
- chown ${fahUser} ${stateDir}
- cp -f ${pkgs.writeText "client.cfg" cfg.config} ${stateDir}/client.cfg
- '';
- script = "${pkgs.su}/bin/su -s ${pkgs.runtimeShell} ${fahUser} -c 'cd ${stateDir}; ${pkgs.foldingathome}/bin/fah6'";
- };
-
- services.foldingAtHome.config = ''
- [settings]
- username=${cfg.nickname}
- '';
- };
-}
diff --git a/nixpkgs/nixos/modules/services/misc/home-assistant.nix b/nixpkgs/nixos/modules/services/misc/home-assistant.nix
index d63f38e93b8..86033d02bf3 100644
--- a/nixpkgs/nixos/modules/services/misc/home-assistant.nix
+++ b/nixpkgs/nixos/modules/services/misc/home-assistant.nix
@@ -96,7 +96,20 @@ in {
config = mkOption {
default = null;
- type = with types; nullOr attrs;
+ # Migrate to new option types later: https://github.com/NixOS/nixpkgs/pull/75584
+ type = with lib.types; let
+ valueType = nullOr (oneOf [
+ bool
+ int
+ float
+ str
+ (lazyAttrsOf valueType)
+ (listOf valueType)
+ ]) // {
+ description = "Yaml value";
+ emptyValue.value = {};
+ };
+ in valueType;
example = literalExample ''
{
homeassistant = {
diff --git a/nixpkgs/nixos/modules/services/misc/matrix-synapse.nix b/nixpkgs/nixos/modules/services/misc/matrix-synapse.nix
index 750f4a292fb..d02fa13bb99 100644
--- a/nixpkgs/nixos/modules/services/misc/matrix-synapse.nix
+++ b/nixpkgs/nixos/modules/services/misc/matrix-synapse.nix
@@ -111,6 +111,9 @@ app_service_config_files: ${builtins.toJSON cfg.app_service_config_files}
${cfg.extraConfig}
'';
+
+ hasLocalPostgresDB = let args = cfg.database_args; in
+ usePostgresql && (!(args ? host) || (elem args.host [ "localhost" "127.0.0.1" "::1" ]));
in {
options = {
services.matrix-synapse = {
@@ -354,13 +357,6 @@ in {
The database engine name. Can be sqlite or psycopg2.
'';
};
- create_local_database = mkOption {
- type = types.bool;
- default = true;
- description = ''
- Whether to create a local database automatically.
- '';
- };
database_name = mkOption {
type = types.str;
default = "matrix-synapse";
@@ -657,6 +653,25 @@ in {
};
config = mkIf cfg.enable {
+ assertions = [
+ { assertion = hasLocalPostgresDB -> config.services.postgresql.enable;
+ message = ''
+ Cannot deploy matrix-synapse with a configuration for a local postgresql database
+ and a missing postgresql service. Since 20.03 it's mandatory to manually configure the
+ database (please read the thread in https://github.com/NixOS/nixpkgs/pull/80447 for
+ further reference).
+
+ If you
+ - try to deploy a fresh synapse, you need to configure the database yourself. An example
+ for this can be found in <nixpkgs/nixos/tests/matrix-synapse.nix>
+ - update your existing matrix-synapse instance, you simply need to add `services.postgresql.enable = true`
+ to your configuration.
+
+ For further information about this update, please read the release-notes of 20.03 carefully.
+ '';
+ }
+ ];
+
users.users.matrix-synapse = {
group = "matrix-synapse";
home = cfg.dataDir;
@@ -669,18 +684,9 @@ in {
gid = config.ids.gids.matrix-synapse;
};
- services.postgresql = mkIf (usePostgresql && cfg.create_local_database) {
- enable = mkDefault true;
- ensureDatabases = [ cfg.database_name ];
- ensureUsers = [{
- name = cfg.database_user;
- ensurePermissions = { "DATABASE \"${cfg.database_name}\"" = "ALL PRIVILEGES"; };
- }];
- };
-
systemd.services.matrix-synapse = {
description = "Synapse Matrix homeserver";
- after = [ "network.target" ] ++ lib.optional config.services.postgresql.enable "postgresql.service" ;
+ after = [ "network.target" ] ++ optional hasLocalPostgresDB "postgresql.service";
wantedBy = [ "multi-user.target" ];
preStart = ''
${cfg.package}/bin/homeserver \
@@ -709,6 +715,12 @@ in {
The `trusted_third_party_id_servers` option as been removed in `matrix-synapse` v1.4.0
as the behavior is now obsolete.
'')
+ (mkRemovedOptionModule [ "services" "matrix-synapse" "create_local_database" ] ''
+ Database configuration must be done manually. An exemplary setup is demonstrated in
+ <nixpkgs/nixos/tests/matrix-synapse.nix>
+ '')
];
+ meta.doc = ./matrix-synapse.xml;
+
}
diff --git a/nixpkgs/nixos/modules/services/misc/matrix-synapse.xml b/nixpkgs/nixos/modules/services/misc/matrix-synapse.xml
new file mode 100644
index 00000000000..053a3b2a563
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/misc/matrix-synapse.xml
@@ -0,0 +1,224 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ version="5.0"
+ xml:id="module-services-matrix">
+ <title>Matrix</title>
+ <para>
+ <link xlink:href="https://matrix.org/">Matrix</link> is an open standard for
+ interoperable, decentralised, real-time communication over IP. It can be used
+ to power Instant Messaging, VoIP/WebRTC signalling, Internet of Things
+ communication - or anywhere you need a standard HTTP API for publishing and
+ subscribing to data whilst tracking the conversation history.
+ </para>
+ <para>
+ This chapter will show you how to set up your own, self-hosted Matrix
+ homeserver using the Synapse reference homeserver, and how to serve your own
+ copy of the Riot web client. See the
+ <link xlink:href="https://matrix.org/docs/projects/try-matrix-now.html">Try
+ Matrix Now!</link> overview page for links to Riot Apps for Android and iOS,
+ desktop clients, as well as bridges to other networks and other projects
+ around Matrix.
+ </para>
+ <section xml:id="module-services-matrix-synapse">
+ <title>Synapse Homeserver</title>
+
+ <para>
+ <link xlink:href="https://github.com/matrix-org/synapse">Synapse</link> is
+ the reference homeserver implementation of Matrix from the core development
+ team at matrix.org. The following configuration example will set up a
+ synapse server for the <literal>example.org</literal> domain, served from
+ the host <literal>myhostname.example.org</literal>. For more information,
+ please refer to the
+ <link xlink:href="https://github.com/matrix-org/synapse#synapse-installation">
+ installation instructions of Synapse </link>.
+<programlisting>
+let
+ fqdn =
+ let
+ join = hostName: domain: hostName + optionalString (domain != null) ".${domain}";
+ in join config.networking.hostName config.networking.domain;
+in {
+ networking = {
+ <link linkend="opt-networking.hostName">hostName</link> = "myhostname";
+ <link linkend="opt-networking.domain">domain</link> = "example.org";
+ };
+ <link linkend="opt-networking.firewall.allowedTCPPorts">networking.firewall.allowedTCPPorts</link> = [ 80 443 ];
+
+ <link linkend="opt-services.postgresql.enable">services.postgresql.enable</link> = true;
+ <link linkend="opt-services.postgresql.initialScript">services.postgresql.initialScript</link> = ''
+ CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
+ CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
+ TEMPLATE template0
+ LC_COLLATE = "C"
+ LC_CTYPE = "C";
+ '';
+
+ services.nginx = {
+ <link linkend="opt-services.nginx.enable">enable</link> = true;
+ # only recommendedProxySettings and recommendedGzipSettings are strictly required,
+ # but the rest make sense as well
+ <link linkend="opt-services.nginx.recommendedTlsSettings">recommendedTlsSettings</link> = true;
+ <link linkend="opt-services.nginx.recommendedOptimisation">recommendedOptimisation</link> = true;
+ <link linkend="opt-services.nginx.recommendedGzipSettings">recommendedGzipSettings</link> = true;
+ <link linkend="opt-services.nginx.recommendedProxySettings">recommendedProxySettings</link> = true;
+
+ <link linkend="opt-services.nginx.virtualHosts">virtualHosts</link> = {
+ # This host section can be placed on a different host than the rest,
+ # i.e. to delegate from the host being accessible as ${config.networking.domain}
+ # to another host actually running the Matrix homeserver.
+ "${config.networking.domain}" = {
+ <link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.extraConfig">locations."= /.well-known/matrix/server".extraConfig</link> =
+ let
+ # use 443 instead of the default 8448 port to unite
+ # the client-server and server-server port for simplicity
+ server = { "m.server" = "${fqdn}:443"; };
+ in ''
+ add_header Content-Type application/json;
+ return 200 '${builtins.toJSON server}';
+ '';
+ <link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.extraConfig">locations."= /.well-known/matrix/client".extraConfig</link> =
+ let
+ client = {
+ "m.homeserver" = { "base_url" = "https://${fqdn}"; };
+ "m.identity_server" = { "base_url" = "https://vector.im"; };
+ };
+ # ACAO required to allow riot-web on any URL to request this json file
+ in ''
+ add_header Content-Type application/json;
+ add_header Access-Control-Allow-Origin *;
+ return 200 '${builtins.toJSON client}';
+ '';
+ };
+
+ # Reverse proxy for Matrix client-server and server-server communication
+ ${fqdn} = {
+ <link linkend="opt-services.nginx.virtualHosts._name_.enableACME">enableACME</link> = true;
+ <link linkend="opt-services.nginx.virtualHosts._name_.forceSSL">forceSSL</link> = true;
+
+ # Or do a redirect instead of the 404, or whatever is appropriate for you.
+ # But do not put a Matrix Web client here! See the Riot Web section below.
+ <link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.extraConfig">locations."/".extraConfig</link> = ''
+ return 404;
+ '';
+
+ # forward all Matrix API calls to the synapse Matrix homeserver
+ locations."/_matrix" = {
+ <link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.proxyPass">proxyPass</link> = "http://[::1]:8008"; # without a trailing /
+ };
+ };
+ };
+ };
+ services.matrix-synapse = {
+ <link linkend="opt-services.matrix-synapse.enable">enable</link> = true;
+ <link linkend="opt-services.matrix-synapse.server_name">server_name</link> = config.networking.domain;
+ <link linkend="opt-services.matrix-synapse.listeners">listeners</link> = [
+ {
+ <link linkend="opt-services.matrix-synapse.listeners._.port">port</link> = 8008;
+ <link linkend="opt-services.matrix-synapse.listeners._.bind_address">bind_address</link> = "::1";
+ <link linkend="opt-services.matrix-synapse.listeners._.type">type</link> = "http";
+ <link linkend="opt-services.matrix-synapse.listeners._.tls">tls</link> = false;
+ <link linkend="opt-services.matrix-synapse.listeners._.x_forwarded">x_forwarded</link> = true;
+ <link linkend="opt-services.matrix-synapse.listeners._.resources">resources</link> = [
+ {
+ <link linkend="opt-services.matrix-synapse.listeners._.resources._.names">names</link> = [ "client" "federation" ];
+ <link linkend="opt-services.matrix-synapse.listeners._.resources._.compress">compress</link> = false;
+ }
+ ];
+ }
+ ];
+ };
+};
+</programlisting>
+ </para>
+
+ <para>
+ If the <code>A</code> and <code>AAAA</code> DNS records on
+ <literal>example.org</literal> do not point on the same host as the records
+ for <code>myhostname.example.org</code>, you can easily move the
+ <code>/.well-known</code> virtualHost section of the code to the host that
+ is serving <literal>example.org</literal>, while the rest stays on
+ <literal>myhostname.example.org</literal> with no other changes required.
+ This pattern also allows to seamlessly move the homeserver from
+ <literal>myhostname.example.org</literal> to
+ <literal>myotherhost.example.org</literal> by only changing the
+ <code>/.well-known</code> redirection target.
+ </para>
+
+ <para>
+ If you want to run a server with public registration by anybody, you can
+ then enable <literal><link linkend="opt-services.matrix-synapse.enable_registration">services.matrix-synapse.enable_registration</link> =
+ true;</literal>. Otherwise, or you can generate a registration secret with
+ <command>pwgen -s 64 1</command> and set it with
+ <option><link linkend="opt-services.matrix-synapse.registration_shared_secret">services.matrix-synapse.registration_shared_secret</link></option>. To
+ create a new user or admin, run the following after you have set the secret
+ and have rebuilt NixOS:
+<screen>
+<prompt>$ </prompt>nix run nixpkgs.matrix-synapse
+<prompt>$ </prompt>register_new_matrix_user -k <replaceable>your-registration-shared-secret</replaceable> http://localhost:8008
+<prompt>New user localpart: </prompt><replaceable>your-username</replaceable>
+<prompt>Password:</prompt>
+<prompt>Confirm password:</prompt>
+<prompt>Make admin [no]:</prompt>
+Success!
+</screen>
+ In the example, this would create a user with the Matrix Identifier
+ <literal>@your-username:example.org</literal>. Note that the registration
+ secret ends up in the nix store and therefore is world-readable by any user
+ on your machine, so it makes sense to only temporarily activate the
+ <link linkend="opt-services.matrix-synapse.registration_shared_secret">registration_shared_secret</link>
+ option until a better solution for NixOS is in place.
+ </para>
+ </section>
+ <section xml:id="module-services-matrix-riot-web">
+ <title>Riot Web Client</title>
+
+ <para>
+ <link xlink:href="https://github.com/vector-im/riot-web/">Riot Web</link> is
+ the reference web client for Matrix and developed by the core team at
+ matrix.org. The following snippet can be optionally added to the code before
+ to complete the synapse installation with a web client served at
+ <code>https://riot.myhostname.example.org</code> and
+ <code>https://riot.example.org</code>. Alternatively, you can use the hosted
+ copy at <link xlink:href="https://riot.im/app">https://riot.im/app</link>,
+ or use other web clients or native client applications. Due to the
+ <literal>/.well-known</literal> urls set up done above, many clients should
+ fill in the required connection details automatically when you enter your
+ Matrix Identifier. See
+ <link xlink:href="https://matrix.org/docs/projects/try-matrix-now.html">Try
+ Matrix Now!</link> for a list of existing clients and their supported
+ featureset.
+<programlisting>
+{
+ services.nginx.virtualHosts."riot.${fqdn}" = {
+ <link linkend="opt-services.nginx.virtualHosts._name_.enableACME">enableACME</link> = true;
+ <link linkend="opt-services.nginx.virtualHosts._name_.forceSSL">forceSSL</link> = true;
+ <link linkend="opt-services.nginx.virtualHosts._name_.serverAliases">serverAliases</link> = [
+ "riot.${config.networking.domain}"
+ ];
+
+ <link linkend="opt-services.nginx.virtualHosts._name_.root">root</link> = pkgs.riot-web.override {
+ conf = {
+ default_server_config."m.homeserver" = {
+ "base_url" = "${config.networking.domain}";
+ "server_name" = "${fqdn}";
+ };
+ };
+ };
+ };
+}
+</programlisting>
+ </para>
+
+ <para>
+ Note that the Riot developers do not recommend running Riot and your Matrix
+ homeserver on the same fully-qualified domain name for security reasons. In
+ the example, this means that you should not reuse the
+ <literal>myhostname.example.org</literal> virtualHost to also serve Riot,
+ but instead serve it on a different subdomain, like
+ <literal>riot.example.org</literal> in the example. See the
+ <link xlink:href="https://github.com/vector-im/riot-web#important-security-note">Riot
+ Important Security Notes</link> for more information on this subject.
+ </para>
+ </section>
+</chapter>
diff --git a/nixpkgs/nixos/modules/services/misc/parsoid.nix b/nixpkgs/nixos/modules/services/misc/parsoid.nix
index 61626e78f8b..09b7f977bfb 100644
--- a/nixpkgs/nixos/modules/services/misc/parsoid.nix
+++ b/nixpkgs/nixos/modules/services/misc/parsoid.nix
@@ -6,7 +6,7 @@ let
cfg = config.services.parsoid;
- parsoid = pkgs.nodePackages."parsoid-git://github.com/abbradar/parsoid#stable";
+ parsoid = pkgs.nodePackages.parsoid;
confTree = {
worker_heartbeat_timeout = 300000;
@@ -98,8 +98,29 @@ in
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
- User = "nobody";
ExecStart = "${parsoid}/lib/node_modules/parsoid/bin/server.js -c ${confFile} -n ${toString cfg.workers}";
+
+ DynamicUser = true;
+ User = "parsoid";
+ Group = "parsoid";
+
+ CapabilityBoundingSet = "";
+ NoNewPrivileges = true;
+ ProtectSystem = "strict";
+ ProtectHome = true;
+ PrivateTmp = true;
+ PrivateDevices = true;
+ ProtectHostname = true;
+ ProtectKernelTunables = true;
+ ProtectKernelModules = true;
+ ProtectControlGroups = true;
+ RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+ RestrictNamespaces = true;
+ LockPersonality = true;
+ #MemoryDenyWriteExecute = true;
+ RestrictRealtime = true;
+ RestrictSUIDSGID = true;
+ RemoveIPC = true;
};
};
diff --git a/nixpkgs/nixos/modules/services/misc/sssd.nix b/nixpkgs/nixos/modules/services/misc/sssd.nix
index 6b64045dde8..36008d25741 100644
--- a/nixpkgs/nixos/modules/services/misc/sssd.nix
+++ b/nixpkgs/nixos/modules/services/misc/sssd.nix
@@ -88,9 +88,7 @@ in {
exec ${pkgs.sssd}/bin/sss_ssh_authorizedkeys "$@"
'';
};
- services.openssh.extraConfig = ''
- AuthorizedKeysCommand /etc/ssh/authorized_keys_command
- AuthorizedKeysCommandUser nobody
- '';
+ services.openssh.authorizedKeysCommand = "/etc/ssh/authorized_keys_command";
+ services.openssh.authorizedKeysCommandUser = "nobody";
})];
}
diff --git a/nixpkgs/nixos/modules/services/misc/zoneminder.nix b/nixpkgs/nixos/modules/services/misc/zoneminder.nix
index d7f7324580c..d5b3537068d 100644
--- a/nixpkgs/nixos/modules/services/misc/zoneminder.nix
+++ b/nixpkgs/nixos/modules/services/misc/zoneminder.nix
@@ -77,6 +77,8 @@ in {
`config.services.zoneminder.database.createLocally` to true. Otherwise,
when set to `false` (the default), you will have to create the database
and database user as well as populate the database yourself.
+ Additionally, you will need to run `zmupdate.pl` yourself when
+ upgrading to a newer version.
'';
webserver = mkOption {
@@ -330,6 +332,8 @@ in {
${config.services.mysql.package}/bin/mysql < ${pkg}/share/zoneminder/db/zm_create.sql
touch "/var/lib/${dirName}/db-created"
fi
+
+ ${zoneminder}/bin/zmupdate.pl -nointeractive
'';
serviceConfig = {
User = user;
diff --git a/nixpkgs/nixos/modules/services/monitoring/cadvisor.nix b/nixpkgs/nixos/modules/services/monitoring/cadvisor.nix
index 695a8c42e85..655a6934a26 100644
--- a/nixpkgs/nixos/modules/services/monitoring/cadvisor.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/cadvisor.nix
@@ -135,7 +135,6 @@ in {
serviceConfig.TimeoutStartSec=300;
};
- virtualisation.docker.enable = mkDefault true;
})
];
}
diff --git a/nixpkgs/nixos/modules/services/monitoring/heapster.nix b/nixpkgs/nixos/modules/services/monitoring/heapster.nix
index 585632943fd..0a9dfa12eaa 100644
--- a/nixpkgs/nixos/modules/services/monitoring/heapster.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/heapster.nix
@@ -49,7 +49,7 @@ in {
};
};
- users.users.heapsterrs = {
+ users.users.heapster = {
uid = config.ids.uids.heapster;
description = "Heapster user";
};
diff --git a/nixpkgs/nixos/modules/services/monitoring/nagios.nix b/nixpkgs/nixos/modules/services/monitoring/nagios.nix
index 3ca79dddaf5..9ac6869068f 100644
--- a/nixpkgs/nixos/modules/services/monitoring/nagios.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/nagios.nix
@@ -154,7 +154,7 @@ in
};
virtualHost = mkOption {
- type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix);
+ type = types.submodule (import ../web-servers/apache-httpd/vhost-options.nix);
example = literalExample ''
{ hostName = "example.org";
adminAddr = "webmaster@example.org";
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix
index b67f697ca0d..6b1a4be44d1 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix
@@ -9,12 +9,13 @@ let
# a wrapper that verifies that the configuration is valid
promtoolCheck = what: name: file:
- pkgs.runCommand
- "${name}-${replaceStrings [" "] [""] what}-checked"
- { buildInputs = [ cfg.package ]; } ''
- ln -s ${file} $out
- promtool ${what} $out
- '';
+ if cfg.checkConfig then
+ pkgs.runCommand
+ "${name}-${replaceStrings [" "] [""] what}-checked"
+ { buildInputs = [ cfg.package ]; } ''
+ ln -s ${file} $out
+ promtool ${what} $out
+ '' else file;
# Pretty-print JSON to a file
writePrettyJSON = name: x:
@@ -601,6 +602,20 @@ in {
if Prometheus is served via a reverse proxy).
'';
};
+
+ checkConfig = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Check configuration with <literal>promtool
+ check</literal>. The call to <literal>promtool</literal> is
+ subject to sandboxing by Nix. When credentials are stored in
+ external files (<literal>password_file</literal>,
+ <literal>bearer_token_file</literal>, etc), they will not be
+ visible to <literal>promtool</literal> and it will report
+ errors, despite a correct configuration.
+ '';
+ };
};
config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix
index 36ebffa4463..f9ad1457fc8 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix
@@ -29,6 +29,7 @@ let
"fritzbox"
"json"
"mail"
+ "mikrotik"
"minio"
"nextcloud"
"nginx"
@@ -197,13 +198,25 @@ in
config = mkMerge ([{
assertions = [ {
- assertion = (cfg.snmp.configurationPath == null) != (cfg.snmp.configuration == null);
+ assertion = cfg.snmp.enable -> (
+ (cfg.snmp.configurationPath == null) != (cfg.snmp.configuration == null)
+ );
message = ''
Please ensure you have either `services.prometheus.exporters.snmp.configuration'
or `services.prometheus.exporters.snmp.configurationPath' set!
'';
} {
- assertion = (cfg.mail.configFile == null) != (cfg.mail.configuration == {});
+ assertion = cfg.mikrotik.enable -> (
+ (cfg.mikrotik.configFile == null) != (cfg.mikrotik.configuration == null)
+ );
+ message = ''
+ Please specify either `services.prometheus.exporters.mikrotik.configuration'
+ or `services.prometheus.exporters.mikrotik.configFile'.
+ '';
+ } {
+ assertion = cfg.mail.enable -> (
+ (cfg.mail.configFile == null) != (cfg.mail.configuration == null)
+ );
message = ''
Please specify either 'services.prometheus.exporters.mail.configuration'
or 'services.prometheus.exporters.mail.configFile'.
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix
index 8a90afa9984..fe8d905da3f 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix
@@ -61,7 +61,7 @@ in {
ExecStart = ''
${pkgs.prometheus-blackbox-exporter}/bin/blackbox_exporter \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
- --config.file ${adjustedConfigFile} \
+ --config.file ${escapeShellArg adjustedConfigFile} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix
index 1cc34641809..97210463027 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix
@@ -66,7 +66,7 @@ in
serviceConfig = {
ExecStart = ''
${pkgs.prometheus-collectd-exporter}/bin/collectd_exporter \
- -log.format ${cfg.logFormat} \
+ -log.format ${escapeShellArg cfg.logFormat} \
-log.level ${cfg.logLevel} \
-web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
${collectSettingsArgs} \
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix
index e9fa26cb1f5..68afba21d64 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix
@@ -30,7 +30,7 @@ in
${pkgs.prometheus-dnsmasq-exporter}/bin/dnsmasq_exporter \
--listen ${cfg.listenAddress}:${toString cfg.port} \
--dnsmasq ${cfg.dnsmasqListenAddress} \
- --leases_path ${cfg.leasesPath} \
+ --leases_path ${escapeShellArg cfg.leasesPath} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix
index a01074758ff..aba3533e439 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix
@@ -64,7 +64,7 @@ in
${pkgs.prometheus-dovecot-exporter}/bin/dovecot_exporter \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
--web.telemetry-path ${cfg.telemetryPath} \
- --dovecot.socket-path ${cfg.socketPath} \
+ --dovecot.socket-path ${escapeShellArg cfg.socketPath} \
--dovecot.scopes ${concatStringsSep "," cfg.scopes} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/json.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/json.nix
index 82a55bafc98..bd0026b55f7 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/json.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/json.nix
@@ -27,7 +27,7 @@ in
ExecStart = ''
${pkgs.prometheus-json-exporter}/bin/prometheus-json-exporter \
--port ${toString cfg.port} \
- ${cfg.url} ${cfg.configFile} \
+ ${cfg.url} ${escapeShellArg cfg.configFile} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mail.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mail.nix
index 7d8c6fb6140..18c5c4dd162 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mail.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mail.nix
@@ -90,7 +90,7 @@ let
Timeout until mails are considered "didn't make it".
'';
};
- disableFileDelition = mkOption {
+ disableFileDeletion = mkOption {
type = types.bool;
default = false;
description = ''
@@ -127,8 +127,8 @@ in
'';
};
configuration = mkOption {
- type = types.submodule exporterOptions;
- default = {};
+ type = types.nullOr (types.submodule exporterOptions);
+ default = null;
description = ''
Specify the mailexporter configuration file to use.
'';
@@ -147,8 +147,9 @@ in
ExecStart = ''
${pkgs.prometheus-mail-exporter}/bin/mailexporter \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
+ --web.telemetry-path ${cfg.telemetryPath} \
--config.file ${
- if cfg.configuration != {} then configurationFile else cfg.configFile
+ if cfg.configuration != null then configurationFile else (escapeShellArg cfg.configFile)
} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mikrotik.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mikrotik.nix
new file mode 100644
index 00000000000..62c2cc56847
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mikrotik.nix
@@ -0,0 +1,66 @@
+{ config, lib, pkgs, options }:
+
+with lib;
+
+let
+ cfg = config.services.prometheus.exporters.mikrotik;
+in
+{
+ port = 9436;
+ extraOpts = {
+ configFile = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ description = ''
+ Path to a mikrotik exporter configuration file. Mutually exclusive with
+ <option>configuration</option> option.
+ '';
+ example = literalExample "./mikrotik.yml";
+ };
+
+ configuration = mkOption {
+ type = types.nullOr types.attrs;
+ default = null;
+ description = ''
+ Mikrotik exporter configuration as nix attribute set. Mutually exclusive with
+ <option>configFile</option> option.
+
+ See <link xlink:href="https://github.com/nshttpd/mikrotik-exporter/blob/master/README.md"/>
+ for the description of the configuration file format.
+ '';
+ example = literalExample ''
+ {
+ devices = [
+ {
+ name = "my_router";
+ address = "10.10.0.1";
+ user = "prometheus";
+ password = "changeme";
+ }
+ ];
+ features = {
+ bgp = true;
+ dhcp = true;
+ routes = true;
+ optics = true;
+ };
+ }
+ '';
+ };
+ };
+ serviceOpts = let
+ configFile = if cfg.configFile != null
+ then cfg.configFile
+ else "${pkgs.writeText "mikrotik-exporter.yml" (builtins.toJSON cfg.configuration)}";
+ in {
+ serviceConfig = {
+ # -port is misleading name, it actually accepts address too
+ ExecStart = ''
+ ${pkgs.prometheus-mikrotik-exporter}/bin/mikrotik-exporter \
+ -config-file=${escapeShellArg configFile} \
+ -port=${cfg.listenAddress}:${toString cfg.port} \
+ ${concatStringsSep " \\\n " cfg.extraFlags}
+ '';
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/minio.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/minio.nix
index ab3e3d7d5d5..d6dd62f871b 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/minio.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/minio.nix
@@ -54,8 +54,8 @@ in
${pkgs.prometheus-minio-exporter}/bin/minio-exporter \
-web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
-minio.server ${cfg.minioAddress} \
- -minio.access-key ${cfg.minioAccessKey} \
- -minio.access-secret ${cfg.minioAccessSecret} \
+ -minio.access-key ${escapeShellArg cfg.minioAccessKey} \
+ -minio.access-secret ${escapeShellArg cfg.minioAccessSecret} \
${optionalString cfg.minioBucketStats "-minio.bucket-stats"} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix
index 5f9a52053f7..aee6bd5e66c 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix
@@ -50,7 +50,7 @@ in
-u ${cfg.username} \
-t ${cfg.timeout} \
-l ${cfg.url} \
- -p @${cfg.passwordFile} \
+ -p ${escapeShellArg "@${cfg.passwordFile}"} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix
index ba852fea433..56cddfc55b7 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix
@@ -30,7 +30,17 @@ in
Whether to perform certificate verification for https.
'';
};
-
+ constLabels = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ example = [
+ "label1=value1"
+ "label2=value2"
+ ];
+ description = ''
+ A list of constant labels that will be used in every metric.
+ '';
+ };
};
serviceOpts = {
serviceConfig = {
@@ -40,6 +50,7 @@ in
--nginx.ssl-verify ${toString cfg.sslVerify} \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
--web.telemetry-path ${cfg.telemetryPath} \
+ --prometheus.const-labels ${concatStringsSep "," cfg.constLabels} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix
index d50564717ea..3b6ef1631f8 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix
@@ -67,15 +67,15 @@ in
${pkgs.prometheus-postfix-exporter}/bin/postfix_exporter \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
--web.telemetry-path ${cfg.telemetryPath} \
- --postfix.showq_path ${cfg.showqPath} \
+ --postfix.showq_path ${escapeShellArg cfg.showqPath} \
${concatStringsSep " \\\n " (cfg.extraFlags
++ optional cfg.systemd.enable "--systemd.enable"
++ optional cfg.systemd.enable (if cfg.systemd.slice != null
then "--systemd.slice ${cfg.systemd.slice}"
else "--systemd.unit ${cfg.systemd.unit}")
++ optional (cfg.systemd.enable && (cfg.systemd.journalPath != null))
- "--systemd.journal_path ${cfg.systemd.journalPath}"
- ++ optional (!cfg.systemd.enable) "--postfix.logfile_path ${cfg.logfilePath}")}
+ "--systemd.journal_path ${escapeShellArg cfg.systemd.journalPath}"
+ ++ optional (!cfg.systemd.enable) "--postfix.logfile_path ${escapeShellArg cfg.logfilePath}")}
'';
};
};
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix
index fe7ae8a8ac9..045e48a3d0f 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix
@@ -19,7 +19,7 @@ in
configuration = mkOption {
type = types.nullOr types.attrs;
- default = {};
+ default = null;
description = ''
Snmp exporter configuration as nix attribute set. Mutually exclusive with 'configurationPath' option.
'';
@@ -36,15 +36,15 @@ in
};
logFormat = mkOption {
- type = types.str;
- default = "logger:stderr";
+ type = types.enum ["logfmt" "json"];
+ default = "logfmt";
description = ''
- Set the log target and format.
+ Output format of log messages.
'';
};
logLevel = mkOption {
- type = types.enum ["debug" "info" "warn" "error" "fatal"];
+ type = types.enum ["debug" "info" "warn" "error"];
default = "info";
description = ''
Only log messages with the given severity or above.
@@ -54,13 +54,13 @@ in
serviceOpts = let
configFile = if cfg.configurationPath != null
then cfg.configurationPath
- else "${pkgs.writeText "snmp-eporter-conf.yml" (builtins.toJSON cfg.configuration)}";
+ else "${pkgs.writeText "snmp-exporter-conf.yml" (builtins.toJSON cfg.configuration)}";
in {
serviceConfig = {
ExecStart = ''
${pkgs.prometheus-snmp-exporter.bin}/bin/snmp_exporter \
- --config.file=${configFile} \
- --log.format=${cfg.logFormat} \
+ --config.file=${escapeShellArg configFile} \
+ --log.format=${escapeShellArg cfg.logFormat} \
--log.level=${cfg.logLevel} \
--web.listen-address=${cfg.listenAddress}:${toString cfg.port} \
${concatStringsSep " \\\n " cfg.extraFlags}
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix
index 9aa0f1b85aa..8d0e8764001 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix
@@ -55,8 +55,8 @@ in
${pkgs.prometheus-unifi-exporter}/bin/unifi_exporter \
-telemetry.addr ${cfg.listenAddress}:${toString cfg.port} \
-unifi.addr ${cfg.unifiAddress} \
- -unifi.username ${cfg.unifiUsername} \
- -unifi.password ${cfg.unifiPassword} \
+ -unifi.username ${escapeShellArg cfg.unifiUsername} \
+ -unifi.password ${escapeShellArg cfg.unifiPassword} \
-unifi.timeout ${cfg.unifiTimeout} \
${optionalString cfg.unifiInsecure "-unifi.insecure" } \
${concatStringsSep " \\\n " cfg.extraFlags}
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix
index 12153fa021e..5b5a6e18fcd 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix
@@ -74,10 +74,10 @@ in
${pkgs.prometheus-varnish-exporter}/bin/prometheus_varnish_exporter \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
--web.telemetry-path ${cfg.telemetryPath} \
- --varnishstat-path ${cfg.varnishStatPath} \
+ --varnishstat-path ${escapeShellArg cfg.varnishStatPath} \
${concatStringsSep " \\\n " (cfg.extraFlags
++ optional (cfg.healthPath != null) "--web.health-path ${cfg.healthPath}"
- ++ optional (cfg.instance != null) "-n ${cfg.instance}"
+ ++ optional (cfg.instance != null) "-n ${escapeShellArg cfg.instance}"
++ optional cfg.noExit "--no-exit"
++ optional cfg.withGoMetrics "--with-go-metrics"
++ optional cfg.verbose "--verbose"
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix
index 374f83a2939..04421fc2d25 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix
@@ -59,7 +59,7 @@ in {
${optionalString cfg.verbose "-v"} \
${optionalString cfg.singleSubnetPerField "-s"} \
${optionalString cfg.withRemoteIp "-r"} \
- ${optionalString (cfg.wireguardConfig != null) "-n ${cfg.wireguardConfig}"}
+ ${optionalString (cfg.wireguardConfig != null) "-n ${escapeShellArg cfg.wireguardConfig}"}
'';
};
};
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/xmpp-alerts.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/xmpp-alerts.nix
new file mode 100644
index 00000000000..44b15cb2034
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/xmpp-alerts.nix
@@ -0,0 +1,47 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.prometheus.xmpp-alerts;
+
+ configFile = pkgs.writeText "prometheus-xmpp-alerts.yml" (builtins.toJSON cfg.configuration);
+
+in
+
+{
+ options.services.prometheus.xmpp-alerts = {
+
+ enable = mkEnableOption "XMPP Web hook service for Alertmanager";
+
+ configuration = mkOption {
+ type = types.attrs;
+ description = "Configuration as attribute set which will be converted to YAML";
+ };
+
+ };
+
+ config = mkIf cfg.enable {
+ systemd.services.prometheus-xmpp-alerts = {
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network-online.target" ];
+ wants = [ "network-online.target" ];
+ serviceConfig = {
+ ExecStart = "${pkgs.prometheus-xmpp-alerts}/bin/prometheus-xmpp-alerts --config ${configFile}";
+ Restart = "on-failure";
+ DynamicUser = true;
+ PrivateTmp = true;
+ PrivateDevices = true;
+ ProtectHome = true;
+ ProtectSystem = "strict";
+ ProtectKernelTunables = true;
+ ProtectKernelModules = true;
+ ProtectControlGroups = true;
+ NoNewPrivileges = true;
+ SystemCallArchitectures = "native";
+ RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+ SystemCallFilter = [ "@system-service" ];
+ };
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/monitoring/statsd.nix b/nixpkgs/nixos/modules/services/monitoring/statsd.nix
index 17836e95a6f..30b2916a992 100644
--- a/nixpkgs/nixos/modules/services/monitoring/statsd.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/statsd.nix
@@ -125,7 +125,7 @@ in
message = "Only builtin backends (graphite, console, repeater) or backends enumerated in `pkgs.nodePackages` are allowed!";
}) cfg.backends;
- users.use.statsdrs = {
+ users.users.statsd = {
uid = config.ids.uids.statsd;
description = "Statsd daemon user";
};
diff --git a/nixpkgs/nixos/modules/services/networking/cjdns.nix b/nixpkgs/nixos/modules/services/networking/cjdns.nix
index 3fb85b16cbe..5f8ac96b229 100644
--- a/nixpkgs/nixos/modules/services/networking/cjdns.nix
+++ b/nixpkgs/nixos/modules/services/networking/cjdns.nix
@@ -29,17 +29,13 @@ let
};
# Additional /etc/hosts entries for peers with an associated hostname
- cjdnsExtraHosts = import (pkgs.runCommand "cjdns-hosts" {}
- # Generate a builder that produces an output usable as a Nix string value
- ''
- exec >$out
- echo \'\'
- ${concatStringsSep "\n" (mapAttrsToList (k: v:
- optionalString (v.hostname != "")
- "echo $(${pkgs.cjdns}/bin/publictoip6 ${v.publicKey}) ${v.hostname}")
- (cfg.ETHInterface.connectTo // cfg.UDPInterface.connectTo))}
- echo \'\'
- '');
+ cjdnsExtraHosts = pkgs.runCommandNoCC "cjdns-hosts" {} ''
+ exec >$out
+ ${concatStringsSep "\n" (mapAttrsToList (k: v:
+ optionalString (v.hostname != "")
+ "echo $(${pkgs.cjdns}/bin/publictoip6 ${v.publicKey}) ${v.hostname}")
+ (cfg.ETHInterface.connectTo // cfg.UDPInterface.connectTo))}
+ '';
parseModules = x:
x // { connectTo = mapAttrs (name: value: { inherit (value) password publicKey; }) x.connectTo; };
@@ -144,13 +140,15 @@ in
connectTo = mkOption {
type = types.attrsOf ( types.submodule ( connectToSubmodule ) );
default = { };
- example = {
- "192.168.1.1:27313" = {
- hostname = "homer.hype";
- password = "5kG15EfpdcKNX3f2GSQ0H1HC7yIfxoCoImnO5FHM";
- publicKey = "371zpkgs8ss387tmr81q04mp0hg1skb51hw34vk1cq644mjqhup0.k";
- };
- };
+ example = literalExample ''
+ {
+ "192.168.1.1:27313" = {
+ hostname = "homer.hype";
+ password = "5kG15EfpdcKNX3f2GSQ0H1HC7yIfxoCoImnO5FHM";
+ publicKey = "371zpkgs8ss387tmr81q04mp0hg1skb51hw34vk1cq644mjqhup0.k";
+ };
+ }
+ '';
description = ''
Credentials for making UDP tunnels.
'';
@@ -189,13 +187,15 @@ in
connectTo = mkOption {
type = types.attrsOf ( types.submodule ( connectToSubmodule ) );
default = { };
- example = {
- "01:02:03:04:05:06" = {
- hostname = "homer.hype";
- password = "5kG15EfpdcKNX3f2GSQ0H1HC7yIfxoCoImnO5FHM";
- publicKey = "371zpkgs8ss387tmr81q04mp0hg1skb51hw34vk1cq644mjqhup0.k";
- };
- };
+ example = literalExample ''
+ {
+ "01:02:03:04:05:06" = {
+ hostname = "homer.hype";
+ password = "5kG15EfpdcKNX3f2GSQ0H1HC7yIfxoCoImnO5FHM";
+ publicKey = "371zpkgs8ss387tmr81q04mp0hg1skb51hw34vk1cq644mjqhup0.k";
+ };
+ }
+ '';
description = ''
Credentials for connecting look similar to UDP credientials
except they begin with the mac address.
@@ -278,7 +278,7 @@ in
};
};
- networking.extraHosts = mkIf cfg.addExtraHosts cjdnsExtraHosts;
+ networking.hostFiles = mkIf cfg.addExtraHosts [ cjdnsExtraHosts ];
assertions = [
{ assertion = ( cfg.ETHInterface.bind != "" || cfg.UDPInterface.bind != "" || cfg.confFile != null );
diff --git a/nixpkgs/nixos/modules/services/networking/dhcpcd.nix b/nixpkgs/nixos/modules/services/networking/dhcpcd.nix
index 6972c833cc5..c0619211c2f 100644
--- a/nixpkgs/nixos/modules/services/networking/dhcpcd.nix
+++ b/nixpkgs/nixos/modules/services/networking/dhcpcd.nix
@@ -19,7 +19,7 @@ let
map (i: i.name) (filter (i: if i.useDHCP != null then !i.useDHCP else i.ipv4.addresses != [ ]) interfaces)
++ mapAttrsToList (i: _: i) config.networking.sits
++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bridges))
- ++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.vswitches))
+ ++ flatten (concatMap (i: attrNames (filterAttrs (_: config: config.type != "internal") i.interfaces)) (attrValues config.networking.vswitches))
++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bonds))
++ config.networking.dhcpcd.denyInterfaces;
@@ -190,6 +190,8 @@ in
before = [ "network-online.target" ];
after = [ "systemd-udev-settle.service" ];
+ restartTriggers = [ exitHook ];
+
# Stopping dhcpcd during a reconfiguration is undesirable
# because it brings down the network interfaces configured by
# dhcpcd. So do a "systemctl restart" instead.
diff --git a/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy.nix b/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy.nix
deleted file mode 100644
index 8edcf925dbf..00000000000
--- a/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy.nix
+++ /dev/null
@@ -1,328 +0,0 @@
-{ config, lib, pkgs, ... }:
-with lib;
-
-let
- cfg = config.services.dnscrypt-proxy;
-
- stateDirectory = "/var/lib/dnscrypt-proxy";
-
- # The minisign public key used to sign the upstream resolver list.
- # This is somewhat more flexible than preloading the key as an
- # embedded string.
- upstreamResolverListPubKey = pkgs.fetchurl {
- url = https://raw.githubusercontent.com/dyne/dnscrypt-proxy/master/minisign.pub;
- sha256 = "18lnp8qr6ghfc2sd46nn1rhcpr324fqlvgsp4zaigw396cd7vnnh";
- };
-
- # Internal flag indicating whether the upstream resolver list is used.
- useUpstreamResolverList = cfg.customResolver == null;
-
- # The final local address.
- localAddress = "${cfg.localAddress}:${toString cfg.localPort}";
-
- # The final resolvers list path.
- resolverList = "${stateDirectory}/dnscrypt-resolvers.csv";
-
- # Build daemon command line
-
- resolverArgs =
- if (cfg.customResolver == null)
- then
- [ "-L ${resolverList}"
- "-R ${cfg.resolverName}"
- ]
- else with cfg.customResolver;
- [ "-N ${name}"
- "-k ${key}"
- "-r ${address}:${toString port}"
- ];
-
- daemonArgs =
- [ "-a ${localAddress}" ]
- ++ resolverArgs
- ++ cfg.extraArgs;
-in
-
-{
- meta = {
- maintainers = with maintainers; [ joachifm ];
- doc = ./dnscrypt-proxy.xml;
- };
-
- options = {
- # Before adding another option, consider whether it could
- # equally well be passed via extraArgs.
-
- services.dnscrypt-proxy = {
- enable = mkOption {
- default = false;
- type = types.bool;
- description = "Whether to enable the DNSCrypt client proxy";
- };
-
- localAddress = mkOption {
- default = "127.0.0.1";
- type = types.str;
- description = ''
- Listen for DNS queries to relay on this address. The only reason to
- change this from its default value is to proxy queries on behalf
- of other machines (typically on the local network).
- '';
- };
-
- localPort = mkOption {
- default = 53;
- type = types.int;
- description = ''
- Listen for DNS queries to relay on this port. The default value
- assumes that the DNSCrypt proxy should relay DNS queries directly.
- When running as a forwarder for another DNS client, set this option
- to a different value; otherwise leave the default.
- '';
- };
-
- resolverName = mkOption {
- default = "random";
- example = "dnscrypt.eu-nl";
- type = types.nullOr types.str;
- description = ''
- The name of the DNSCrypt resolver to use, taken from
- <filename>${resolverList}</filename>. The default is to
- pick a random non-logging resolver that supports DNSSEC.
- '';
- };
-
- customResolver = mkOption {
- default = null;
- description = ''
- Use an unlisted resolver (e.g., a private DNSCrypt provider). For
- advanced users only. If specified, this option takes precedence.
- '';
- type = types.nullOr (types.submodule ({ ... }: { options = {
- address = mkOption {
- type = types.str;
- description = "IP address";
- example = "208.67.220.220";
- };
-
- port = mkOption {
- type = types.int;
- description = "Port";
- default = 443;
- };
-
- name = mkOption {
- type = types.str;
- description = "Fully qualified domain name";
- example = "2.dnscrypt-cert.example.com";
- };
-
- key = mkOption {
- type = types.str;
- description = "Public key";
- example = "B735:1140:206F:225D:3E2B:D822:D7FD:691E:A1C3:3CC8:D666:8D0C:BE04:BFAB:CA43:FB79";
- };
- }; }));
- };
-
- extraArgs = mkOption {
- default = [];
- type = types.listOf types.str;
- description = ''
- Additional command-line arguments passed verbatim to the daemon.
- See <citerefentry><refentrytitle>dnscrypt-proxy</refentrytitle>
- <manvolnum>8</manvolnum></citerefentry> for details.
- '';
- example = [ "-X libdcplugin_example_cache.so,--min-ttl=60" ];
- };
- };
- };
-
- config = mkIf cfg.enable (mkMerge [{
- assertions = [
- { assertion = (cfg.customResolver != null) || (cfg.resolverName != null);
- message = "please configure upstream DNSCrypt resolver";
- }
- ];
-
- # make man 8 dnscrypt-proxy work
- environment.systemPackages = [ pkgs.dnscrypt-proxy ];
-
- users.users.dnscrypt-proxy = {
- description = "dnscrypt-proxy daemon user";
- isSystemUser = true;
- group = "dnscrypt-proxy";
- };
- users.groups.dnscrypt-proxy = {};
-
- systemd.sockets.dnscrypt-proxy = {
- description = "dnscrypt-proxy listening socket";
- documentation = [ "man:dnscrypt-proxy(8)" ];
-
- wantedBy = [ "sockets.target" ];
-
- socketConfig = {
- ListenStream = localAddress;
- ListenDatagram = localAddress;
- };
- };
-
- systemd.services.dnscrypt-proxy = {
- description = "dnscrypt-proxy daemon";
- documentation = [ "man:dnscrypt-proxy(8)" ];
-
- before = [ "nss-lookup.target" ];
- after = [ "network.target" ];
- requires = [ "dnscrypt-proxy.socket "];
-
- serviceConfig = {
- NonBlocking = "true";
- ExecStart = "${pkgs.dnscrypt-proxy}/bin/dnscrypt-proxy ${toString daemonArgs}";
- ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
-
- User = "dnscrypt-proxy";
-
- PrivateTmp = true;
- PrivateDevices = true;
- ProtectHome = true;
- };
- };
- }
-
- (mkIf config.security.apparmor.enable {
- systemd.services.dnscrypt-proxy.after = [ "apparmor.service" ];
-
- security.apparmor.profiles = singleton (pkgs.writeText "apparmor-dnscrypt-proxy" ''
- ${pkgs.dnscrypt-proxy}/bin/dnscrypt-proxy {
- /dev/null rw,
- /dev/random r,
- /dev/urandom r,
-
- /etc/passwd r,
- /etc/group r,
- ${config.environment.etc."nsswitch.conf".source} r,
-
- ${getLib pkgs.glibc}/lib/*.so mr,
- ${pkgs.tzdata}/share/zoneinfo/** r,
-
- network inet stream,
- network inet6 stream,
- network inet dgram,
- network inet6 dgram,
-
- ${getLib pkgs.dnscrypt-proxy}/lib/dnscrypt-proxy/libdcplugin*.so mr,
-
- ${getLib pkgs.gcc.cc}/lib/libssp.so.* mr,
- ${getLib pkgs.libsodium}/lib/libsodium.so.* mr,
- ${getLib pkgs.systemd}/lib/libsystemd.so.* mr,
- ${getLib pkgs.utillinuxMinimal.out}/lib/libmount.so.* mr,
- ${getLib pkgs.utillinuxMinimal.out}/lib/libblkid.so.* mr,
- ${getLib pkgs.utillinuxMinimal.out}/lib/libuuid.so.* mr,
- ${getLib pkgs.xz}/lib/liblzma.so.* mr,
- ${getLib pkgs.libgcrypt}/lib/libgcrypt.so.* mr,
- ${getLib pkgs.libgpgerror}/lib/libgpg-error.so.* mr,
- ${getLib pkgs.libcap}/lib/libcap.so.* mr,
- ${getLib pkgs.lz4}/lib/liblz4.so.* mr,
- ${getLib pkgs.attr}/lib/libattr.so.* mr, # */
-
- ${resolverList} r,
-
- /run/systemd/notify rw,
- }
- '');
- })
-
- (mkIf useUpstreamResolverList {
- systemd.services.init-dnscrypt-proxy-statedir = {
- description = "Initialize dnscrypt-proxy state directory";
-
- wantedBy = [ "dnscrypt-proxy.service" ];
- before = [ "dnscrypt-proxy.service" ];
-
- script = ''
- mkdir -pv ${stateDirectory}
- chown -c dnscrypt-proxy:dnscrypt-proxy ${stateDirectory}
- cp -uv \
- ${pkgs.dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv \
- ${stateDirectory}
- '';
-
- serviceConfig = {
- Type = "oneshot";
- RemainAfterExit = true;
- };
- };
-
- systemd.services.update-dnscrypt-resolvers = {
- description = "Update list of DNSCrypt resolvers";
-
- requires = [ "init-dnscrypt-proxy-statedir.service" ];
- after = [ "init-dnscrypt-proxy-statedir.service" ];
-
- path = with pkgs; [ curl diffutils dnscrypt-proxy minisign ];
- script = ''
- cd ${stateDirectory}
- domain=raw.githubusercontent.com
- get="curl -fSs --resolve $domain:443:$(hostip -r 8.8.8.8 $domain | head -1)"
- $get -o dnscrypt-resolvers.csv.tmp \
- https://$domain/dyne/dnscrypt-proxy/master/dnscrypt-resolvers.csv
- $get -o dnscrypt-resolvers.csv.minisig.tmp \
- https://$domain/dyne/dnscrypt-proxy/master/dnscrypt-resolvers.csv.minisig
- mv dnscrypt-resolvers.csv.minisig{.tmp,}
- if ! minisign -q -V -p ${upstreamResolverListPubKey} \
- -m dnscrypt-resolvers.csv.tmp -x dnscrypt-resolvers.csv.minisig ; then
- echo "failed to verify resolver list!" >&2
- exit 1
- fi
- [[ -f dnscrypt-resolvers.csv ]] && mv dnscrypt-resolvers.csv{,.old}
- mv dnscrypt-resolvers.csv{.tmp,}
- if cmp dnscrypt-resolvers.csv{,.old} ; then
- echo "no change"
- else
- echo "resolver list updated"
- fi
- '';
-
- serviceConfig = {
- PrivateTmp = true;
- PrivateDevices = true;
- ProtectHome = true;
- ProtectSystem = "strict";
- ReadWritePaths = "${dirOf stateDirectory} ${stateDirectory}";
- SystemCallFilter = "~@mount";
- };
- };
-
- systemd.timers.update-dnscrypt-resolvers = {
- wantedBy = [ "timers.target" ];
- timerConfig = {
- OnBootSec = "5min";
- OnUnitActiveSec = "6h";
- };
- };
- })
- ]);
-
- imports = [
- (mkRenamedOptionModule [ "services" "dnscrypt-proxy" "port" ] [ "services" "dnscrypt-proxy" "localPort" ])
-
- (mkChangedOptionModule
- [ "services" "dnscrypt-proxy" "tcpOnly" ]
- [ "services" "dnscrypt-proxy" "extraArgs" ]
- (config:
- let val = getAttrFromPath [ "services" "dnscrypt-proxy" "tcpOnly" ] config; in
- optional val "-T"))
-
- (mkChangedOptionModule
- [ "services" "dnscrypt-proxy" "ephemeralKeys" ]
- [ "services" "dnscrypt-proxy" "extraArgs" ]
- (config:
- let val = getAttrFromPath [ "services" "dnscrypt-proxy" "ephemeralKeys" ] config; in
- optional val "-E"))
-
- (mkRemovedOptionModule [ "services" "dnscrypt-proxy" "resolverList" ] ''
- The current resolver listing from upstream is always used
- unless a custom resolver is specified.
- '')
- ];
-}
diff --git a/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy.xml b/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy.xml
deleted file mode 100644
index afc7880392a..00000000000
--- a/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-<chapter xmlns="http://docbook.org/ns/docbook"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:xi="http://www.w3.org/2001/XInclude"
- version="5.0"
- xml:id="sec-dnscrypt-proxy">
- <title>DNSCrypt client proxy</title>
- <para>
- The DNSCrypt client proxy relays DNS queries to a DNSCrypt enabled upstream
- resolver. The traffic between the client and the upstream resolver is
- encrypted and authenticated, mitigating the risk of MITM attacks, DNS
- poisoning attacks, and third-party snooping (assuming the upstream is
- trustworthy).
- </para>
- <sect1 xml:id="sec-dnscrypt-proxy-configuration">
- <title>Basic configuration</title>
-
- <para>
- To enable the client proxy, set
-<programlisting>
-<xref linkend="opt-services.dnscrypt-proxy.enable"/> = true;
-</programlisting>
- </para>
-
- <para>
- Enabling the client proxy does not alter the system nameserver; to relay
- local queries, prepend <literal>127.0.0.1</literal> to
- <option>networking.nameservers</option>.
- </para>
- </sect1>
- <sect1 xml:id="sec-dnscrypt-proxy-forwarder">
- <title>As a forwarder for another DNS client</title>
-
- <para>
- To run the DNSCrypt proxy client as a forwarder for another DNS client,
- change the default proxy listening port to a non-standard value and point
- the other client to it:
-<programlisting>
-<xref linkend="opt-services.dnscrypt-proxy.localPort"/> = 43;
-</programlisting>
- </para>
-
- <sect2 xml:id="sec-dnscrypt-proxy-forwarder-dsnmasq">
- <title>dnsmasq</title>
- <para>
-<programlisting>
-{
- <xref linkend="opt-services.dnsmasq.enable"/> = true;
- <xref linkend="opt-services.dnsmasq.servers"/> = [ "127.0.0.1#43" ];
-}
-</programlisting>
- </para>
- </sect2>
-
- <sect2 xml:id="sec-dnscrypt-proxy-forwarder-unbound">
- <title>unbound</title>
- <para>
-<programlisting>
-{
- <xref linkend="opt-services.unbound.enable"/> = true;
- <xref linkend="opt-services.unbound.forwardAddresses"/> = [ "127.0.0.1@43" ];
-}
-</programlisting>
- </para>
- </sect2>
- </sect1>
-</chapter>
diff --git a/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy2.nix b/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy2.nix
new file mode 100644
index 00000000000..e48eb729103
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy2.nix
@@ -0,0 +1,61 @@
+{ config, lib, pkgs, ... }: with lib;
+
+let
+ cfg = config.services.dnscrypt-proxy2;
+in
+
+{
+ options.services.dnscrypt-proxy2 = {
+ enable = mkEnableOption "dnscrypt-proxy2";
+
+ settings = mkOption {
+ description = ''
+ Attrset that is converted and passed as TOML config file.
+ For available params, see: <link xlink:href="https://github.com/DNSCrypt/dnscrypt-proxy/blob/master/dnscrypt-proxy/example-dnscrypt-proxy.toml"/>
+ '';
+ example = literalExample ''
+ {
+ sources.public-resolvers = {
+ urls = [ "https://download.dnscrypt.info/resolvers-list/v2/public-resolvers.md" ];
+ cache_file = "public-resolvers.md";
+ minisign_key = "RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3";
+ refresh_delay = 72;
+ };
+ }
+ '';
+ type = types.attrs;
+ default = {};
+ };
+
+ configFile = mkOption {
+ description = ''
+ Path to TOML config file. See: <link xlink:href="https://github.com/DNSCrypt/dnscrypt-proxy/blob/master/dnscrypt-proxy/example-dnscrypt-proxy.toml"/>
+ If this option is set, it will override any configuration done in options.services.dnscrypt-proxy2.settings.
+ '';
+ example = "/etc/dnscrypt-proxy/dnscrypt-proxy.toml";
+ type = types.path;
+ default = pkgs.runCommand "dnscrypt-proxy.toml" {
+ json = builtins.toJSON cfg.settings;
+ passAsFile = [ "json" ];
+ } ''
+ ${pkgs.remarshal}/bin/json2toml < $jsonPath > $out
+ '';
+ defaultText = literalExample "TOML file generated from services.dnscrypt-proxy2.settings";
+ };
+ };
+
+ config = mkIf cfg.enable {
+
+ networking.nameservers = lib.mkDefault [ "127.0.0.1" ];
+
+ systemd.services.dnscrypt-proxy2 = {
+ after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ serviceConfig = {
+ AmbientCapabilities = "CAP_NET_BIND_SERVICE";
+ DynamicUser = true;
+ ExecStart = "${pkgs.dnscrypt-proxy2}/bin/dnscrypt-proxy -config ${cfg.configFile}";
+ };
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/networking/firewall.nix b/nixpkgs/nixos/modules/services/networking/firewall.nix
index 15aaf741067..cdc3a172ea7 100644
--- a/nixpkgs/nixos/modules/services/networking/firewall.nix
+++ b/nixpkgs/nixos/modules/services/networking/firewall.nix
@@ -546,9 +546,13 @@ in
options nf_conntrack nf_conntrack_helper=1
'';
- assertions = [ { assertion = (cfg.checkReversePath != false) || kernelHasRPFilter;
- message = "This kernel does not support rpfilter"; }
- ];
+ assertions = [
+ # This is approximately "checkReversePath -> kernelHasRPFilter",
+ # but the checkReversePath option can include non-boolean
+ # values.
+ { assertion = cfg.checkReversePath == false || kernelHasRPFilter;
+ message = "This kernel does not support rpfilter"; }
+ ];
systemd.services.firewall = {
description = "Firewall";
diff --git a/nixpkgs/nixos/modules/services/networking/freeradius.nix b/nixpkgs/nixos/modules/services/networking/freeradius.nix
index e192b70c129..f3fdd576b65 100644
--- a/nixpkgs/nixos/modules/services/networking/freeradius.nix
+++ b/nixpkgs/nixos/modules/services/networking/freeradius.nix
@@ -10,14 +10,15 @@ let
{
description = "FreeRadius server";
wantedBy = ["multi-user.target"];
- after = ["network-online.target"];
- wants = ["network-online.target"];
+ after = ["network.target"];
+ wants = ["network.target"];
preStart = ''
${pkgs.freeradius}/bin/radiusd -C -d ${cfg.configDir} -l stdout
'';
serviceConfig = {
- ExecStart = "${pkgs.freeradius}/bin/radiusd -f -d ${cfg.configDir} -l stdout -xx";
+ ExecStart = "${pkgs.freeradius}/bin/radiusd -f -d ${cfg.configDir} -l stdout" +
+ optionalString cfg.debug " -xx";
ExecReload = [
"${pkgs.freeradius}/bin/radiusd -C -d ${cfg.configDir} -l stdout"
"${pkgs.coreutils}/bin/kill -HUP $MAINPID"
@@ -41,6 +42,16 @@ let
'';
};
+ debug = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to enable debug logging for freeradius (-xx
+ option). This should not be left on, since it includes
+ sensitive data such as passwords in the logs.
+ '';
+ };
+
};
in
@@ -66,6 +77,7 @@ in
};
systemd.services.freeradius = freeradiusService cfg;
+ warnings = optional cfg.debug "Freeradius debug logging is enabled. This will log passwords in plaintext to the journal!";
};
diff --git a/nixpkgs/nixos/modules/services/networking/git-daemon.nix b/nixpkgs/nixos/modules/services/networking/git-daemon.nix
index 6f2e149433f..52c895215fb 100644
--- a/nixpkgs/nixos/modules/services/networking/git-daemon.nix
+++ b/nixpkgs/nixos/modules/services/networking/git-daemon.nix
@@ -104,14 +104,14 @@ in
config = mkIf cfg.enable {
- users.users = optionalAttrs (cfg.user != "git") {
+ users.users = optionalAttrs (cfg.user == "git") {
git = {
uid = config.ids.uids.git;
description = "Git daemon user";
};
};
- users.groups = optionalAttrs (cfg.group != "git") {
+ users.groups = optionalAttrs (cfg.group == "git") {
git.gid = config.ids.gids.git;
};
diff --git a/nixpkgs/nixos/modules/services/networking/haproxy.nix b/nixpkgs/nixos/modules/services/networking/haproxy.nix
index aff71e5e97d..4678829986c 100644
--- a/nixpkgs/nixos/modules/services/networking/haproxy.nix
+++ b/nixpkgs/nixos/modules/services/networking/haproxy.nix
@@ -26,6 +26,18 @@ with lib;
'';
};
+ user = mkOption {
+ type = types.str;
+ default = "haproxy";
+ description = "User account under which haproxy runs.";
+ };
+
+ group = mkOption {
+ type = types.str;
+ default = "haproxy";
+ description = "Group account under which haproxy runs.";
+ };
+
config = mkOption {
type = types.nullOr types.lines;
default = null;
@@ -49,7 +61,8 @@ with lib;
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
- DynamicUser = true;
+ User = cfg.user;
+ Group = cfg.group;
Type = "notify";
# when running the config test, don't be quiet so we can see what goes wrong
ExecStartPre = "${pkgs.haproxy}/sbin/haproxy -c -f ${haproxyCfg}";
@@ -60,5 +73,16 @@ with lib;
AmbientCapabilities = "CAP_NET_BIND_SERVICE";
};
};
+
+ users.users = optionalAttrs (cfg.user == "haproxy") {
+ haproxy = {
+ group = cfg.group;
+ isSystemUser = true;
+ };
+ };
+
+ users.groups = optionalAttrs (cfg.group == "haproxy") {
+ haproxy = {};
+ };
};
}
diff --git a/nixpkgs/nixos/modules/services/networking/i2pd.nix b/nixpkgs/nixos/modules/services/networking/i2pd.nix
index 326d34f6ca9..93a21fd4c97 100644
--- a/nixpkgs/nixos/modules/services/networking/i2pd.nix
+++ b/nixpkgs/nixos/modules/services/networking/i2pd.nix
@@ -158,10 +158,10 @@ let
(sec "addressbook")
(strOpt "defaulturl" cfg.addressbook.defaulturl)
] ++ (optionalEmptyList "subscriptions" cfg.addressbook.subscriptions)
- ++ (flip mapAttrs
- (collect (name: proto: proto ? port && proto ? address && proto ? name) cfg.proto)
+ ++ (flip map
+ (collect (proto: proto ? port && proto ? address) cfg.proto)
(proto: let protoOpts = [
- (sec name)
+ (sec proto.name)
(boolOpt "enabled" proto.enable)
(strOpt "address" proto.address)
(intOpt "port" proto.port)
@@ -181,10 +181,10 @@ let
tunnelConf = let opts = [
notice
- (flip mapAttrs
- (collect (name: tun: tun ? port && tun ? destination) cfg.outTunnels)
+ (flip map
+ (collect (tun: tun ? port && tun ? destination) cfg.outTunnels)
(tun: let outTunOpts = [
- (sec name)
+ (sec tun.name)
"type = client"
(intOpt "port" tun.port)
(strOpt "destination" tun.destination)
@@ -204,10 +204,10 @@ let
++ (if tun ? crypto.tagsToSend then
optionalNullInt "crypto.tagstosend" tun.crypto.tagsToSend else []);
in concatStringsSep "\n" outTunOpts))
- (flip mapAttrs
- (collect (name: tun: tun ? port && tun ? address) cfg.inTunnels)
+ (flip map
+ (collect (tun: tun ? port && tun ? address) cfg.inTunnels)
(tun: let inTunOpts = [
- (sec name)
+ (sec tun.name)
"type = server"
(intOpt "port" tun.port)
(strOpt "host" tun.address)
@@ -606,7 +606,7 @@ in
outTunnels = mkOption {
default = {};
- type = with types; loaOf (submodule (
+ type = with types; attrsOf (submodule (
{ name, ... }: {
options = {
destinationPort = mkOption {
@@ -627,7 +627,7 @@ in
inTunnels = mkOption {
default = {};
- type = with types; loaOf (submodule (
+ type = with types; attrsOf (submodule (
{ name, ... }: {
options = {
inPort = mkOption {
diff --git a/nixpkgs/nixos/modules/services/networking/iodine.nix b/nixpkgs/nixos/modules/services/networking/iodine.nix
index f9ca26c2796..46051d7044b 100644
--- a/nixpkgs/nixos/modules/services/networking/iodine.nix
+++ b/nixpkgs/nixos/modules/services/networking/iodine.nix
@@ -9,6 +9,8 @@ let
iodinedUser = "iodined";
+ /* is this path made unreadable by ProtectHome = true ? */
+ isProtected = x: hasPrefix "/root" x || hasPrefix "/home" x;
in
{
imports = [
@@ -35,45 +37,48 @@ in
corresponding attribute name.
'';
example = literalExample ''
- {
- foo = {
- server = "tunnel.mdomain.com";
- relay = "8.8.8.8";
- extraConfig = "-v";
+ {
+ foo = {
+ server = "tunnel.mdomain.com";
+ relay = "8.8.8.8";
+ extraConfig = "-v";
+ }
}
- }
'';
- type = types.attrsOf (types.submodule (
- {
- options = {
- server = mkOption {
- type = types.str;
- default = "";
- description = "Domain or Subdomain of server running iodined";
- example = "tunnel.mydomain.com";
- };
-
- relay = mkOption {
- type = types.str;
- default = "";
- description = "DNS server to use as a intermediate relay to the iodined server";
- example = "8.8.8.8";
- };
-
- extraConfig = mkOption {
- type = types.str;
- default = "";
- description = "Additional command line parameters";
- example = "-l 192.168.1.10 -p 23";
- };
-
- passwordFile = mkOption {
- type = types.str;
- default = "";
- description = "File that contains password";
- };
- };
- }));
+ type = types.attrsOf (
+ types.submodule (
+ {
+ options = {
+ server = mkOption {
+ type = types.str;
+ default = "";
+ description = "Hostname of server running iodined";
+ example = "tunnel.mydomain.com";
+ };
+
+ relay = mkOption {
+ type = types.str;
+ default = "";
+ description = "DNS server to use as an intermediate relay to the iodined server";
+ example = "8.8.8.8";
+ };
+
+ extraConfig = mkOption {
+ type = types.str;
+ default = "";
+ description = "Additional command line parameters";
+ example = "-l 192.168.1.10 -p 23";
+ };
+
+ passwordFile = mkOption {
+ type = types.str;
+ default = "";
+ description = "Path to a file containing the password.";
+ };
+ };
+ }
+ )
+ );
};
server = {
@@ -121,31 +126,67 @@ in
boot.kernelModules = [ "tun" ];
systemd.services =
- let
- createIodineClientService = name: cfg:
- {
- description = "iodine client - ${name}";
- after = [ "network.target" ];
- wantedBy = [ "multi-user.target" ];
- script = "exec ${pkgs.iodine}/bin/iodine -f -u ${iodinedUser} ${cfg.extraConfig} ${optionalString (cfg.passwordFile != "") "< \"${cfg.passwordFile}\""} ${cfg.relay} ${cfg.server}";
- serviceConfig = {
- RestartSec = "30s";
- Restart = "always";
+ let
+ createIodineClientService = name: cfg:
+ {
+ description = "iodine client - ${name}";
+ after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ script = "exec ${pkgs.iodine}/bin/iodine -f -u ${iodinedUser} ${cfg.extraConfig} ${optionalString (cfg.passwordFile != "") "< \"${builtins.toString cfg.passwordFile}\""} ${cfg.relay} ${cfg.server}";
+ serviceConfig = {
+ RestartSec = "30s";
+ Restart = "always";
+
+ # hardening :
+ # Filesystem access
+ ProtectSystem = "strict";
+ ProtectHome = if isProtected cfg.passwordFile then "read-only" else "true" ;
+ PrivateTmp = true;
+ ReadWritePaths = "/dev/net/tun";
+ PrivateDevices = false;
+ ProtectKernelTunables = true;
+ ProtectKernelModules = true;
+ ProtectControlGroups = true;
+ # Caps
+ NoNewPrivileges = true;
+ # Misc.
+ LockPersonality = true;
+ RestrictRealtime = true;
+ PrivateMounts = true;
+ MemoryDenyWriteExecute = true;
+ };
+ };
+ in
+ listToAttrs (
+ mapAttrsToList
+ (name: value: nameValuePair "iodine-${name}" (createIodineClientService name value))
+ cfg.clients
+ ) // {
+ iodined = mkIf (cfg.server.enable) {
+ description = "iodine, ip over dns server daemon";
+ after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ script = "exec ${pkgs.iodine}/bin/iodined -f -u ${iodinedUser} ${cfg.server.extraConfig} ${optionalString (cfg.server.passwordFile != "") "< \"${builtins.toString cfg.server.passwordFile}\""} ${cfg.server.ip} ${cfg.server.domain}";
+ serviceConfig = {
+ # Filesystem access
+ ProtectSystem = "strict";
+ ProtectHome = if isProtected cfg.server.passwordFile then "read-only" else "true" ;
+ PrivateTmp = true;
+ ReadWritePaths = "/dev/net/tun";
+ PrivateDevices = false;
+ ProtectKernelTunables = true;
+ ProtectKernelModules = true;
+ ProtectControlGroups = true;
+ # Caps
+ NoNewPrivileges = true;
+ # Misc.
+ LockPersonality = true;
+ RestrictRealtime = true;
+ PrivateMounts = true;
+ MemoryDenyWriteExecute = true;
+ };
+ };
};
- };
- in
- listToAttrs (
- mapAttrsToList
- (name: value: nameValuePair "iodine-${name}" (createIodineClientService name value))
- cfg.clients
- ) // {
- iodined = mkIf (cfg.server.enable) {
- description = "iodine, ip over dns server daemon";
- after = [ "network.target" ];
- wantedBy = [ "multi-user.target" ];
- script = "exec ${pkgs.iodine}/bin/iodined -f -u ${iodinedUser} ${cfg.server.extraConfig} ${optionalString (cfg.server.passwordFile != "") "< \"${cfg.server.passwordFile}\""} ${cfg.server.ip} ${cfg.server.domain}";
- };
- };
users.users.${iodinedUser} = {
uid = config.ids.uids.iodined;
diff --git a/nixpkgs/nixos/modules/services/networking/iwd.nix b/nixpkgs/nixos/modules/services/networking/iwd.nix
index 839fa48d9a4..6be67a8b96f 100644
--- a/nixpkgs/nixos/modules/services/networking/iwd.nix
+++ b/nixpkgs/nixos/modules/services/networking/iwd.nix
@@ -23,12 +23,7 @@ in {
systemd.packages = [ pkgs.iwd ];
systemd.services.iwd.wantedBy = [ "multi-user.target" ];
-
- systemd.tmpfiles.rules = [
- "d /var/lib/iwd 0700 root root -"
- "d /var/lib/ead 0700 root root -"
- ];
};
- meta.maintainers = with lib.maintainers; [ mic92 ];
+ meta.maintainers = with lib.maintainers; [ mic92 dtzWill ];
}
diff --git a/nixpkgs/nixos/modules/services/networking/knot.nix b/nixpkgs/nixos/modules/services/networking/knot.nix
index 47364ecb846..12ff89fe849 100644
--- a/nixpkgs/nixos/modules/services/networking/knot.nix
+++ b/nixpkgs/nixos/modules/services/networking/knot.nix
@@ -5,14 +5,16 @@ with lib;
let
cfg = config.services.knot;
- configFile = pkgs.writeText "knot.conf" cfg.extraConfig;
- socketFile = "/run/knot/knot.sock";
+ configFile = pkgs.writeTextFile {
+ name = "knot.conf";
+ text = (concatMapStringsSep "\n" (file: "include: ${file}") cfg.keyFiles) + "\n" +
+ cfg.extraConfig;
+ checkPhase = lib.optionalString (cfg.keyFiles == []) ''
+ ${cfg.package}/bin/knotc --config=$out conf-check
+ '';
+ };
- knotConfCheck = file: pkgs.runCommand "knot-config-checked"
- { buildInputs = [ cfg.package ]; } ''
- ln -s ${configFile} $out
- knotc --config=${configFile} conf-check
- '';
+ socketFile = "/run/knot/knot.sock";
knot-cli-wrappers = pkgs.stdenv.mkDerivation {
name = "knot-cli-wrappers";
@@ -45,6 +47,19 @@ in {
'';
};
+ keyFiles = mkOption {
+ type = types.listOf types.path;
+ default = [];
+ description = ''
+ A list of files containing additional configuration
+ to be included using the include directive. This option
+ allows to include configuration like TSIG keys without
+ exposing them to the nix store readable to any process.
+ Note that using this option will also disable configuration
+ checks at build time.
+ '';
+ };
+
extraConfig = mkOption {
type = types.lines;
default = "";
@@ -65,6 +80,13 @@ in {
};
config = mkIf config.services.knot.enable {
+ users.users.knot = {
+ isSystemUser = true;
+ group = "knot";
+ description = "Knot daemon user";
+ };
+
+ users.groups.knot.gid = null;
systemd.services.knot = {
unitConfig.Documentation = "man:knotd(8) man:knot.conf(5) man:knotc(8) https://www.knot-dns.cz/docs/${cfg.package.version}/html/";
description = cfg.package.meta.description;
@@ -74,12 +96,12 @@ in {
serviceConfig = {
Type = "notify";
- ExecStart = "${cfg.package}/bin/knotd --config=${knotConfCheck configFile} --socket=${socketFile} ${concatStringsSep " " cfg.extraArgs}";
+ ExecStart = "${cfg.package}/bin/knotd --config=${configFile} --socket=${socketFile} ${concatStringsSep " " cfg.extraArgs}";
ExecReload = "${knot-cli-wrappers}/bin/knotc reload";
CapabilityBoundingSet = "CAP_NET_BIND_SERVICE CAP_SETPCAP";
AmbientCapabilities = "CAP_NET_BIND_SERVICE CAP_SETPCAP";
NoNewPrivileges = true;
- DynamicUser = "yes";
+ User = "knot";
RuntimeDirectory = "knot";
StateDirectory = "knot";
StateDirectoryMode = "0700";
diff --git a/nixpkgs/nixos/modules/services/networking/kresd.nix b/nixpkgs/nixos/modules/services/networking/kresd.nix
index bb941e93e15..c5a84eebd46 100644
--- a/nixpkgs/nixos/modules/services/networking/kresd.nix
+++ b/nixpkgs/nixos/modules/services/networking/kresd.nix
@@ -3,16 +3,38 @@
with lib;
let
-
cfg = config.services.kresd;
- configFile = pkgs.writeText "kresd.conf" ''
- ${optionalString (cfg.listenDoH != []) "modules.load('http')"}
- ${cfg.extraConfig};
- '';
- package = pkgs.knot-resolver.override {
- extraFeatures = cfg.listenDoH != [];
- };
+ # Convert systemd-style address specification to kresd config line(s).
+ # On Nix level we don't attempt to precisely validate the address specifications.
+ mkListen = kind: addr: let
+ al_v4 = builtins.match "([0-9.]\+):([0-9]\+)" addr;
+ al_v6 = builtins.match "\\[(.\+)]:([0-9]\+)" addr;
+ al_portOnly = builtins.match "()([0-9]\+)" addr;
+ al = findFirst (a: a != null)
+ (throw "services.kresd.*: incorrect address specification '${addr}'")
+ [ al_v4 al_v6 al_portOnly ];
+ port = last al;
+ addrSpec = if al_portOnly == null then "'${head al}'" else "{'::', '127.0.0.1'}";
+ in # freebind is set for compatibility with earlier kresd services;
+ # it could be configurable, for example.
+ ''
+ net.listen(${addrSpec}, ${port}, { kind = '${kind}', freebind = true })
+ '';
+
+ configFile = pkgs.writeText "kresd.conf" (
+ optionalString (cfg.listenDoH != []) ''
+ modules.load('http')
+ ''
+ + concatMapStrings (mkListen "dns") cfg.listenPlain
+ + concatMapStrings (mkListen "tls") cfg.listenTLS
+ + concatMapStrings (mkListen "doh") cfg.listenDoH
+ + cfg.extraConfig
+ );
+
+ package = if cfg.listenDoH == []
+ then pkgs.knot-resolver # never force `extraFeatures = false`
+ else pkgs.knot-resolver.override { extraFeatures = true; };
in {
meta.maintainers = [ maintainers.vcunat /* upstream developer */ ];
@@ -25,6 +47,7 @@ in {
value
)
)
+ (mkRemovedOptionModule [ "services" "kresd" "cacheDir" ] "Please use (bind-)mounting instead.")
];
###### interface
@@ -35,8 +58,8 @@ in {
description = ''
Whether to enable knot-resolver domain name server.
DNSSEC validation is turned on by default.
- You can run <literal>sudo nc -U /run/kresd/control</literal>
- and give commands interactively to kresd.
+ You can run <literal>sudo nc -U /run/knot-resolver/control/1</literal>
+ and give commands interactively to kresd@1.service.
'';
};
extraConfig = mkOption {
@@ -46,16 +69,10 @@ in {
Extra lines to be added verbatim to the generated configuration file.
'';
};
- cacheDir = mkOption {
- type = types.path;
- default = "/var/cache/kresd";
- description = ''
- Directory for caches. They are intended to survive reboots.
- '';
- };
listenPlain = mkOption {
type = with types; listOf str;
default = [ "[::1]:53" "127.0.0.1:53" ];
+ example = [ "53" ];
description = ''
What addresses and ports the server should listen on.
For detailed syntax see ListenStream in man systemd.socket.
@@ -75,91 +92,54 @@ in {
default = [];
example = [ "198.51.100.1:443" "[2001:db8::1]:443" "443" ];
description = ''
- Addresses and ports on which kresd should provide DNS over HTTPS (see RFC 7858).
+ Addresses and ports on which kresd should provide DNS over HTTPS (see RFC 8484).
For detailed syntax see ListenStream in man systemd.socket.
'';
};
+ instances = mkOption {
+ type = types.ints.unsigned;
+ default = 1;
+ description = ''
+ The number of instances to start. They will be called kresd@{1,2,...}.service.
+ Knot Resolver uses no threads, so this is the way to scale.
+ You can dynamically start/stop them at will, so this is just system default.
+ '';
+ };
# TODO: perhaps options for more common stuff like cache size or forwarding
};
###### implementation
config = mkIf cfg.enable {
- environment.etc."kresd.conf".source = configFile; # not required
+ environment.etc."knot-resolver/kresd.conf".source = configFile; # not required
- users.users.kresd =
- { uid = config.ids.uids.kresd;
- group = "kresd";
+ users.users.knot-resolver =
+ { isSystemUser = true;
+ group = "knot-resolver";
description = "Knot-resolver daemon user";
};
- users.groups.kresd.gid = config.ids.gids.kresd;
-
- systemd.sockets.kresd = rec {
- wantedBy = [ "sockets.target" ];
- before = wantedBy;
- listenStreams = cfg.listenPlain;
- socketConfig = {
- ListenDatagram = listenStreams;
- FreeBind = true;
- FileDescriptorName = "dns";
- };
- };
+ users.groups.knot-resolver.gid = null;
- systemd.sockets.kresd-tls = mkIf (cfg.listenTLS != []) rec {
- wantedBy = [ "sockets.target" ];
- before = wantedBy;
- partOf = [ "kresd.socket" ];
- listenStreams = cfg.listenTLS;
- socketConfig = {
- FileDescriptorName = "tls";
- FreeBind = true;
- Service = "kresd.service";
- };
- };
+ systemd.packages = [ package ]; # the units are patched inside the package a bit
- systemd.sockets.kresd-doh = mkIf (cfg.listenDoH != []) rec {
- wantedBy = [ "sockets.target" ];
- before = wantedBy;
- partOf = [ "kresd.socket" ];
- listenStreams = cfg.listenDoH;
- socketConfig = {
- FileDescriptorName = "doh";
- FreeBind = true;
- Service = "kresd.service";
- };
+ systemd.targets.kresd = { # configure units started by default
+ wantedBy = [ "multi-user.target" ];
+ wants = [ "kres-cache-gc.service" ]
+ ++ map (i: "kresd@${toString i}.service") (range 1 cfg.instances);
};
-
- systemd.sockets.kresd-control = rec {
- wantedBy = [ "sockets.target" ];
- before = wantedBy;
- partOf = [ "kresd.socket" ];
- listenStreams = [ "/run/kresd/control" ];
- socketConfig = {
- FileDescriptorName = "control";
- Service = "kresd.service";
- SocketMode = "0660"; # only root user/group may connect and control kresd
- };
+ systemd.services."kresd@".serviceConfig = {
+ ExecStart = "${package}/bin/kresd --noninteractive "
+ + "-c ${package}/lib/knot-resolver/distro-preconfig.lua -c ${configFile}";
+ # Ensure correct ownership in case UID or GID changes.
+ CacheDirectory = "knot-resolver";
+ CacheDirectoryMode = "0750";
};
- systemd.tmpfiles.rules = [ "d '${cfg.cacheDir}' 0770 kresd kresd - -" ];
+ environment.etc."tmpfiles.d/knot-resolver.conf".source =
+ "${package}/lib/tmpfiles.d/knot-resolver.conf";
- systemd.services.kresd = {
- description = "Knot-resolver daemon";
-
- serviceConfig = {
- User = "kresd";
- Type = "notify";
- WorkingDirectory = cfg.cacheDir;
- Restart = "on-failure";
- Sockets = [ "kresd.socket" "kresd-control.socket" ]
- ++ optional (cfg.listenTLS != []) "kresd-tls.socket";
- };
-
- # Trust anchor goes from dns-root-data by default.
- script = ''
- exec '${package}/bin/kresd' --config '${configFile}' --forks=1
- '';
-
- requires = [ "kresd.socket" ];
- };
+ # Try cleaning up the previously default location of cache file.
+ # Note that /var/cache/* should always be safe to remove.
+ # TODO: remove later, probably between 20.09 and 21.03
+ systemd.tmpfiles.rules = [ "R /var/cache/kresd" ];
};
}
diff --git a/nixpkgs/nixos/modules/services/networking/minidlna.nix b/nixpkgs/nixos/modules/services/networking/minidlna.nix
index 3ddea3c9757..c580ba47dad 100644
--- a/nixpkgs/nixos/modules/services/networking/minidlna.nix
+++ b/nixpkgs/nixos/modules/services/networking/minidlna.nix
@@ -95,6 +95,22 @@ in
'';
};
+ services.minidlna.announceInterval = mkOption {
+ type = types.int;
+ default = 895;
+ description =
+ ''
+ The interval between announces (in seconds).
+
+ By default miniDLNA will announce its presence on the network
+ approximately every 15 minutes.
+
+ Many people prefer shorter announce intervals (e.g. 60 seconds)
+ on their home networks, especially when DLNA clients are
+ started on demand.
+ '';
+ };
+
services.minidlna.config = mkOption {
type = types.lines;
description =
@@ -144,6 +160,7 @@ in
${concatMapStrings (dir: ''
media_dir=${dir}
'') cfg.mediaDirs}
+ notify_interval=${toString cfg.announceInterval}
${cfg.extraConfig}
'';
diff --git a/nixpkgs/nixos/modules/services/networking/nat.nix b/nixpkgs/nixos/modules/services/networking/nat.nix
index 9c658af30f7..21ae9eb8b6d 100644
--- a/nixpkgs/nixos/modules/services/networking/nat.nix
+++ b/nixpkgs/nixos/modules/services/networking/nat.nix
@@ -65,7 +65,7 @@ let
let
m = builtins.match "([0-9.]+):([0-9-]+)" fwd.destination;
destinationIP = if (m == null) then throw "bad ip:ports `${fwd.destination}'" else elemAt m 0;
- destinationPorts = if (m == null) then throw "bad ip:ports `${fwd.destination}'" else elemAt m 1;
+ destinationPorts = if (m == null) then throw "bad ip:ports `${fwd.destination}'" else builtins.replaceStrings ["-"] [":"] (elemAt m 1);
in ''
# Allow connections to ${loopbackip}:${toString fwd.sourcePort} from the host itself
iptables -w -t nat -A nixos-nat-out \
diff --git a/nixpkgs/nixos/modules/services/networking/nix-store-gcs-proxy.nix b/nixpkgs/nixos/modules/services/networking/nix-store-gcs-proxy.nix
new file mode 100644
index 00000000000..3f2ce5bca4d
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/nix-store-gcs-proxy.nix
@@ -0,0 +1,75 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ opts = { name, config, ... }: {
+ options = {
+ enable = mkOption {
+ default = true;
+ type = types.bool;
+ example = true;
+ description = "Whether to enable proxy for this bucket";
+ };
+ bucketName = mkOption {
+ type = types.str;
+ default = name;
+ example = "my-bucket-name";
+ description = "Name of Google storage bucket";
+ };
+ address = mkOption {
+ type = types.str;
+ example = "localhost:3000";
+ description = "The address of the proxy.";
+ };
+ };
+ };
+ enabledProxies = lib.filterAttrs (n: v: v.enable) config.services.nix-store-gcs-proxy;
+ mapProxies = function: lib.mkMerge (lib.mapAttrsToList function enabledProxies);
+in
+{
+ options.services.nix-store-gcs-proxy = mkOption {
+ type = types.attrsOf (types.submodule opts);
+ default = {};
+ description = ''
+ An attribute set describing an HTTP to GCS proxy that allows us to use GCS
+ bucket via HTTP protocol.
+ '';
+ };
+
+ config.systemd.services = mapProxies (name: cfg: {
+ "nix-store-gcs-proxy-${name}" = {
+ description = "A HTTP nix store that proxies requests to Google Storage";
+ wantedBy = ["multi-user.target"];
+
+ serviceConfig = {
+ RestartSec = 5;
+ StartLimitInterval = 10;
+ ExecStart = ''
+ ${pkgs.nix-store-gcs-proxy}/bin/nix-store-gcs-proxy \
+ --bucket-name ${cfg.bucketName} \
+ --addr ${cfg.address}
+ '';
+
+ DynamicUser = true;
+
+ ProtectSystem = "strict";
+ ProtectHome = true;
+ PrivateTmp = true;
+ PrivateDevices = true;
+ PrivateMounts = true;
+ PrivateUsers = true;
+
+ ProtectKernelTunables = true;
+ ProtectKernelModules = true;
+ ProtectControlGroups = true;
+
+ NoNewPrivileges = true;
+ LockPersonality = true;
+ RestrictRealtime = true;
+ };
+ };
+ });
+
+ meta.maintainers = [ maintainers.mrkkrp ];
+}
diff --git a/nixpkgs/nixos/modules/services/networking/nsd.nix b/nixpkgs/nixos/modules/services/networking/nsd.nix
index 344396638a6..429580e5c6c 100644
--- a/nixpkgs/nixos/modules/services/networking/nsd.nix
+++ b/nixpkgs/nixos/modules/services/networking/nsd.nix
@@ -244,7 +244,7 @@ let
};
data = mkOption {
- type = types.str;
+ type = types.lines;
default = "";
example = "";
description = ''
@@ -484,7 +484,7 @@ in
};
extraConfig = mkOption {
- type = types.str;
+ type = types.lines;
default = "";
description = ''
Extra nsd config.
diff --git a/nixpkgs/nixos/modules/services/networking/ntp/ntpd.nix b/nixpkgs/nixos/modules/services/networking/ntp/ntpd.nix
index b5403cb747d..54ff054d84c 100644
--- a/nixpkgs/nixos/modules/services/networking/ntp/ntpd.nix
+++ b/nixpkgs/nixos/modules/services/networking/ntp/ntpd.nix
@@ -23,6 +23,8 @@ let
restrict -6 ::1
${toString (map (server: "server " + server + " iburst\n") cfg.servers)}
+
+ ${cfg.extraConfig}
'';
ntpFlags = "-c ${configFile} -u ${ntpUser}:nogroup ${toString cfg.extraFlags}";
@@ -81,6 +83,17 @@ in
'';
};
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ example = ''
+ fudge 127.127.1.0 stratum 10
+ '';
+ description = ''
+ Additional text appended to <filename>ntp.conf</filename>.
+ '';
+ };
+
extraFlags = mkOption {
type = types.listOf types.str;
description = "Extra flags passed to the ntpd command.";
diff --git a/nixpkgs/nixos/modules/services/networking/pppd.nix b/nixpkgs/nixos/modules/services/networking/pppd.nix
index b31bfa64235..c1cbdb46176 100644
--- a/nixpkgs/nixos/modules/services/networking/pppd.nix
+++ b/nixpkgs/nixos/modules/services/networking/pppd.nix
@@ -130,7 +130,7 @@ in
systemdConfigs = listToAttrs (map mkSystemd enabledConfigs);
in mkIf cfg.enable {
- environment.etc = mkMerge etcFiles;
- systemd.services = mkMerge systemdConfigs;
+ environment.etc = etcFiles;
+ systemd.services = systemdConfigs;
};
}
diff --git a/nixpkgs/nixos/modules/services/networking/shorewall.nix b/nixpkgs/nixos/modules/services/networking/shorewall.nix
index 0f94d414fcf..16383be2530 100644
--- a/nixpkgs/nixos/modules/services/networking/shorewall.nix
+++ b/nixpkgs/nixos/modules/services/networking/shorewall.nix
@@ -26,7 +26,7 @@ in {
description = "The shorewall package to use.";
};
configs = lib.mkOption {
- type = types.attrsOf types.str;
+ type = types.attrsOf types.lines;
default = {};
description = ''
This option defines the Shorewall configs.
@@ -63,12 +63,7 @@ in {
'';
};
environment = {
- etc = lib.mapAttrsToList
- (name: file:
- { source = file;
- target = "shorewall/${name}";
- })
- cfg.configs;
+ etc = lib.mapAttrs' (name: conf: lib.nameValuePair "shorewall/${name}" {source=conf;}) cfg.configs;
systemPackages = [ cfg.package ];
};
};
diff --git a/nixpkgs/nixos/modules/services/networking/shorewall6.nix b/nixpkgs/nixos/modules/services/networking/shorewall6.nix
index 9c22a037c0b..e081aedc6c3 100644
--- a/nixpkgs/nixos/modules/services/networking/shorewall6.nix
+++ b/nixpkgs/nixos/modules/services/networking/shorewall6.nix
@@ -26,7 +26,7 @@ in {
description = "The shorewall package to use.";
};
configs = lib.mkOption {
- type = types.attrsOf types.str;
+ type = types.attrsOf types.lines;
default = {};
description = ''
This option defines the Shorewall configs.
@@ -63,12 +63,7 @@ in {
'';
};
environment = {
- etc = lib.mapAttrsToList
- (name: file:
- { source = file;
- target = "shorewall6/${name}";
- })
- cfg.configs;
+ etc = lib.mapAttrs' (name: conf: lib.nameValuePair "shorewall6/${name}" {source=conf;}) cfg.configs;
systemPackages = [ cfg.package ];
};
};
diff --git a/nixpkgs/nixos/modules/services/networking/smartdns.nix b/nixpkgs/nixos/modules/services/networking/smartdns.nix
new file mode 100644
index 00000000000..f1888af7041
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/smartdns.nix
@@ -0,0 +1,61 @@
+{ lib, pkgs, config, ... }:
+
+with lib;
+
+let
+ inherit (lib.types) attrsOf coercedTo listOf oneOf str int bool;
+ cfg = config.services.smartdns;
+
+ confFile = pkgs.writeText "smartdns.conf" (with generators;
+ toKeyValue {
+ mkKeyValue = mkKeyValueDefault {
+ mkValueString = v:
+ if isBool v then
+ if v then "yes" else "no"
+ else
+ mkValueStringDefault { } v;
+ } " ";
+ listsAsDuplicateKeys =
+ true; # Allowing duplications because we need to deal with multiple entries with the same key.
+ } cfg.settings);
+in {
+ options.services.smartdns = {
+ enable = mkEnableOption "SmartDNS DNS server";
+
+ bindPort = mkOption {
+ type = types.port;
+ default = 53;
+ description = "DNS listening port number.";
+ };
+
+ settings = mkOption {
+ type =
+ let atom = oneOf [ str int bool ];
+ in attrsOf (coercedTo atom toList (listOf atom));
+ example = literalExample ''
+ {
+ bind = ":5353 -no-rule -group example";
+ cache-size = 4096;
+ server-tls = [ "8.8.8.8:853" "1.1.1.1:853" ];
+ server-https = "https://cloudflare-dns.com/dns-query -exclude-default-group";
+ prefetch-domain = true;
+ speed-check-mode = "ping,tcp:80";
+ };
+ '';
+ description = ''
+ A set that will be generated into configuration file, see the <link xlink:href="https://github.com/pymumu/smartdns/blob/master/ReadMe_en.md#configuration-parameter">SmartDNS README</link> for details of configuration parameters.
+ You could override the options here like <option>services.smartdns.bindPort</option> by writing <literal>settings.bind = ":5353 -no-rule -group example";</literal>.
+ '';
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ services.smartdns.settings.bind = mkDefault ":${toString cfg.bindPort}";
+
+ systemd.packages = [ pkgs.smartdns ];
+ systemd.services.smartdns.wantedBy = [ "multi-user.target" ];
+ environment.etc."smartdns/smartdns.conf".source = confFile;
+ environment.etc."default/smartdns".source =
+ "${pkgs.smartdns}/etc/default/smartdns";
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/networking/ssh/sshd.nix b/nixpkgs/nixos/modules/services/networking/ssh/sshd.nix
index b0e2e303cbc..464e9ed38c4 100644
--- a/nixpkgs/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixpkgs/nixos/modules/services/networking/ssh/sshd.nix
@@ -17,7 +17,7 @@ let
${cfg.extraConfig}
EOL
- ssh-keygen -f mock-hostkey -N ""
+ ssh-keygen -q -f mock-hostkey -N ""
sshd -t -f $out -h mock-hostkey
'';
@@ -238,6 +238,26 @@ in
description = "Files from which authorized keys are read.";
};
+ authorizedKeysCommand = mkOption {
+ type = types.str;
+ default = "none";
+ description = ''
+ Specifies a program to be used to look up the user's public
+ keys. The program must be owned by root, not writable by group
+ or others and specified by an absolute path.
+ '';
+ };
+
+ authorizedKeysCommandUser = mkOption {
+ type = types.str;
+ default = "nobody";
+ description = ''
+ Specifies the user under whose account the AuthorizedKeysCommand
+ is run. It is recommended to use a dedicated user that has no
+ other role on the host than running authorized keys commands.
+ '';
+ };
+
kexAlgorithms = mkOption {
type = types.listOf types.str;
default = [
@@ -485,6 +505,10 @@ in
PrintMotd no # handled by pam_motd
AuthorizedKeysFile ${toString cfg.authorizedKeysFiles}
+ ${optionalString (cfg.authorizedKeysCommand != "none") ''
+ AuthorizedKeysCommand ${cfg.authorizedKeysCommand}
+ AuthorizedKeysCommandUser ${cfg.authorizedKeysCommandUser}
+ ''}
${flip concatMapStrings cfg.hostKeys (k: ''
HostKey ${k.path}
diff --git a/nixpkgs/nixos/modules/services/networking/sslh.nix b/nixpkgs/nixos/modules/services/networking/sslh.nix
index 0222e8ce8b5..c4fa370a5fe 100644
--- a/nixpkgs/nixos/modules/services/networking/sslh.nix
+++ b/nixpkgs/nixos/modules/services/networking/sslh.nix
@@ -77,19 +77,14 @@ in
config = mkMerge [
(mkIf cfg.enable {
- users.users.${user} = {
- description = "sslh daemon user";
- isSystemUser = true;
- };
-
systemd.services.sslh = {
description = "Applicative Protocol Multiplexer (e.g. share SSH and HTTPS on the same port)";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
- User = user;
- Group = "nogroup";
+ DynamicUser = true;
+ User = "sslh";
PermissionsStartOnly = true;
Restart = "always";
RestartSec = "1s";
diff --git a/nixpkgs/nixos/modules/services/networking/stubby.nix b/nixpkgs/nixos/modules/services/networking/stubby.nix
index b38bcd4cec0..c5e0f929a12 100644
--- a/nixpkgs/nixos/modules/services/networking/stubby.nix
+++ b/nixpkgs/nixos/modules/services/networking/stubby.nix
@@ -72,6 +72,7 @@ let
resolution_type: GETDNS_RESOLUTION_STUB
dns_transport_list:
${fallbacks}
+ appdata_dir: "/var/cache/stubby"
tls_authentication: ${cfg.authenticationMode}
tls_query_padding_blocksize: ${toString cfg.queryPaddingBlocksize}
edns_client_subnet_private: ${if cfg.subnetPrivate then "1" else "0"}
@@ -204,10 +205,12 @@ in
wantedBy = [ "multi-user.target" ];
serviceConfig = {
+ Type = "notify";
AmbientCapabilities = "CAP_NET_BIND_SERVICE";
CapabilityBoundingSet = "CAP_NET_BIND_SERVICE";
ExecStart = "${pkgs.stubby}/bin/stubby -C ${confFile} ${optionalString cfg.debugLogging "-l"}";
DynamicUser = true;
+ CacheDirectory = "stubby";
};
};
};
diff --git a/nixpkgs/nixos/modules/services/networking/supybot.nix b/nixpkgs/nixos/modules/services/networking/supybot.nix
index 92c84bd0e1e..dc9fb31ffd0 100644
--- a/nixpkgs/nixos/modules/services/networking/supybot.nix
+++ b/nixpkgs/nixos/modules/services/networking/supybot.nix
@@ -3,32 +3,35 @@
with lib;
let
-
cfg = config.services.supybot;
-
+ isStateDirHome = hasPrefix "/home/" cfg.stateDir;
+ isStateDirVar = cfg.stateDir == "/var/lib/supybot";
+ pyEnv = pkgs.python3.withPackages (p: [ p.limnoria ] ++ (cfg.extraPackages p));
in
-
{
-
options = {
services.supybot = {
enable = mkOption {
+ type = types.bool;
default = false;
- description = "Enable Supybot, an IRC bot";
+ description = "Enable Supybot, an IRC bot (also known as Limnoria).";
};
stateDir = mkOption {
- # Setting this to /var/lib/supybot caused useradd to fail
- default = "/home/supybot";
+ type = types.path;
+ default = if versionAtLeast config.system.stateVersion "20.09"
+ then "/var/lib/supybot"
+ else "/home/supybot";
+ defaultText = "/var/lib/supybot";
description = "The root directory, logs and plugins are stored here";
};
configFile = mkOption {
type = types.path;
description = ''
- Path to a supybot config file. This can be generated by
+ Path to initial supybot config file. This can be generated by
running supybot-wizard.
Note: all paths should include the full path to the stateDir
@@ -36,21 +39,54 @@ in
'';
};
+ plugins = mkOption {
+ type = types.attrsOf types.path;
+ default = {};
+ description = ''
+ Attribute set of additional plugins that will be symlinked to the
+ <filename>plugin</filename> subdirectory.
+
+ Please note that you still need to add the plugins to the config
+ file (or with <literal>!load</literal>) using their attribute name.
+ '';
+ example = literalExample ''
+ let
+ plugins = pkgs.fetchzip {
+ url = "https://github.com/ProgVal/Supybot-plugins/archive/57c2450c.zip";
+ sha256 = "077snf84ibnva3sbpzdfpfma6hcdw7dflwnhg6pw7mgnf0nd84qd";
+ };
+ in
+ {
+ Wikipedia = "''${plugins}/Wikipedia";
+ Decide = ./supy-decide;
+ }
+ '';
+ };
+
+ extraPackages = mkOption {
+ default = p: [];
+ description = ''
+ Extra Python packages available to supybot plugins. The
+ value must be a function which receives the attrset defined
+ in <varname>python3Packages</varname> as the sole argument.
+ '';
+ example = literalExample ''p: [ p.lxml p.requests ]'';
+ };
+
};
};
-
config = mkIf cfg.enable {
- environment.systemPackages = [ pkgs.pythonPackages.limnoria ];
+ environment.systemPackages = [ pkgs.python3Packages.limnoria ];
- users.users.supybotrs = {
+ users.users.supybot = {
uid = config.ids.uids.supybot;
group = "supybot";
description = "Supybot IRC bot user";
home = cfg.stateDir;
- createHome = true;
+ isSystemUser = true;
};
users.groups.supybot = {
@@ -59,19 +95,16 @@ in
systemd.services.supybot = {
description = "Supybot, an IRC bot";
+ documentation = [ "https://limnoria.readthedocs.io/" ];
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
- path = [ pkgs.pythonPackages.limnoria ];
preStart = ''
- cd ${cfg.stateDir}
- mkdir -p backup conf data plugins logs/plugins tmp web
- ln -sf ${cfg.configFile} supybot.cfg
# This needs to be created afresh every time
- rm -f supybot.cfg.bak
+ rm -f '${cfg.stateDir}/supybot.cfg.bak'
'';
serviceConfig = {
- ExecStart = "${pkgs.pythonPackages.limnoria}/bin/supybot ${cfg.stateDir}/supybot.cfg";
+ ExecStart = "${pyEnv}/bin/supybot ${cfg.stateDir}/supybot.cfg";
PIDFile = "/run/supybot.pid";
User = "supybot";
Group = "supybot";
@@ -79,8 +112,50 @@ in
Restart = "on-abort";
StartLimitInterval = "5m";
StartLimitBurst = "1";
+
+ NoNewPrivileges = true;
+ PrivateDevices = true;
+ PrivateMounts = true;
+ PrivateTmp = true;
+ ProtectControlGroups = true;
+ ProtectKernelModules = true;
+ ProtectKernelTunables = true;
+ RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+ RestrictSUIDSGID = true;
+ SystemCallArchitectures = "native";
+ RestrictNamespaces = true;
+ RestrictRealtime = true;
+ LockPersonality = true;
+ MemoryDenyWriteExecute = true;
+ RemoveIPC = true;
+ ProtectHostname = true;
+ CapabilityBoundingSet = "";
+ ProtectSystem = "full";
+ }
+ // optionalAttrs isStateDirVar {
+ StateDirectory = "supybot";
+ ProtectSystem = "strict";
+ }
+ // optionalAttrs (!isStateDirHome) {
+ ProtectHome = true;
};
};
+ systemd.tmpfiles.rules = [
+ "d '${cfg.stateDir}' 0700 supybot supybot - -"
+ "d '${cfg.stateDir}/backup' 0750 supybot supybot - -"
+ "d '${cfg.stateDir}/conf' 0750 supybot supybot - -"
+ "d '${cfg.stateDir}/data' 0750 supybot supybot - -"
+ "d '${cfg.stateDir}/plugins' 0750 supybot supybot - -"
+ "d '${cfg.stateDir}/logs' 0750 supybot supybot - -"
+ "d '${cfg.stateDir}/logs/plugins' 0750 supybot supybot - -"
+ "d '${cfg.stateDir}/tmp' 0750 supybot supybot - -"
+ "d '${cfg.stateDir}/web' 0750 supybot supybot - -"
+ "L '${cfg.stateDir}/supybot.cfg' - - - - ${cfg.configFile}"
+ ]
+ ++ (flip mapAttrsToList cfg.plugins (name: dest:
+ "L+ '${cfg.stateDir}/plugins/${name}' - - - - ${dest}"
+ ));
+
};
}
diff --git a/nixpkgs/nixos/modules/services/networking/tailscale.nix b/nixpkgs/nixos/modules/services/networking/tailscale.nix
new file mode 100644
index 00000000000..513c42b4011
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/tailscale.nix
@@ -0,0 +1,46 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let cfg = config.services.tailscale;
+in {
+ meta.maintainers = with maintainers; [ danderson mbaillie ];
+
+ options.services.tailscale = {
+ enable = mkEnableOption "Tailscale client daemon";
+
+ port = mkOption {
+ type = types.port;
+ default = 41641;
+ description = "The port to listen on for tunnel traffic (0=autoselect).";
+ };
+ };
+
+ config = mkIf cfg.enable {
+ systemd.services.tailscale = {
+ description = "Tailscale client daemon";
+
+ after = [ "network-pre.target" ];
+ wants = [ "network-pre.target" ];
+ wantedBy = [ "multi-user.target" ];
+
+ unitConfig = {
+ StartLimitIntervalSec = 0;
+ StartLimitBurst = 0;
+ };
+
+ serviceConfig = {
+ ExecStart =
+ "${pkgs.tailscale}/bin/tailscaled --port ${toString cfg.port}";
+
+ RuntimeDirectory = "tailscale";
+ RuntimeDirectoryMode = 755;
+
+ StateDirectory = "tailscale";
+ StateDirectoryMode = 700;
+
+ Restart = "on-failure";
+ };
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/networking/vsftpd.nix b/nixpkgs/nixos/modules/services/networking/vsftpd.nix
index 47990dbb377..b3e20184423 100644
--- a/nixpkgs/nixos/modules/services/networking/vsftpd.nix
+++ b/nixpkgs/nixos/modules/services/networking/vsftpd.nix
@@ -133,8 +133,8 @@ let
${optionalString cfg.enableVirtualUsers ''
guest_enable=YES
guest_username=vsftpd
- pam_service_name=vsftpd
''}
+ pam_service_name=vsftpd
${cfg.extraConfig}
'';
diff --git a/nixpkgs/nixos/modules/services/networking/wireguard.nix b/nixpkgs/nixos/modules/services/networking/wireguard.nix
index 980961225c9..e8f83f6dd8b 100644
--- a/nixpkgs/nixos/modules/services/networking/wireguard.nix
+++ b/nixpkgs/nixos/modules/services/networking/wireguard.nix
@@ -151,7 +151,7 @@ let
publicKey = mkOption {
example = "xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=";
type = types.str;
- description = "The base64 public key the peer.";
+ description = "The base64 public key of the peer.";
};
presharedKey = mkOption {
@@ -428,14 +428,14 @@ in
++ (attrValues (
mapAttrs (name: value: {
assertion = value.generatePrivateKeyFile -> (value.privateKey == null);
- message = "networking.wireguard.interfaces.${name}.generatePrivateKey must not be set if networking.wireguard.interfaces.${name}.privateKey is set.";
+ message = "networking.wireguard.interfaces.${name}.generatePrivateKeyFile must not be set if networking.wireguard.interfaces.${name}.privateKey is set.";
}) cfg.interfaces))
++ map ({ interfaceName, peer, ... }: {
assertion = (peer.presharedKey == null) || (peer.presharedKeyFile == null);
message = "networking.wireguard.interfaces.${interfaceName} peer «${peer.publicKey}» has both presharedKey and presharedKeyFile set, but only one can be used.";
}) all_peers;
- boot.extraModulePackages = [ kernel.wireguard ];
+ boot.extraModulePackages = optional (versionOlder kernel.kernel.version "5.6") kernel.wireguard;
environment.systemPackages = [ pkgs.wireguard-tools ];
systemd.services =
diff --git a/nixpkgs/nixos/modules/services/networking/zerotierone.nix b/nixpkgs/nixos/modules/services/networking/zerotierone.nix
index 069e15a909b..cf39ed065a7 100644
--- a/nixpkgs/nixos/modules/services/networking/zerotierone.nix
+++ b/nixpkgs/nixos/modules/services/networking/zerotierone.nix
@@ -67,5 +67,16 @@ in
networking.firewall.allowedUDPPorts = [ cfg.port ];
environment.systemPackages = [ cfg.package ];
+
+ # Prevent systemd from potentially changing the MAC address
+ systemd.network.links."50-zerotier" = {
+ matchConfig = {
+ OriginalName = "zt*";
+ };
+ linkConfig = {
+ AutoNegotiation = false;
+ MACAddressPolicy = "none";
+ };
+ };
};
}
diff --git a/nixpkgs/nixos/modules/services/torrent/transmission.nix b/nixpkgs/nixos/modules/services/torrent/transmission.nix
index 5ba72e8d773..fd28b94f7be 100644
--- a/nixpkgs/nixos/modules/services/torrent/transmission.nix
+++ b/nixpkgs/nixos/modules/services/torrent/transmission.nix
@@ -23,7 +23,8 @@ let
for DIR in "${homeDir}" "${settingsDir}" "${fullSettings.download-dir}" "${fullSettings.incomplete-dir}"; do
mkdir -p "$DIR"
done
- chmod 700 "${homeDir}" "${settingsDir}"
+ chmod 755 "${homeDir}"
+ chmod 700 "${settingsDir}"
chmod ${downloadDirPermissions} "${fullSettings.download-dir}" "${fullSettings.incomplete-dir}"
cp -f ${settingsFile} ${settingsDir}/settings.json
'';
diff --git a/nixpkgs/nixos/modules/services/wayland/cage.nix b/nixpkgs/nixos/modules/services/wayland/cage.nix
new file mode 100644
index 00000000000..c59ca9983a6
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/wayland/cage.nix
@@ -0,0 +1,99 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+ cfg = config.services.cage;
+in {
+ options.services.cage.enable = mkEnableOption "cage kiosk service";
+
+ options.services.cage.user = mkOption {
+ type = types.str;
+ default = "demo";
+ description = ''
+ User to log-in as.
+ '';
+ };
+
+ options.services.cage.extraArguments = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ defaultText = "[]";
+ description = "Additional command line arguments to pass to Cage.";
+ example = ["-d"];
+ };
+
+ options.services.cage.program = mkOption {
+ type = types.path;
+ default = "${pkgs.xterm}/bin/xterm";
+ description = ''
+ Program to run in cage.
+ '';
+ };
+
+ config = mkIf cfg.enable {
+
+ # The service is partially based off of the one provided in the
+ # cage wiki at
+ # https://github.com/Hjdskes/cage/wiki/Starting-Cage-on-boot-with-systemd.
+ systemd.services."cage-tty1" = {
+ enable = true;
+ after = [
+ "systemd-user-sessions.service"
+ "plymouth-start.service"
+ "plymouth-quit.service"
+ "systemd-logind.service"
+ "getty@tty1.service"
+ ];
+ before = [ "graphical.target" ];
+ wants = [ "dbus.socket" "systemd-logind.service" "plymouth-quit.service"];
+ wantedBy = [ "graphical.target" ];
+ conflicts = [ "getty@tty1.service" ];
+
+ restartIfChanged = false;
+ unitConfig.ConditionPathExists = "/dev/tty1";
+ serviceConfig = {
+ ExecStart = ''
+ ${pkgs.cage}/bin/cage \
+ ${escapeShellArgs cfg.extraArguments} \
+ -- ${cfg.program}
+ '';
+ User = cfg.user;
+
+ IgnoreSIGPIPE = "no";
+
+ # Log this user with utmp, letting it show up with commands 'w' and
+ # 'who'. This is needed since we replace (a)getty.
+ UtmpIdentifier = "%n";
+ UtmpMode = "user";
+ # A virtual terminal is needed.
+ TTYPath = "/dev/tty1";
+ TTYReset = "yes";
+ TTYVHangup = "yes";
+ TTYVTDisallocate = "yes";
+ # Fail to start if not controlling the virtual terminal.
+ StandardInput = "tty-fail";
+ StandardOutput = "syslog";
+ StandardError = "syslog";
+ # Set up a full (custom) user session for the user, required by Cage.
+ PAMName = "cage";
+ };
+ };
+
+ security.pam.services.cage.text = ''
+ auth required pam_unix.so nullok
+ account required pam_unix.so
+ session required pam_unix.so
+ session required ${pkgs.systemd}/lib/security/pam_systemd.so
+ '';
+
+ hardware.opengl.enable = mkDefault true;
+
+ systemd.targets.graphical.wants = [ "cage-tty1.service" ];
+
+ systemd.defaultUnit = "graphical.target";
+ };
+
+ meta.maintainers = with lib.maintainers; [ matthewbauer flokli ];
+
+}
diff --git a/nixpkgs/nixos/modules/services/web-apps/codimd.nix b/nixpkgs/nixos/modules/services/web-apps/codimd.nix
index 5f56f8ed5a0..751f81649dd 100644
--- a/nixpkgs/nixos/modules/services/web-apps/codimd.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/codimd.nix
@@ -156,7 +156,7 @@ in
};
useCDN = mkOption {
type = types.bool;
- default = true;
+ default = false;
description = ''
Whether to use CDN resources or not.
'';
diff --git a/nixpkgs/nixos/modules/services/web-apps/grocy.nix b/nixpkgs/nixos/modules/services/web-apps/grocy.nix
new file mode 100644
index 00000000000..568bdfd0c42
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/web-apps/grocy.nix
@@ -0,0 +1,172 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.grocy;
+in {
+ options.services.grocy = {
+ enable = mkEnableOption "grocy";
+
+ hostName = mkOption {
+ type = types.str;
+ description = ''
+ FQDN for the grocy instance.
+ '';
+ };
+
+ nginx.enableSSL = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether or not to enable SSL (with ACME and let's encrypt)
+ for the grocy vhost.
+ '';
+ };
+
+ phpfpm.settings = mkOption {
+ type = with types; attrsOf (oneOf [ int str bool ]);
+ default = {
+ "pm" = "dynamic";
+ "php_admin_value[error_log]" = "stderr";
+ "php_admin_flag[log_errors]" = true;
+ "listen.owner" = "nginx";
+ "catch_workers_output" = true;
+ "pm.max_children" = "32";
+ "pm.start_servers" = "2";
+ "pm.min_spare_servers" = "2";
+ "pm.max_spare_servers" = "4";
+ "pm.max_requests" = "500";
+ };
+
+ description = ''
+ Options for grocy's PHPFPM pool.
+ '';
+ };
+
+ dataDir = mkOption {
+ type = types.str;
+ default = "/var/lib/grocy";
+ description = ''
+ Home directory of the <literal>grocy</literal> user which contains
+ the application's state.
+ '';
+ };
+
+ settings = {
+ currency = mkOption {
+ type = types.str;
+ default = "USD";
+ example = "EUR";
+ description = ''
+ ISO 4217 code for the currency to display.
+ '';
+ };
+
+ culture = mkOption {
+ type = types.enum [ "de" "en" "da" "en_GB" "es" "fr" "hu" "it" "nl" "no" "pl" "pt_BR" "ru" "sk_SK" "sv_SE" "tr" ];
+ default = "en";
+ description = ''
+ Display language of the frontend.
+ '';
+ };
+
+ calendar = {
+ showWeekNumber = mkOption {
+ default = true;
+ type = types.bool;
+ description = ''
+ Show the number of the weeks in the calendar views.
+ '';
+ };
+ firstDayOfWeek = mkOption {
+ default = null;
+ type = types.nullOr (types.enum (range 0 6));
+ description = ''
+ Which day of the week (0=Sunday, 1=Monday etc.) should be the
+ first day.
+ '';
+ };
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ environment.etc."grocy/config.php".text = ''
+ <?php
+ Setting('CULTURE', '${cfg.settings.culture}');
+ Setting('CURRENCY', '${cfg.settings.currency}');
+ Setting('CALENDAR_FIRST_DAY_OF_WEEK', '${toString cfg.settings.calendar.firstDayOfWeek}');
+ Setting('CALENDAR_SHOW_WEEK_OF_YEAR', ${boolToString cfg.settings.calendar.showWeekNumber});
+ '';
+
+ users.users.grocy = {
+ isSystemUser = true;
+ createHome = true;
+ home = cfg.dataDir;
+ group = "nginx";
+ };
+
+ systemd.tmpfiles.rules = map (
+ dirName: "d '${cfg.dataDir}/${dirName}' - grocy nginx - -"
+ ) [ "viewcache" "plugins" "settingoverrides" "storage" ];
+
+ services.phpfpm.pools.grocy = {
+ user = "grocy";
+ group = "nginx";
+
+ # PHP 7.3 is the only version which is supported/tested by upstream:
+ # https://github.com/grocy/grocy/blob/v2.6.0/README.md#how-to-install
+ phpPackage = pkgs.php73;
+
+ inherit (cfg.phpfpm) settings;
+
+ phpEnv = {
+ GROCY_CONFIG_FILE = "/etc/grocy/config.php";
+ GROCY_DB_FILE = "${cfg.dataDir}/grocy.db";
+ GROCY_STORAGE_DIR = "${cfg.dataDir}/storage";
+ GROCY_PLUGIN_DIR = "${cfg.dataDir}/plugins";
+ GROCY_CACHE_DIR = "${cfg.dataDir}/viewcache";
+ };
+ };
+
+ services.nginx = {
+ enable = true;
+ virtualHosts."${cfg.hostName}" = mkMerge [
+ { root = "${pkgs.grocy}/public";
+ locations."/".extraConfig = ''
+ rewrite ^ /index.php;
+ '';
+ locations."~ \\.php$".extraConfig = ''
+ fastcgi_split_path_info ^(.+\.php)(/.+)$;
+ fastcgi_pass unix:${config.services.phpfpm.pools.grocy.socket};
+ include ${config.services.nginx.package}/conf/fastcgi.conf;
+ include ${config.services.nginx.package}/conf/fastcgi_params;
+ '';
+ locations."~ \\.(js|css|ttf|woff2?|png|jpe?g|svg)$".extraConfig = ''
+ add_header Cache-Control "public, max-age=15778463";
+ add_header X-Content-Type-Options nosniff;
+ add_header X-XSS-Protection "1; mode=block";
+ add_header X-Robots-Tag none;
+ add_header X-Download-Options noopen;
+ add_header X-Permitted-Cross-Domain-Policies none;
+ add_header Referrer-Policy no-referrer;
+ access_log off;
+ '';
+ extraConfig = ''
+ try_files $uri /index.php;
+ '';
+ }
+ (mkIf cfg.nginx.enableSSL {
+ enableACME = true;
+ forceSSL = true;
+ })
+ ];
+ };
+ };
+
+ meta = {
+ maintainers = with maintainers; [ ma27 ];
+ doc = ./grocy.xml;
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/web-apps/grocy.xml b/nixpkgs/nixos/modules/services/web-apps/grocy.xml
new file mode 100644
index 00000000000..fdf6d00f4b1
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/web-apps/grocy.xml
@@ -0,0 +1,77 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ version="5.0"
+ xml:id="module-services-grocy">
+
+ <title>Grocy</title>
+ <para>
+ <link xlink:href="https://grocy.info/">Grocy</link> is a web-based self-hosted groceries
+ &amp; household management solution for your home.
+ </para>
+
+ <section xml:id="module-services-grocy-basic-usage">
+ <title>Basic usage</title>
+ <para>
+ A very basic configuration may look like this:
+<programlisting>{ pkgs, ... }:
+{
+ services.grocy = {
+ <link linkend="opt-services.grocy.enable">enable</link> = true;
+ <link linkend="opt-services.grocy.hostName">hostName</link> = "grocy.tld";
+ };
+}</programlisting>
+ This configures a simple vhost using <link linkend="opt-services.nginx.enable">nginx</link>
+ which listens to <literal>grocy.tld</literal> with fully configured ACME/LE (this can be
+ disabled by setting <link linkend="opt-services.grocy.nginx.enableSSL">services.grocy.nginx.enableSSL</link>
+ to <literal>false</literal>). After the initial setup the credentials <literal>admin:admin</literal>
+ can be used to login.
+ </para>
+ <para>
+ The application's state is persisted at <literal>/var/lib/grocy/grocy.db</literal> in a
+ <package>sqlite3</package> database. The migration is applied when requesting the <literal>/</literal>-route
+ of the application.
+ </para>
+ </section>
+
+ <section xml:id="module-services-grocy-settings">
+ <title>Settings</title>
+ <para>
+ The configuration for <literal>grocy</literal> is located at <literal>/etc/grocy/config.php</literal>.
+ By default, the following settings can be defined in the NixOS-configuration:
+<programlisting>{ pkgs, ... }:
+{
+ services.grocy.settings = {
+ # The default currency in the system for invoices etc.
+ # Please note that exchange rates aren't taken into account, this
+ # is just the setting for what's shown in the frontend.
+ <link linkend="opt-services.grocy.settings.currency">currency</link> = "EUR";
+
+ # The display language (and locale configuration) for grocy.
+ <link linkend="opt-services.grocy.settings.currency">culture</link> = "de";
+
+ calendar = {
+ # Whether or not to show the week-numbers
+ # in the calendar.
+ <link linkend="opt-services.grocy.settings.calendar.showWeekNumber">showWeekNumber</link> = true;
+
+ # Index of the first day to be shown in the calendar (0=Sunday, 1=Monday,
+ # 2=Tuesday and so on).
+ <link linkend="opt-services.grocy.settings.calendar.firstDayOfWeek">firstDayOfWeek</link> = 2;
+ };
+ };
+}</programlisting>
+ </para>
+ <para>
+ If you want to alter the configuration file on your own, you can do this manually with
+ an expression like this:
+<programlisting>{ lib, ... }:
+{
+ environment.etc."grocy/config.php".text = lib.mkAfter ''
+ // Arbitrary PHP code in grocy's configuration file
+ '';
+}</programlisting>
+ </para>
+ </section>
+
+</chapter>
diff --git a/nixpkgs/nixos/modules/services/web-apps/jirafeau.nix b/nixpkgs/nixos/modules/services/web-apps/jirafeau.nix
new file mode 100644
index 00000000000..4f181257ef7
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/web-apps/jirafeau.nix
@@ -0,0 +1,169 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+ cfg = config.services.jirafeau;
+
+ group = config.services.nginx.group;
+ user = config.services.nginx.user;
+
+ withTrailingSlash = str: if hasSuffix "/" str then str else "${str}/";
+
+ localConfig = pkgs.writeText "config.local.php" ''
+ <?php
+ $cfg['admin_password'] = '${cfg.adminPasswordSha256}';
+ $cfg['web_root'] = 'http://${withTrailingSlash cfg.hostName}';
+ $cfg['var_root'] = '${withTrailingSlash cfg.dataDir}';
+ $cfg['maximal_upload_size'] = ${builtins.toString cfg.maxUploadSizeMegabytes};
+ $cfg['installation_done'] = true;
+
+ ${cfg.extraConfig}
+ '';
+in
+{
+ options.services.jirafeau = {
+ adminPasswordSha256 = mkOption {
+ type = types.str;
+ default = "";
+ description = ''
+ SHA-256 of the desired administration password. Leave blank/unset for no password.
+ '';
+ };
+
+ dataDir = mkOption {
+ type = types.path;
+ default = "/var/lib/jirafeau/data/";
+ description = "Location of Jirafeau storage directory.";
+ };
+
+ enable = mkEnableOption "Jirafeau file upload application.";
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ example = ''
+ $cfg['style'] = 'courgette';
+ $cfg['organisation'] = 'ACME';
+ '';
+ description = let
+ documentationLink =
+ "https://gitlab.com/mojo42/Jirafeau/-/blob/${cfg.package.version}/lib/config.original.php";
+ in
+ ''
+ Jirefeau configuration. Refer to <link xlink:href="${documentationLink}"/> for supported
+ values.
+ '';
+ };
+
+ hostName = mkOption {
+ type = types.str;
+ default = "localhost";
+ description = "URL of instance. Must have trailing slash.";
+ };
+
+ maxUploadSizeMegabytes = mkOption {
+ type = types.int;
+ default = 0;
+ description = "Maximum upload size of accepted files.";
+ };
+
+ maxUploadTimeout = mkOption {
+ type = types.str;
+ default = "30m";
+ description = let
+ nginxCoreDocumentation = "http://nginx.org/en/docs/http/ngx_http_core_module.html";
+ in
+ ''
+ Timeout for reading client request bodies and headers. Refer to
+ <link xlink:href="${nginxCoreDocumentation}#client_body_timeout"/> and
+ <link xlink:href="${nginxCoreDocumentation}#client_header_timeout"/> for accepted values.
+ '';
+ };
+
+ nginxConfig = mkOption {
+ type = types.submodule
+ (import ../web-servers/nginx/vhost-options.nix { inherit config lib; });
+ default = {};
+ example = {
+ serverAliases = [ "wiki.\${config.networking.domain}" ];
+ };
+ description = "Extra configuration for the nginx virtual host of Jirafeau.";
+ };
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.jirafeau;
+ defaultText = "pkgs.jirafeau";
+ description = "Jirafeau package to use";
+ example = "pkgs.jirafeau";
+ };
+
+ poolConfig = mkOption {
+ type = with types; attrsOf (oneOf [ str int bool ]);
+ default = {
+ "pm" = "dynamic";
+ "pm.max_children" = 32;
+ "pm.start_servers" = 2;
+ "pm.min_spare_servers" = 2;
+ "pm.max_spare_servers" = 4;
+ "pm.max_requests" = 500;
+ };
+ description = ''
+ Options for Jirafeau PHP pool. See documentation on <literal>php-fpm.conf</literal> for
+ details on configuration directives.
+ '';
+ };
+ };
+
+
+ config = mkIf cfg.enable {
+ services = {
+ nginx = {
+ enable = true;
+ virtualHosts."${cfg.hostName}" = mkMerge [
+ cfg.nginxConfig
+ {
+ extraConfig = let
+ clientMaxBodySize =
+ if cfg.maxUploadSizeMegabytes == 0 then "0" else "${cfg.maxUploadSizeMegabytes}m";
+ in
+ ''
+ index index.php;
+ client_max_body_size ${clientMaxBodySize};
+ client_body_timeout ${cfg.maxUploadTimeout};
+ client_header_timeout ${cfg.maxUploadTimeout};
+ '';
+ locations = {
+ "~ \\.php$".extraConfig = ''
+ include ${pkgs.nginx}/conf/fastcgi_params;
+ fastcgi_split_path_info ^(.+\.php)(/.+)$;
+ fastcgi_index index.php;
+ fastcgi_pass unix:${config.services.phpfpm.pools.jirafeau.socket};
+ fastcgi_param PATH_INFO $fastcgi_path_info;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ '';
+ };
+ root = mkForce "${cfg.package}";
+ }
+ ];
+ };
+
+ phpfpm.pools.jirafeau = {
+ inherit group user;
+ phpEnv."JIRAFEAU_CONFIG" = "${localConfig}";
+ settings = {
+ "listen.mode" = "0660";
+ "listen.owner" = user;
+ "listen.group" = group;
+ } // cfg.poolConfig;
+ };
+ };
+
+ systemd.tmpfiles.rules = [
+ "d ${cfg.dataDir} 0750 ${user} ${group} - -"
+ "d ${cfg.dataDir}/files/ 0750 ${user} ${group} - -"
+ "d ${cfg.dataDir}/links/ 0750 ${user} ${group} - -"
+ "d ${cfg.dataDir}/async/ 0750 ${user} ${group} - -"
+ ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/web-apps/limesurvey.nix b/nixpkgs/nixos/modules/services/web-apps/limesurvey.nix
index e00a47191c6..56265e80957 100644
--- a/nixpkgs/nixos/modules/services/web-apps/limesurvey.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/limesurvey.nix
@@ -100,7 +100,7 @@ in
};
virtualHost = mkOption {
- type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix);
+ type = types.submodule (import ../web-servers/apache-httpd/vhost-options.nix);
example = literalExample ''
{
hostName = "survey.example.org";
diff --git a/nixpkgs/nixos/modules/services/web-apps/mattermost.nix b/nixpkgs/nixos/modules/services/web-apps/mattermost.nix
index 41c52b9653b..853347bf86e 100644
--- a/nixpkgs/nixos/modules/services/web-apps/mattermost.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/mattermost.nix
@@ -6,14 +6,18 @@ let
cfg = config.services.mattermost;
- defaultConfig = builtins.fromJSON (readFile "${pkgs.mattermost}/config/config.json");
+ defaultConfig = builtins.fromJSON (builtins.replaceStrings [ "\\u0026" ] [ "&" ]
+ (readFile "${pkgs.mattermost}/config/config.json")
+ );
+
+ database = "postgres://${cfg.localDatabaseUser}:${cfg.localDatabasePassword}@localhost:5432/${cfg.localDatabaseName}?sslmode=disable&connect_timeout=10";
mattermostConf = foldl recursiveUpdate defaultConfig
[ { ServiceSettings.SiteURL = cfg.siteUrl;
ServiceSettings.ListenAddress = cfg.listenAddress;
TeamSettings.SiteName = cfg.siteName;
SqlSettings.DriverName = "postgres";
- SqlSettings.DataSource = "postgres://${cfg.localDatabaseUser}:${cfg.localDatabasePassword}@localhost:5432/${cfg.localDatabaseName}?sslmode=disable&connect_timeout=10";
+ SqlSettings.DataSource = database;
}
cfg.extraConfig
];
@@ -175,7 +179,9 @@ in
mkdir -p ${cfg.statePath}/{data,config,logs}
ln -sf ${pkgs.mattermost}/{bin,fonts,i18n,templates,client} ${cfg.statePath}
'' + lib.optionalString (!cfg.mutableConfig) ''
- ln -sf ${mattermostConfJSON} ${cfg.statePath}/config/config.json
+ rm -f ${cfg.statePath}/config/config.json
+ cp ${mattermostConfJSON} ${cfg.statePath}/config/config.json
+ ${pkgs.mattermost}/bin/mattermost config migrate ${cfg.statePath}/config/config.json ${database}
'' + lib.optionalString cfg.mutableConfig ''
if ! test -e "${cfg.statePath}/config/.initial-created"; then
rm -f ${cfg.statePath}/config/config.json
@@ -201,7 +207,8 @@ in
PermissionsStartOnly = true;
User = cfg.user;
Group = cfg.group;
- ExecStart = "${pkgs.mattermost}/bin/mattermost";
+ ExecStart = "${pkgs.mattermost}/bin/mattermost" +
+ (lib.optionalString (!cfg.mutableConfig) " -c ${database}");
WorkingDirectory = "${cfg.statePath}";
Restart = "always";
RestartSec = "10";
@@ -227,4 +234,3 @@ in
})
];
}
-
diff --git a/nixpkgs/nixos/modules/services/web-apps/mediawiki.nix b/nixpkgs/nixos/modules/services/web-apps/mediawiki.nix
index 8a109b39bb5..e9ed53857d8 100644
--- a/nixpkgs/nixos/modules/services/web-apps/mediawiki.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/mediawiki.nix
@@ -290,7 +290,7 @@ in
};
virtualHost = mkOption {
- type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix);
+ type = types.submodule (import ../web-servers/apache-httpd/vhost-options.nix);
example = literalExample ''
{
hostName = "mediawiki.example.org";
diff --git a/nixpkgs/nixos/modules/services/web-apps/moodle.nix b/nixpkgs/nixos/modules/services/web-apps/moodle.nix
index 595d070d940..1196780cf6e 100644
--- a/nixpkgs/nixos/modules/services/web-apps/moodle.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/moodle.nix
@@ -140,7 +140,7 @@ in
};
virtualHost = mkOption {
- type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix);
+ type = types.submodule (import ../web-servers/apache-httpd/vhost-options.nix);
example = literalExample ''
{
hostName = "moodle.example.org";
diff --git a/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix b/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix
index d79f2bb735f..912e05d6d40 100644
--- a/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix
@@ -443,7 +443,7 @@ in {
pools.nextcloud = {
user = "nextcloud";
group = "nginx";
- phpOptions = phpOptionsExtensions + phpOptionsStr;
+ phpOptions = phpOptionsStr;
phpPackage = phpPackage;
phpEnv = {
NEXTCLOUD_CONFIG_DIR = "${cfg.home}/config";
@@ -533,6 +533,7 @@ in {
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
+ add_header X-Frame-Options sameorigin;
add_header Referrer-Policy no-referrer;
access_log off;
'';
@@ -547,6 +548,7 @@ in {
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
+ add_header X-Frame-Options sameorigin;
add_header Referrer-Policy no-referrer;
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
error_page 403 /core/templates/403.php;
diff --git a/nixpkgs/nixos/modules/services/web-apps/wordpress.nix b/nixpkgs/nixos/modules/services/web-apps/wordpress.nix
index ad4f39fbf52..c48a4409737 100644
--- a/nixpkgs/nixos/modules/services/web-apps/wordpress.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/wordpress.nix
@@ -209,7 +209,7 @@ let
};
virtualHost = mkOption {
- type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix);
+ type = types.submodule (import ../web-servers/apache-httpd/vhost-options.nix);
example = literalExample ''
{
adminAddr = "webmaster@example.org";
diff --git a/nixpkgs/nixos/modules/services/web-apps/zabbix.nix b/nixpkgs/nixos/modules/services/web-apps/zabbix.nix
index ee8447810c6..00719512834 100644
--- a/nixpkgs/nixos/modules/services/web-apps/zabbix.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/zabbix.nix
@@ -113,7 +113,7 @@ in
};
virtualHost = mkOption {
- type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix);
+ type = types.submodule (import ../web-servers/apache-httpd/vhost-options.nix);
example = literalExample ''
{
hostName = "zabbix.example.org";
diff --git a/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix
index 9942c63acce..832c8b30ee9 100644
--- a/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix
@@ -4,21 +4,21 @@ with lib;
let
- mainCfg = config.services.httpd;
+ cfg = config.services.httpd;
runtimeDir = "/run/httpd";
- httpd = mainCfg.package.out;
+ pkg = cfg.package.out;
- httpdConf = mainCfg.configFile;
+ httpdConf = cfg.configFile;
- php = mainCfg.phpPackage.override { apacheHttpd = httpd.dev; /* otherwise it only gets .out */ };
+ php = cfg.phpPackage.override { apacheHttpd = pkg.dev; /* otherwise it only gets .out */ };
phpMajorVersion = lib.versions.major (lib.getVersion php);
- mod_perl = pkgs.apacheHttpdPackages.mod_perl.override { apacheHttpd = httpd; };
+ mod_perl = pkgs.apacheHttpdPackages.mod_perl.override { apacheHttpd = pkg; };
- vhosts = attrValues mainCfg.virtualHosts;
+ vhosts = attrValues cfg.virtualHosts;
mkListenInfo = hostOpts:
if hostOpts.listen != [] then hostOpts.listen
@@ -29,8 +29,8 @@ let
listenInfo = unique (concatMap mkListenInfo vhosts);
+ enableHttp2 = any (vhost: vhost.http2) vhosts;
enableSSL = any (listen: listen.ssl) listenInfo;
-
enableUserDir = any (vhost: vhost.enableUserDir) vhosts;
# NOTE: generally speaking order of modules is very important
@@ -41,23 +41,19 @@ let
"mime" "autoindex" "negotiation" "dir"
"alias" "rewrite"
"unixd" "slotmem_shm" "socache_shmcb"
- "mpm_${mainCfg.multiProcessingModule}"
+ "mpm_${cfg.multiProcessingModule}"
]
- ++ (if mainCfg.multiProcessingModule == "prefork" then [ "cgi" ] else [ "cgid" ])
+ ++ (if cfg.multiProcessingModule == "prefork" then [ "cgi" ] else [ "cgid" ])
+ ++ optional enableHttp2 "http2"
++ optional enableSSL "ssl"
++ optional enableUserDir "userdir"
- ++ optional mainCfg.enableMellon { name = "auth_mellon"; path = "${pkgs.apacheHttpdPackages.mod_auth_mellon}/modules/mod_auth_mellon.so"; }
- ++ optional mainCfg.enablePHP { name = "php${phpMajorVersion}"; path = "${php}/modules/libphp${phpMajorVersion}.so"; }
- ++ optional mainCfg.enablePerl { name = "perl"; path = "${mod_perl}/modules/mod_perl.so"; }
- ++ mainCfg.extraModules;
-
-
- allDenied = "Require all denied";
- allGranted = "Require all granted";
+ ++ optional cfg.enableMellon { name = "auth_mellon"; path = "${pkgs.apacheHttpdPackages.mod_auth_mellon}/modules/mod_auth_mellon.so"; }
+ ++ optional cfg.enablePHP { name = "php${phpMajorVersion}"; path = "${php}/modules/libphp${phpMajorVersion}.so"; }
+ ++ optional cfg.enablePerl { name = "perl"; path = "${mod_perl}/modules/mod_perl.so"; }
+ ++ cfg.extraModules;
-
- loggingConf = (if mainCfg.logFormat != "none" then ''
- ErrorLog ${mainCfg.logDir}/error.log
+ loggingConf = (if cfg.logFormat != "none" then ''
+ ErrorLog ${cfg.logDir}/error.log
LogLevel notice
@@ -66,7 +62,7 @@ let
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
- CustomLog ${mainCfg.logDir}/access.log ${mainCfg.logFormat}
+ CustomLog ${cfg.logDir}/access.log ${cfg.logFormat}
'' else ''
ErrorLog /dev/null
'');
@@ -88,34 +84,36 @@ let
sslConf = ''
- SSLSessionCache shmcb:${runtimeDir}/ssl_scache(512000)
+ <IfModule mod_ssl.c>
+ SSLSessionCache shmcb:${runtimeDir}/ssl_scache(512000)
- Mutex posixsem
+ Mutex posixsem
- SSLRandomSeed startup builtin
- SSLRandomSeed connect builtin
+ SSLRandomSeed startup builtin
+ SSLRandomSeed connect builtin
- SSLProtocol ${mainCfg.sslProtocols}
- SSLCipherSuite ${mainCfg.sslCiphers}
- SSLHonorCipherOrder on
+ SSLProtocol ${cfg.sslProtocols}
+ SSLCipherSuite ${cfg.sslCiphers}
+ SSLHonorCipherOrder on
+ </IfModule>
'';
mimeConf = ''
- TypesConfig ${httpd}/conf/mime.types
+ TypesConfig ${pkg}/conf/mime.types
AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl .crl
AddType application/x-httpd-php .php .phtml
<IfModule mod_mime_magic.c>
- MIMEMagicFile ${httpd}/conf/magic
+ MIMEMagicFile ${pkg}/conf/magic
</IfModule>
'';
mkVHostConf = hostOpts:
let
- adminAddr = if hostOpts.adminAddr != null then hostOpts.adminAddr else mainCfg.adminAddr;
+ adminAddr = if hostOpts.adminAddr != null then hostOpts.adminAddr else cfg.adminAddr;
listen = filter (listen: !listen.ssl) (mkListenInfo hostOpts);
listenSSL = filter (listen: listen.ssl) (mkListenInfo hostOpts);
@@ -167,6 +165,7 @@ let
SSLCertificateFile ${sslServerCert}
SSLCertificateKeyFile ${sslServerKey}
${optionalString (sslServerChain != null) "SSLCertificateChainFile ${sslServerChain}"}
+ ${optionalString hostOpts.http2 "Protocols h2 h2c http/1.1"}
${acmeChallenge}
${mkVHostCommonConf hostOpts}
</VirtualHost>
@@ -203,9 +202,9 @@ let
'') (sortProperties (mapAttrsToList (k: v: v // { location = k; }) locations)));
in
''
- ${optionalString mainCfg.logPerVirtualHost ''
- ErrorLog ${mainCfg.logDir}/error-${hostOpts.hostName}.log
- CustomLog ${mainCfg.logDir}/access-${hostOpts.hostName}.log ${hostOpts.logFormat}
+ ${optionalString cfg.logPerVirtualHost ''
+ ErrorLog ${cfg.logDir}/error-${hostOpts.hostName}.log
+ CustomLog ${cfg.logDir}/access-${hostOpts.hostName}.log ${hostOpts.logFormat}
''}
${optionalString (hostOpts.robotsEntries != "") ''
@@ -217,7 +216,7 @@ let
<Directory "${documentRoot}">
Options Indexes FollowSymLinks
AllowOverride None
- ${allGranted}
+ Require all granted
</Directory>
${optionalString hostOpts.enableUserDir ''
@@ -244,7 +243,7 @@ let
Alias ${elem.urlPath} ${elem.dir}/
<Directory ${elem.dir}>
Options +Indexes
- ${allGranted}
+ Require all granted
AllowOverride All
</Directory>
'';
@@ -259,20 +258,20 @@ let
confFile = pkgs.writeText "httpd.conf" ''
- ServerRoot ${httpd}
+ ServerRoot ${pkg}
ServerName ${config.networking.hostName}
DefaultRuntimeDir ${runtimeDir}/runtime
PidFile ${runtimeDir}/httpd.pid
- ${optionalString (mainCfg.multiProcessingModule != "prefork") ''
+ ${optionalString (cfg.multiProcessingModule != "prefork") ''
# mod_cgid requires this.
ScriptSock ${runtimeDir}/cgisock
''}
<IfModule prefork.c>
- MaxClients ${toString mainCfg.maxClients}
- MaxRequestsPerChild ${toString mainCfg.maxRequestsPerChild}
+ MaxClients ${toString cfg.maxClients}
+ MaxRequestsPerChild ${toString cfg.maxRequestsPerChild}
</IfModule>
${let
@@ -281,12 +280,12 @@ let
in concatStringsSep "\n" uniqueListen
}
- User ${mainCfg.user}
- Group ${mainCfg.group}
+ User ${cfg.user}
+ Group ${cfg.group}
${let
mkModule = module:
- if isString module then { name = module; path = "${httpd}/modules/mod_${module}.so"; }
+ if isString module then { name = module; path = "${pkg}/modules/mod_${module}.so"; }
else if isAttrs module then { inherit (module) name path; }
else throw "Expecting either a string or attribute set including a name and path.";
in
@@ -296,37 +295,37 @@ let
AddHandler type-map var
<Files ~ "^\.ht">
- ${allDenied}
+ Require all denied
</Files>
${mimeConf}
${loggingConf}
${browserHacks}
- Include ${httpd}/conf/extra/httpd-default.conf
- Include ${httpd}/conf/extra/httpd-autoindex.conf
- Include ${httpd}/conf/extra/httpd-multilang-errordoc.conf
- Include ${httpd}/conf/extra/httpd-languages.conf
+ Include ${pkg}/conf/extra/httpd-default.conf
+ Include ${pkg}/conf/extra/httpd-autoindex.conf
+ Include ${pkg}/conf/extra/httpd-multilang-errordoc.conf
+ Include ${pkg}/conf/extra/httpd-languages.conf
TraceEnable off
- ${if enableSSL then sslConf else ""}
+ ${sslConf}
# Fascist default - deny access to everything.
<Directory />
Options FollowSymLinks
AllowOverride None
- ${allDenied}
+ Require all denied
</Directory>
# But do allow access to files in the store so that we don't have
# to generate <Directory> clauses for every generated file that we
# want to serve.
<Directory /nix/store>
- ${allGranted}
+ Require all granted
</Directory>
- ${mainCfg.extraConfig}
+ ${cfg.extraConfig}
${concatMapStringsSep "\n" mkVHostConf vhosts}
'';
@@ -334,7 +333,7 @@ let
# Generate the PHP configuration file. Should probably be factored
# out into a separate module.
phpIni = pkgs.runCommand "php.ini"
- { options = mainCfg.phpOptions;
+ { options = cfg.phpOptions;
preferLocalBuild = true;
}
''
@@ -367,17 +366,13 @@ in
(mkRemovedOptionModule [ "services" "httpd" "sslServerKey" ] "Please define a virtual host using `services.httpd.virtualHosts`.")
];
- ###### interface
+ # interface
options = {
services.httpd = {
- enable = mkOption {
- type = types.bool;
- default = false;
- description = "Whether to enable the Apache HTTP Server.";
- };
+ enable = mkEnableOption "the Apache HTTP Server";
package = mkOption {
type = types.package;
@@ -404,7 +399,7 @@ in
default = "";
description = ''
Configuration lines appended to the generated Apache
- configuration file. Note that this mechanism may not work
+ configuration file. Note that this mechanism will not work
when <option>configFile</option> is overridden.
'';
};
@@ -419,7 +414,7 @@ in
]
'';
description = ''
- Additional Apache modules to be used. These can be
+ Additional Apache modules to be used. These can be
specified as a string in the case of modules distributed
with Apache, or as an attribute set specifying the
<varname>name</varname> and <varname>path</varname> of the
@@ -458,8 +453,7 @@ in
type = types.str;
default = "wwwrun";
description = ''
- User account under which httpd runs. The account is created
- automatically if it doesn't exist.
+ User account under which httpd runs.
'';
};
@@ -467,8 +461,7 @@ in
type = types.str;
default = "wwwrun";
description = ''
- Group under which httpd runs. The account is created
- automatically if it doesn't exist.
+ Group under which httpd runs.
'';
};
@@ -476,15 +469,15 @@ in
type = types.path;
default = "/var/log/httpd";
description = ''
- Directory for Apache's log files. It is created automatically.
+ Directory for Apache's log files. It is created automatically.
'';
};
virtualHosts = mkOption {
- type = with types; attrsOf (submodule (import ./per-server-options.nix));
+ type = with types; attrsOf (submodule (import ./vhost-options.nix));
default = {
localhost = {
- documentRoot = "${httpd}/htdocs";
+ documentRoot = "${pkg}/htdocs";
};
};
example = literalExample ''
@@ -540,17 +533,18 @@ in
''
date.timezone = "CET"
'';
- description =
- "Options appended to the PHP configuration file <filename>php.ini</filename>.";
+ description = ''
+ Options appended to the PHP configuration file <filename>php.ini</filename>.
+ '';
};
multiProcessingModule = mkOption {
- type = types.str;
+ type = types.enum [ "event" "prefork" "worker" ];
default = "prefork";
example = "worker";
description =
''
- Multi-processing module to be used by Apache. Available
+ Multi-processing module to be used by Apache. Available
modules are <literal>prefork</literal> (the default;
handles each request in a separate child process),
<literal>worker</literal> (hybrid approach that starts a
@@ -572,8 +566,9 @@ in
type = types.int;
default = 0;
example = 500;
- description =
- "Maximum number of httpd requests answered per httpd child (prefork), 0 means unlimited";
+ description = ''
+ Maximum number of httpd requests answered per httpd child (prefork), 0 means unlimited.
+ '';
};
sslCiphers = mkOption {
@@ -592,10 +587,9 @@ in
};
+ # implementation
- ###### implementation
-
- config = mkIf config.services.httpd.enable {
+ config = mkIf cfg.enable {
assertions = [
{
@@ -626,30 +620,30 @@ in
warnings =
mapAttrsToList (name: hostOpts: ''
Using config.services.httpd.virtualHosts."${name}".servedFiles is deprecated and will become unsupported in a future release. Your configuration will continue to work as is but please migrate your configuration to config.services.httpd.virtualHosts."${name}".locations before the 20.09 release of NixOS.
- '') (filterAttrs (name: hostOpts: hostOpts.servedFiles != []) mainCfg.virtualHosts);
+ '') (filterAttrs (name: hostOpts: hostOpts.servedFiles != []) cfg.virtualHosts);
- users.users = optionalAttrs (mainCfg.user == "wwwrun") {
+ users.users = optionalAttrs (cfg.user == "wwwrun") {
wwwrun = {
- group = mainCfg.group;
+ group = cfg.group;
description = "Apache httpd user";
uid = config.ids.uids.wwwrun;
};
};
- users.groups = optionalAttrs (mainCfg.group == "wwwrun") {
+ users.groups = optionalAttrs (cfg.group == "wwwrun") {
wwwrun.gid = config.ids.gids.wwwrun;
};
security.acme.certs = mapAttrs (name: hostOpts: {
- user = mainCfg.user;
- group = mkDefault mainCfg.group;
- email = if hostOpts.adminAddr != null then hostOpts.adminAddr else mainCfg.adminAddr;
+ user = cfg.user;
+ group = mkDefault cfg.group;
+ email = if hostOpts.adminAddr != null then hostOpts.adminAddr else cfg.adminAddr;
webroot = hostOpts.acmeRoot;
extraDomains = genAttrs hostOpts.serverAliases (alias: null);
postRun = "systemctl reload httpd.service";
- }) (filterAttrs (name: hostOpts: hostOpts.enableACME) mainCfg.virtualHosts);
+ }) (filterAttrs (name: hostOpts: hostOpts.enableACME) cfg.virtualHosts);
- environment.systemPackages = [httpd];
+ environment.systemPackages = [ pkg ];
# required for "apachectl configtest"
environment.etc."httpd/httpd.conf".source = httpdConf;
@@ -689,6 +683,15 @@ in
"access_compat"
];
+ systemd.tmpfiles.rules =
+ let
+ svc = config.systemd.services.httpd.serviceConfig;
+ in
+ [
+ "d '${cfg.logDir}' 0700 ${svc.User} ${svc.Group}"
+ "Z '${cfg.logDir}' - ${svc.User} ${svc.Group}"
+ ];
+
systemd.services.httpd =
let
vhostsACME = filter (hostOpts: hostOpts.enableACME) vhosts;
@@ -700,35 +703,36 @@ in
after = [ "network.target" "fs.target" ] ++ map (hostOpts: "acme-selfsigned-${hostOpts.hostName}.service") vhostsACME;
path =
- [ httpd pkgs.coreutils pkgs.gnugrep ]
- ++ optional mainCfg.enablePHP pkgs.system-sendmail; # Needed for PHP's mail() function.
+ [ pkg pkgs.coreutils pkgs.gnugrep ]
+ ++ optional cfg.enablePHP pkgs.system-sendmail; # Needed for PHP's mail() function.
environment =
- optionalAttrs mainCfg.enablePHP { PHPRC = phpIni; }
- // optionalAttrs mainCfg.enableMellon { LD_LIBRARY_PATH = "${pkgs.xmlsec}/lib"; };
+ optionalAttrs cfg.enablePHP { PHPRC = phpIni; }
+ // optionalAttrs cfg.enableMellon { LD_LIBRARY_PATH = "${pkgs.xmlsec}/lib"; };
preStart =
''
- mkdir -m 0700 -p ${mainCfg.logDir}
-
# Get rid of old semaphores. These tend to accumulate across
# server restarts, eventually preventing it from restarting
# successfully.
- for i in $(${pkgs.utillinux}/bin/ipcs -s | grep ' ${mainCfg.user} ' | cut -f2 -d ' '); do
+ for i in $(${pkgs.utillinux}/bin/ipcs -s | grep ' ${cfg.user} ' | cut -f2 -d ' '); do
${pkgs.utillinux}/bin/ipcrm -s $i
done
'';
- serviceConfig.ExecStart = "@${httpd}/bin/httpd httpd -f ${httpdConf}";
- serviceConfig.ExecStop = "${httpd}/bin/httpd -f ${httpdConf} -k graceful-stop";
- serviceConfig.ExecReload = "${httpd}/bin/httpd -f ${httpdConf} -k graceful";
- serviceConfig.Group = mainCfg.group;
- serviceConfig.Type = "forking";
- serviceConfig.PIDFile = "${runtimeDir}/httpd.pid";
- serviceConfig.Restart = "always";
- serviceConfig.RestartSec = "5s";
- serviceConfig.RuntimeDirectory = "httpd httpd/runtime";
- serviceConfig.RuntimeDirectoryMode = "0750";
+ serviceConfig = {
+ ExecStart = "@${pkg}/bin/httpd httpd -f ${httpdConf}";
+ ExecStop = "${pkg}/bin/httpd -f ${httpdConf} -k graceful-stop";
+ ExecReload = "${pkg}/bin/httpd -f ${httpdConf} -k graceful";
+ User = "root";
+ Group = cfg.group;
+ Type = "forking";
+ PIDFile = "${runtimeDir}/httpd.pid";
+ Restart = "always";
+ RestartSec = "5s";
+ RuntimeDirectory = "httpd httpd/runtime";
+ RuntimeDirectoryMode = "0750";
+ };
};
};
diff --git a/nixpkgs/nixos/modules/services/web-servers/apache-httpd/per-server-options.nix b/nixpkgs/nixos/modules/services/web-servers/apache-httpd/vhost-options.nix
index f34f8b4acdf..263980add8b 100644
--- a/nixpkgs/nixos/modules/services/web-servers/apache-httpd/per-server-options.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/apache-httpd/vhost-options.nix
@@ -135,6 +135,15 @@ in
description = "Path to server SSL chain file.";
};
+ http2 = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to enable HTTP 2. HTTP/2 is supported in all multi-processing modules that come with httpd. <emphasis>However, if you use the prefork mpm, there will
+ be severe restrictions.</emphasis> Refer to <link xlink:href="https://httpd.apache.org/docs/2.4/howto/http2.html#mpm-config"/> for details.
+ '';
+ };
+
adminAddr = mkOption {
type = types.nullOr types.str;
default = null;
diff --git a/nixpkgs/nixos/modules/services/web-servers/caddy.nix b/nixpkgs/nixos/modules/services/web-servers/caddy.nix
index 132c50735d9..0e6e10a5f47 100644
--- a/nixpkgs/nixos/modules/services/web-servers/caddy.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/caddy.nix
@@ -64,32 +64,38 @@ in {
config = mkIf cfg.enable {
systemd.services.caddy = {
description = "Caddy web server";
+ # upstream unit: https://github.com/caddyserver/caddy/blob/master/dist/init/linux-systemd/caddy.service
after = [ "network-online.target" ];
+ wants = [ "network-online.target" ]; # systemd-networkd-wait-online.service
wantedBy = [ "multi-user.target" ];
environment = mkIf (versionAtLeast config.system.stateVersion "17.09")
{ CADDYPATH = cfg.dataDir; };
serviceConfig = {
ExecStart = ''
- ${cfg.package}/bin/caddy -root=/var/tmp -conf=${configFile} \
+ ${cfg.package}/bin/caddy -log stdout -log-timestamps=false \
+ -root=/var/tmp -conf=${configFile} \
-ca=${cfg.ca} -email=${cfg.email} ${optionalString cfg.agree "-agree"}
'';
- ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+ ExecReload = "${pkgs.coreutils}/bin/kill -USR1 $MAINPID";
Type = "simple";
User = "caddy";
Group = "caddy";
- Restart = "on-failure";
- StartLimitInterval = 86400;
- StartLimitBurst = 5;
+ Restart = "on-abnormal";
+ StartLimitIntervalSec = 14400;
+ StartLimitBurst = 10;
AmbientCapabilities = "cap_net_bind_service";
CapabilityBoundingSet = "cap_net_bind_service";
NoNewPrivileges = true;
- LimitNPROC = 64;
+ LimitNPROC = 512;
LimitNOFILE = 1048576;
PrivateTmp = true;
PrivateDevices = true;
ProtectHome = true;
ProtectSystem = "full";
ReadWriteDirectories = cfg.dataDir;
+ KillMode = "mixed";
+ KillSignal = "SIGQUIT";
+ TimeoutStopSec = "5s";
};
};
diff --git a/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix b/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix
index c8602e5975b..28b433104a1 100644
--- a/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix
@@ -87,10 +87,17 @@ let
${optionalString (cfg.sslDhparam != null) "ssl_dhparam ${cfg.sslDhparam};"}
${optionalString (cfg.recommendedTlsSettings) ''
- ssl_session_cache shared:SSL:42m;
- ssl_session_timeout 23m;
- ssl_ecdh_curve secp384r1;
- ssl_prefer_server_ciphers on;
+ # Keep in sync with https://ssl-config.mozilla.org/#server=nginx&config=intermediate
+
+ ssl_session_timeout 1d;
+ ssl_session_cache shared:SSL:10m;
+ # Breaks forward secrecy: https://github.com/mozilla/server-side-tls/issues/135
+ ssl_session_tickets off;
+ # We don't enable insecure ciphers by default, so this allows
+ # clients to pick the most performant, per https://github.com/mozilla/server-side-tls/issues/260
+ ssl_prefer_server_ciphers off;
+
+ # OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
''}
@@ -487,8 +494,9 @@ in
sslCiphers = mkOption {
type = types.str;
- default = "EECDH+aRSA+AESGCM:EDH+aRSA:EECDH+aRSA:+AES256:+AES128:+SHA1:!CAMELLIA:!SEED:!3DES:!DES:!RC4:!eNULL";
- description = "Ciphers to choose from when negotiating tls handshakes.";
+ # Keep in sync with https://ssl-config.mozilla.org/#server=nginx&config=intermediate
+ default = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
+ description = "Ciphers to choose from when negotiating TLS handshakes.";
};
sslProtocols = mkOption {
diff --git a/nixpkgs/nixos/modules/services/web-servers/uwsgi.nix b/nixpkgs/nixos/modules/services/web-servers/uwsgi.nix
index 3481b5e6040..4b74c329e3d 100644
--- a/nixpkgs/nixos/modules/services/web-servers/uwsgi.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/uwsgi.nix
@@ -32,7 +32,7 @@ let
inherit plugins;
} // removeAttrs c [ "type" "pythonPackages" ]
// optionalAttrs (python != null) {
- pythonpath = "${pythonEnv}/${python.sitePackages}";
+ pyhome = "${pythonEnv}";
env =
# Argh, uwsgi expects list of key-values there instead of a dictionary.
let env' = c.env or [];
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix
index 4a6f2ca727d..910a246d776 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix
@@ -86,6 +86,7 @@ in
pkgs.shared-mime-info
pkgs.xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/
pkgs.mate.mate-settings-daemon
+ pkgs.yelp # for 'Contents' in 'Help' menus
];
programs.dconf.enable = true;
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix
index b46a2d189ef..869c6694489 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix
@@ -16,7 +16,10 @@ in
{
- meta.maintainers = pkgs.pantheon.maintainers;
+ meta = {
+ doc = ./pantheon.xml;
+ maintainers = pkgs.pantheon.maintainers;
+ };
options = {
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.xml b/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.xml
new file mode 100644
index 00000000000..4d92a7446c0
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.xml
@@ -0,0 +1,130 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xml:id="chap-pantheon">
+ <title>Pantheon Destkop</title>
+ <para>
+ Pantheon is the desktop environment created for the elementary OS distribution. It is written from scratch in Vala, utilizing GNOME technologies with GTK 3 and Granite.
+ </para>
+ <section xml:id="sec-pantheon-enable">
+ <title>Enabling Pantheon</title>
+
+ <para>
+ All of Pantheon is working in NixOS and the applications should be available, aside from a few <link xlink:href="https://github.com/NixOS/nixpkgs/issues/58161">exceptions</link>. To enable Pantheon, set
+<programlisting>
+<xref linkend="opt-services.xserver.desktopManager.pantheon.enable"/> = true;
+</programlisting>
+ This automatically enables LightDM and Pantheon's LightDM greeter. If you'd like to disable this, set
+<programlisting>
+<xref linkend="opt-services.xserver.displayManager.lightdm.greeters.pantheon.enable"/> = false;
+<xref linkend="opt-services.xserver.displayManager.lightdm.enable"/> = false;
+</programlisting>
+ but please be aware using Pantheon without LightDM as a display manager will break screenlocking from the UI. The NixOS module for Pantheon installs all of Pantheon's default applications. If you'd like to not install Pantheon's apps, set
+<programlisting>
+<xref linkend="opt-services.pantheon.apps.enable"/> = false;
+</programlisting>
+ You can also use <xref linkend="opt-environment.pantheon.excludePackages"/> to remove any other app (like <package>geary</package>).
+ </para>
+ </section>
+ <section xml:id="sec-pantheon-wingpanel-switchboard">
+ <title>Wingpanel and Switchboard plugins</title>
+
+ <para>
+ Wingpanel and Switchboard work differently than they do in other distributions, as far as using plugins. You cannot install a plugin globally (like with <option>environment.systemPackages</option>) to start using it. You should instead be using the following options:
+ <itemizedlist>
+ <listitem>
+ <para>
+ <xref linkend="opt-services.xserver.desktopManager.pantheon.extraWingpanelIndicators"/>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <xref linkend="opt-services.xserver.desktopManager.pantheon.extraSwitchboardPlugs"/>
+ </para>
+ </listitem>
+ </itemizedlist>
+ to configure the programs with plugs or indicators.
+ </para>
+
+ <para>
+ The difference in NixOS is both these programs are patched to load plugins from a directory that is the value of an environment variable. All of which is controlled in Nix. If you need to configure the particular packages manually you can override the packages like:
+<programlisting>
+wingpanel-with-indicators.override {
+ indicators = [
+ pkgs.some-special-indicator
+ ];
+};
+
+switchboard-with-plugs.override {
+ plugs = [
+ pkgs.some-special-plug
+ ];
+};
+</programlisting>
+ please note that, like how the NixOS options describe these as extra plugins, this would only add to the default plugins included with the programs. If for some reason you'd like to configure which plugins to use exactly, both packages have an argument for this:
+<programlisting>
+wingpanel-with-indicators.override {
+ useDefaultIndicators = false;
+ indicators = specialListOfIndicators;
+};
+
+switchboard-with-plugs.override {
+ useDefaultPlugs = false;
+ plugs = specialListOfPlugs;
+};
+</programlisting>
+ this could be most useful for testing a particular plug-in in isolation.
+ </para>
+ </section>
+ <section xml:id="sec-pantheon-faq">
+ <title>FAQ</title>
+
+ <variablelist>
+ <varlistentry xml:id="sec-pantheon-faq-messed-up-theme">
+ <term>
+ I have switched from a different desktop and Pantheon’s theming looks messed up.
+ </term>
+ <listitem>
+ <para>
+ Open Switchboard and go to: <guilabel>Administration</guilabel> → <guilabel>About</guilabel> → <guilabel>Restore Default Settings</guilabel> → <guibutton>Restore Settings</guibutton>. This will reset any dconf settings to their Pantheon defaults. Note this could reset certain GNOME specific preferences if that desktop was used prior.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry xml:id="sec-pantheon-faq-slow-shutdown">
+ <term>
+ Using Pantheon sometimes makes my shutdown take a long time.
+ </term>
+ <listitem>
+ <para>
+ We have not yet determined what processes fight with systemd during shutdown, there are many reports. In elementary OS the default system timeout is lowered to lessen the impact of the issue. If you'd like to do this in NixOS, set
+<programlisting>
+ <xref linkend="opt-systemd.extraConfig"/> = ''
+ DefaultTimeoutStopSec=10s
+ DefaultTimeoutStartSec=10s
+'';
+</programlisting>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry xml:id="sec-pantheon-faq-gnome3-and-pantheon">
+ <term>
+ I cannot enable both GNOME 3 and Pantheon.
+ </term>
+ <listitem>
+ <para>
+ This is a known <link xlink:href="https://github.com/NixOS/nixpkgs/issues/64611">issue</link> and there is no known workaround.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry xml:id="sec-pantheon-faq-appcenter">
+ <term>
+ Does AppCenter work, or is it available?
+ </term>
+ <listitem>
+ <para>
+ AppCenter has been available since 20.03, but it is of little use. This is because there is no functioning PackageKit backend for Nix 2.0. In the near future you will be able to install Flatpak applications from AppCenter on NixOS. See this <link xlink:href="https://github.com/NixOS/nixpkgs/issues/70214">issue</link>.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+</chapter>
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix
index 2538858ac0f..60ef0159ff1 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix
@@ -8,6 +8,137 @@ let
cfg = xcfg.desktopManager.plasma5;
inherit (pkgs) kdeApplications plasma5 libsForQt5 qt5;
+ inherit (pkgs) writeText;
+
+ pulseaudio = config.hardware.pulseaudio;
+ pactl = "${getBin pulseaudio.package}/bin/pactl";
+ startplasma-x11 = "${getBin plasma5.plasma-workspace}/bin/startplasma-x11";
+ sed = "${getBin pkgs.gnused}/bin/sed";
+
+ gtkrc2 = writeText "gtkrc-2.0" ''
+ # Default GTK+ 2 config for NixOS Plasma 5
+ include "/run/current-system/sw/share/themes/Breeze/gtk-2.0/gtkrc"
+ style "user-font"
+ {
+ font_name="Sans Serif Regular"
+ }
+ widget_class "*" style "user-font"
+ gtk-font-name="Sans Serif Regular 10"
+ gtk-theme-name="Breeze"
+ gtk-icon-theme-name="breeze"
+ gtk-fallback-icon-theme="hicolor"
+ gtk-cursor-theme-name="breeze_cursors"
+ gtk-toolbar-style=GTK_TOOLBAR_ICONS
+ gtk-menu-images=1
+ gtk-button-images=1
+ '';
+
+ gtk3_settings = writeText "settings.ini" ''
+ [Settings]
+ gtk-font-name=Sans Serif Regular 10
+ gtk-theme-name=Breeze
+ gtk-icon-theme-name=breeze
+ gtk-fallback-icon-theme=hicolor
+ gtk-cursor-theme-name=breeze_cursors
+ gtk-toolbar-style=GTK_TOOLBAR_ICONS
+ gtk-menu-images=1
+ gtk-button-images=1
+ '';
+
+ kcminputrc = writeText "kcminputrc" ''
+ [Mouse]
+ cursorTheme=breeze_cursors
+ cursorSize=0
+ '';
+
+ activationScript = ''
+ ${set_XDG_CONFIG_HOME}
+
+ # The KDE icon cache is supposed to update itself automatically, but it uses
+ # the timestamp on the icon theme directory as a trigger. This doesn't work
+ # on NixOS because the timestamp never changes. As a workaround, delete the
+ # icon cache at login and session activation.
+ # See also: http://lists-archives.org/kde-devel/26175-what-when-will-icon-cache-refresh.html
+ rm -fv $HOME/.cache/icon-cache.kcache
+
+ # xdg-desktop-settings generates this empty file but
+ # it makes kbuildsyscoca5 fail silently. To fix this
+ # remove that menu if it exists.
+ rm -fv ''${XDG_CONFIG_HOME}/menus/applications-merged/xdg-desktop-menu-dummy.menu
+
+ # Qt writes a weird ‘libraryPath’ line to
+ # ~/.config/Trolltech.conf that causes the KDE plugin
+ # paths of previous KDE invocations to be searched.
+ # Obviously using mismatching KDE libraries is potentially
+ # disastrous, so here we nuke references to the Nix store
+ # in Trolltech.conf. A better solution would be to stop
+ # Qt from doing this wackiness in the first place.
+ trolltech_conf="''${XDG_CONFIG_HOME}/Trolltech.conf"
+ if [ -e "$trolltech_conf" ]; then
+ ${sed} -i "$trolltech_conf" -e '/nix\\store\|nix\/store/ d'
+ fi
+
+ # Remove the kbuildsyscoca5 cache. It will be regenerated
+ # immediately after. This is necessary for kbuildsyscoca5 to
+ # recognize that software that has been removed.
+ rm -fv $HOME/.cache/ksycoca*
+
+ ${pkgs.libsForQt5.kservice}/bin/kbuildsycoca5
+ '';
+
+ set_XDG_CONFIG_HOME = ''
+ # Set the default XDG_CONFIG_HOME if it is unset.
+ # Per the XDG Base Directory Specification:
+ # https://specifications.freedesktop.org/basedir-spec/latest
+ # 1. Never export this variable! If it is unset, then child processes are
+ # expected to set the default themselves.
+ # 2. Contaminate / if $HOME is unset; do not check if $HOME is set.
+ XDG_CONFIG_HOME=''${XDG_CONFIG_HOME:-$HOME/.config}
+ '';
+
+ startplasma =
+ ''
+ ${set_XDG_CONFIG_HOME}
+ mkdir -p "''${XDG_CONFIG_HOME}"
+
+ ''
+ + optionalString pulseaudio.enable ''
+ # Load PulseAudio module for routing support.
+ # See also: http://colin.guthr.ie/2009/10/so-how-does-the-kde-pulseaudio-support-work-anyway/
+ ${pactl} load-module module-device-manager "do_routing=1"
+
+ ''
+ + ''
+ ${activationScript}
+
+ # Create default configurations if Plasma has never been started.
+ kdeglobals="''${XDG_CONFIG_HOME}/kdeglobals"
+ if ! [ -f "$kdeglobals" ]
+ then
+ kcminputrc="''${XDG_CONFIG_HOME}/kcminputrc"
+ if ! [ -f "$kcminputrc" ]
+ then
+ cat ${kcminputrc} >"$kcminputrc"
+ fi
+
+ gtkrc2="$HOME/.gtkrc-2.0"
+ if ! [ -f "$gtkrc2" ]
+ then
+ cat ${gtkrc2} >"$gtkrc2"
+ fi
+
+ gtk3_settings="''${XDG_CONFIG_HOME}/gtk-3.0/settings.ini"
+ if ! [ -f "$gtk3_settings" ]
+ then
+ mkdir -p "$(dirname "$gtk3_settings")"
+ cat ${gtk3_settings} >"$gtk3_settings"
+ fi
+ fi
+
+ ''
+ + ''
+ exec "${startplasma-x11}"
+ '';
in
@@ -41,27 +172,7 @@ in
services.xserver.desktopManager.session = singleton {
name = "plasma5";
bgSupport = true;
- start = ''
- # Load PulseAudio module for routing support.
- # See http://colin.guthr.ie/2009/10/so-how-does-the-kde-pulseaudio-support-work-anyway/
- ${optionalString config.hardware.pulseaudio.enable ''
- ${getBin config.hardware.pulseaudio.package}/bin/pactl load-module module-device-manager "do_routing=1"
- ''}
-
- if [ -f "$HOME/.config/kdeglobals" ]
- then
- # Remove extraneous font style names.
- # See also: https://phabricator.kde.org/D9070
- ${getBin pkgs.gnused}/bin/sed -i "$HOME/.config/kdeglobals" \
- -e '/^fixed=/ s/,Regular$//' \
- -e '/^font=/ s/,Regular$//' \
- -e '/^menuFont=/ s/,Regular$//' \
- -e '/^smallestReadableFont=/ s/,Regular$//' \
- -e '/^toolBarFont=/ s/,Regular$//'
- fi
-
- exec "${getBin plasma5.plasma-workspace}/bin/startkde"
- '';
+ start = startplasma;
};
security.wrappers = {
@@ -137,6 +248,7 @@ in
libkscreen
libksysguard
milou
+ plasma-browser-integration
plasma-integration
polkit-kde-agent
systemsettings
@@ -226,29 +338,7 @@ in
xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-kde ];
# Update the start menu for each user that is currently logged in
- system.userActivationScripts.plasmaSetup = ''
- # The KDE icon cache is supposed to update itself
- # automatically, but it uses the timestamp on the icon
- # theme directory as a trigger. Since in Nix the
- # timestamp is always the same, this doesn't work. So as
- # a workaround, nuke the icon cache on login. This isn't
- # perfect, since it may require logging out after
- # installing new applications to update the cache.
- # See http://lists-archives.org/kde-devel/26175-what-when-will-icon-cache-refresh.html
- rm -fv $HOME/.cache/icon-cache.kcache
-
- # xdg-desktop-settings generates this empty file but
- # it makes kbuildsyscoca5 fail silently. To fix this
- # remove that menu if it exists.
- rm -fv $HOME/.config/menus/applications-merged/xdg-desktop-menu-dummy.menu
-
- # Remove the kbuildsyscoca5 cache. It will be regenerated
- # immediately after. This is necessary for kbuildsyscoca5 to
- # recognize that software that has been removed.
- rm -fv $HOME/.cache/ksycoca*
-
- ${pkgs.libsForQt5.kservice}/bin/kbuildsycoca5
- '';
+ system.userActivationScripts.plasmaSetup = activationScript;
})
];
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/xfce.nix
index 21f59074f3a..a08b1947f65 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/xfce.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/xfce.nix
@@ -127,9 +127,14 @@ in
"/share/gtksourceview-4.0"
];
- services.xserver.displayManager.sessionPackages = [
- pkgs.xfce.xfce4-session
- ];
+ services.xserver.desktopManager.session = [{
+ name = "xfce";
+ bgSupport = true;
+ start = ''
+ ${pkgs.runtimeShell} ${pkgs.xfce.xfce4-session.xinitrc} &
+ waitPID=$!
+ '';
+ }];
services.xserver.updateDbusEnvironment = true;
services.xserver.gdk-pixbuf.modulePackages = [ pkgs.librsvg ];
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/default.nix b/nixpkgs/nixos/modules/services/x11/display-managers/default.nix
index 1efd0739376..5d49ca94387 100644
--- a/nixpkgs/nixos/modules/services/x11/display-managers/default.nix
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/default.nix
@@ -141,9 +141,11 @@ let
'';
dmDefault = cfg.desktopManager.default;
+ # fallback default for cases when only default wm is set
+ dmFallbackDefault = if dmDefault != null then dmDefault else "none";
wmDefault = cfg.windowManager.default;
- defaultSessionFromLegacyOptions = concatStringsSep "+" (filter (s: s != null) ([ dmDefault ] ++ optional (wmDefault != "none") wmDefault));
+ defaultSessionFromLegacyOptions = dmFallbackDefault + optionalString (wmDefault != null && wmDefault != "none") "+${wmDefault}";
in
@@ -358,7 +360,7 @@ in
{ c = wmDefault; t = "- services.xserver.windowManager.default"; }
]))}
Please use
- services.xserver.displayManager.defaultSession = "${concatStringsSep "+" (filter (s: s != null) [ dmDefault wmDefault ])}";
+ services.xserver.displayManager.defaultSession = "${defaultSessionFromLegacyOptions}";
instead.
''
];
@@ -425,6 +427,7 @@ in
TryExec=${script}
Exec=${script}
Name=${sessionName}
+ DesktopNames=${sessionName}
'';
} // {
providedSessions = [ sessionName ];
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/gdm.nix b/nixpkgs/nixos/modules/services/x11/display-managers/gdm.nix
index 325023f4121..e0ac47bb766 100644
--- a/nixpkgs/nixos/modules/services/x11/display-managers/gdm.nix
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/gdm.nix
@@ -166,9 +166,10 @@ in
};
systemd.tmpfiles.rules = [
- "d /run/gdm/.config 0711 gdm gdm -"
+ "d /run/gdm/.config 0711 gdm gdm"
] ++ optionals config.hardware.pulseaudio.enable [
- "L+ /run/gdm/.config/pulse - - - - ${pulseConfig}"
+ "d /run/gdm/.config/pulse 0711 gdm gdm"
+ "L+ /run/gdm/.config/pulse/${pulseConfig.name} - - - - ${pulseConfig}"
] ++ optionals config.services.gnome3.gnome-initial-setup.enable [
# Create stamp file for gnome-initial-setup to prevent it starting in GDM.
"f /run/gdm/.config/gnome-initial-setup-done 0711 gdm gdm - yes"
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/tiny.nix b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/tiny.nix
new file mode 100644
index 00000000000..a9ba8e6280d
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/tiny.nix
@@ -0,0 +1,92 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ dmcfg = config.services.xserver.displayManager;
+ ldmcfg = dmcfg.lightdm;
+ cfg = ldmcfg.greeters.tiny;
+
+in
+{
+ options = {
+
+ services.xserver.displayManager.lightdm.greeters.tiny = {
+
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to enable lightdm-tiny-greeter as the lightdm greeter.
+
+ Note that this greeter starts only the default X session.
+ You can configure the default X session using
+ <xref linkend="opt-services.xserver.displayManager.defaultSession"/>.
+ '';
+ };
+
+ label = {
+ user = mkOption {
+ type = types.str;
+ default = "Username";
+ description = ''
+ The string to represent the user_text label.
+ '';
+ };
+
+ pass = mkOption {
+ type = types.str;
+ default = "Password";
+ description = ''
+ The string to represent the pass_text label.
+ '';
+ };
+ };
+
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Section to describe style and ui.
+ '';
+ };
+
+ };
+
+ };
+
+ config = mkIf (ldmcfg.enable && cfg.enable) {
+
+ services.xserver.displayManager.lightdm.greeters.gtk.enable = false;
+
+ nixpkgs.config.lightdm-tiny-greeter.conf =
+ let
+ configHeader = ''
+ #include <gtk/gtk.h>
+ static const char *user_text = "${cfg.label.user}";
+ static const char *pass_text = "${cfg.label.pass}";
+ static const char *session = "${dmcfg.defaultSession}";
+ '';
+ in
+ optionalString (cfg.extraConfig != "")
+ (configHeader + cfg.extraConfig);
+
+ services.xserver.displayManager.lightdm.greeter =
+ mkDefault {
+ package = pkgs.lightdm-tiny-greeter.xgreeters;
+ name = "lightdm-tiny-greeter";
+ };
+
+ assertions = [
+ {
+ assertion = dmcfg.defaultSession != null;
+ message = ''
+ Please set: services.xserver.displayManager.defaultSession
+ '';
+ }
+ ];
+
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/lightdm.nix b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm.nix
index f7face0adb7..cb7b5f95958 100644
--- a/nixpkgs/nixos/modules/services/x11/display-managers/lightdm.nix
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm.nix
@@ -77,6 +77,7 @@ in
./lightdm-greeters/mini.nix
./lightdm-greeters/enso-os.nix
./lightdm-greeters/pantheon.nix
+ ./lightdm-greeters/tiny.nix
];
options = {
diff --git a/nixpkgs/nixos/modules/services/x11/unclutter.nix b/nixpkgs/nixos/modules/services/x11/unclutter.nix
index c0868604a68..56e30c79d1f 100644
--- a/nixpkgs/nixos/modules/services/x11/unclutter.nix
+++ b/nixpkgs/nixos/modules/services/x11/unclutter.nix
@@ -61,7 +61,7 @@ in {
serviceConfig.ExecStart = ''
${cfg.package}/bin/unclutter \
-idle ${toString cfg.timeout} \
- -jitter ${toString (cfg.threeshold - 1)} \
+ -jitter ${toString (cfg.threshold - 1)} \
${optionalString cfg.keystroke "-keystroke"} \
${concatMapStrings (x: " -"+x) cfg.extraOptions} \
-not ${concatStringsSep " " cfg.excluded} \
diff --git a/nixpkgs/nixos/modules/services/x11/urxvtd.nix b/nixpkgs/nixos/modules/services/x11/urxvtd.nix
index 9bfcfa9b065..867ac38a944 100644
--- a/nixpkgs/nixos/modules/services/x11/urxvtd.nix
+++ b/nixpkgs/nixos/modules/services/x11/urxvtd.nix
@@ -18,10 +18,10 @@ in {
};
package = mkOption {
- default = pkgs.rxvt_unicode-with-plugins;
- defaultText = "pkgs.rxvt_unicode-with-plugins";
+ default = pkgs.rxvt-unicode;
+ defaultText = "pkgs.rxvt-unicode";
description = ''
- Package to install. Usually pkgs.rxvt_unicode-with-plugins or pkgs.rxvt_unicode
+ Package to install. Usually pkgs.rxvt-unicode.
'';
type = types.package;
};
diff --git a/nixpkgs/nixos/modules/services/x11/xserver.nix b/nixpkgs/nixos/modules/services/x11/xserver.nix
index 7f0de96d208..74d702ea1c3 100644
--- a/nixpkgs/nixos/modules/services/x11/xserver.nix
+++ b/nixpkgs/nixos/modules/services/x11/xserver.nix
@@ -573,7 +573,7 @@ in
then { modules = [xorg.${"xf86video" + name}]; }
else null)
knownVideoDrivers;
- in optional (driver != null) ({ inherit name; modules = []; driverName = name; } // driver));
+ in optional (driver != null) ({ inherit name; modules = []; driverName = name; display = true; } // driver));
assertions = [
{ assertion = config.security.polkit.enable;
@@ -740,7 +740,7 @@ in
${cfg.serverLayoutSection}
# Reference the Screen sections for each driver. This will
# cause the X server to try each in turn.
- ${flip concatMapStrings cfg.drivers (d: ''
+ ${flip concatMapStrings (filter (d: d.display) cfg.drivers) (d: ''
Screen "Screen-${d.name}[0]"
'')}
EndSection
@@ -764,42 +764,44 @@ in
${driver.deviceSection or ""}
${xrandrDeviceSection}
EndSection
+ ${optionalString driver.display ''
+
+ Section "Screen"
+ Identifier "Screen-${driver.name}[0]"
+ Device "Device-${driver.name}[0]"
+ ${optionalString (cfg.monitorSection != "") ''
+ Monitor "Monitor[0]"
+ ''}
+
+ ${cfg.screenSection}
+ ${driver.screenSection or ""}
+
+ ${optionalString (cfg.defaultDepth != 0) ''
+ DefaultDepth ${toString cfg.defaultDepth}
+ ''}
+
+ ${optionalString
+ (driver.name != "virtualbox" &&
+ (cfg.resolutions != [] ||
+ cfg.extraDisplaySettings != "" ||
+ cfg.virtualScreen != null))
+ (let
+ f = depth:
+ ''
+ SubSection "Display"
+ Depth ${toString depth}
+ ${optionalString (cfg.resolutions != [])
+ "Modes ${concatMapStrings (res: ''"${toString res.x}x${toString res.y}"'') cfg.resolutions}"}
+ ${cfg.extraDisplaySettings}
+ ${optionalString (cfg.virtualScreen != null)
+ "Virtual ${toString cfg.virtualScreen.x} ${toString cfg.virtualScreen.y}"}
+ EndSubSection
+ '';
+ in concatMapStrings f [8 16 24]
+ )}
- Section "Screen"
- Identifier "Screen-${driver.name}[0]"
- Device "Device-${driver.name}[0]"
- ${optionalString (cfg.monitorSection != "") ''
- Monitor "Monitor[0]"
- ''}
-
- ${cfg.screenSection}
- ${driver.screenSection or ""}
-
- ${optionalString (cfg.defaultDepth != 0) ''
- DefaultDepth ${toString cfg.defaultDepth}
- ''}
-
- ${optionalString
- (driver.name != "virtualbox" &&
- (cfg.resolutions != [] ||
- cfg.extraDisplaySettings != "" ||
- cfg.virtualScreen != null))
- (let
- f = depth:
- ''
- SubSection "Display"
- Depth ${toString depth}
- ${optionalString (cfg.resolutions != [])
- "Modes ${concatMapStrings (res: ''"${toString res.x}x${toString res.y}"'') cfg.resolutions}"}
- ${cfg.extraDisplaySettings}
- ${optionalString (cfg.virtualScreen != null)
- "Virtual ${toString cfg.virtualScreen.x} ${toString cfg.virtualScreen.y}"}
- EndSubSection
- '';
- in concatMapStrings f [8 16 24]
- )}
-
- EndSection
+ EndSection
+ ''}
'')}
${xrandrMonitorSections}
diff --git a/nixpkgs/nixos/modules/system/activation/activation-script.nix b/nixpkgs/nixos/modules/system/activation/activation-script.nix
index 495d77dfd49..ddfd1af4a31 100644
--- a/nixpkgs/nixos/modules/system/activation/activation-script.nix
+++ b/nixpkgs/nixos/modules/system/activation/activation-script.nix
@@ -162,16 +162,6 @@ in
<literal>/usr/bin/env</literal>.
'';
};
-
- environment.ld-linux = mkOption {
- default = false;
- type = types.bool;
- visible = false;
- description = ''
- Install symlink to ld-linux(8) system-wide to allow running unmodified ELF binaries.
- It might be useful to run games or executables distributed inside jar files.
- '';
- };
};
@@ -205,30 +195,9 @@ in
''
else ''
rm -f /usr/bin/env
- rmdir -p /usr/bin || true
+ rmdir --ignore-fail-on-non-empty /usr/bin /usr
'';
- system.activationScripts.ld-linux =
- concatStrings (
- mapAttrsToList
- (target: source:
- if config.environment.ld-linux then ''
- mkdir -m 0755 -p $(dirname ${target})
- ln -sfn ${escapeShellArg source} ${target}.tmp
- mv -f ${target}.tmp ${target} # atomically replace
- '' else ''
- rm -f ${target}
- rmdir $(dirname ${target}) || true
- '')
- {
- "i686-linux" ."/lib/ld-linux.so.2" = "${pkgs.glibc.out}/lib/ld-linux.so.2";
- "x86_64-linux" ."/lib/ld-linux.so.2" = "${pkgs.pkgsi686Linux.glibc.out}/lib/ld-linux.so.2";
- "x86_64-linux" ."/lib64/ld-linux-x86-64.so.2" = "${pkgs.glibc.out}/lib64/ld-linux-x86-64.so.2";
- "aarch64-linux"."/lib/ld-linux-aarch64.so.1" = "${pkgs.glibc.out}/lib/ld-linux-aarch64.so.1";
- "armv7l-linux" ."/lib/ld-linux-armhf.so.3" = "${pkgs.glibc.out}/lib/ld-linux-armhf.so.3";
- }.${pkgs.stdenv.system} or {}
- );
-
system.activationScripts.specialfs =
''
specialMount() {
diff --git a/nixpkgs/nixos/modules/system/activation/switch-to-configuration.pl b/nixpkgs/nixos/modules/system/activation/switch-to-configuration.pl
index 641cf9faadc..b82d69b3bb8 100644
--- a/nixpkgs/nixos/modules/system/activation/switch-to-configuration.pl
+++ b/nixpkgs/nixos/modules/system/activation/switch-to-configuration.pl
@@ -183,7 +183,7 @@ while (my ($unit, $state) = each %{$activePrev}) {
# active after the system has resumed, which probably
# should not be the case. Just ignore it.
if ($unit ne "suspend.target" && $unit ne "hibernate.target" && $unit ne "hybrid-sleep.target") {
- unless (boolIsTrue($unitInfo->{'RefuseManualStart'} // "no")) {
+ unless (boolIsTrue($unitInfo->{'RefuseManualStart'} // "no") || boolIsTrue($unitInfo->{'X-OnlyManualStart'} // "no")) {
$unitsToStart{$unit} = 1;
recordUnit($startListFile, $unit);
# Don't spam the user with target units that always get started.
@@ -222,7 +222,7 @@ while (my ($unit, $state) = each %{$activePrev}) {
$unitsToReload{$unit} = 1;
recordUnit($reloadListFile, $unit);
}
- elsif (!boolIsTrue($unitInfo->{'X-RestartIfChanged'} // "yes") || boolIsTrue($unitInfo->{'RefuseManualStop'} // "no") ) {
+ elsif (!boolIsTrue($unitInfo->{'X-RestartIfChanged'} // "yes") || boolIsTrue($unitInfo->{'RefuseManualStop'} // "no") || boolIsTrue($unitInfo->{'X-OnlyManualStart'} // "no")) {
$unitsToSkip{$unit} = 1;
} else {
if (!boolIsTrue($unitInfo->{'X-StopIfChanged'} // "yes")) {
diff --git a/nixpkgs/nixos/modules/system/activation/top-level.nix b/nixpkgs/nixos/modules/system/activation/top-level.nix
index f67d2900561..14bd751ce32 100644
--- a/nixpkgs/nixos/modules/system/activation/top-level.nix
+++ b/nixpkgs/nixos/modules/system/activation/top-level.nix
@@ -15,6 +15,7 @@ let
map (childConfig:
(import ../../../lib/eval-config.nix {
inherit baseModules;
+ system = config.nixpkgs.initialSystem;
modules =
(optionals inheritParent modules)
++ [ ./no-clone.nix ]
diff --git a/nixpkgs/nixos/modules/system/boot/initrd-network.nix b/nixpkgs/nixos/modules/system/boot/initrd-network.nix
index cb8fc957a99..0ab6e626b34 100644
--- a/nixpkgs/nixos/modules/system/boot/initrd-network.nix
+++ b/nixpkgs/nixos/modules/system/boot/initrd-network.nix
@@ -6,7 +6,11 @@ let
cfg = config.boot.initrd.network;
- dhcpinterfaces = lib.attrNames (lib.filterAttrs (iface: v: v.useDHCP == true) (config.networking.interfaces or {}));
+ dhcpInterfaces = lib.attrNames (lib.filterAttrs (iface: v: v.useDHCP == true) (config.networking.interfaces or {}));
+ doDhcp = config.networking.useDHCP || dhcpInterfaces != [];
+ dhcpIfShellExpr = if config.networking.useDHCP
+ then "$(ls /sys/class/net/ | grep -v ^lo$)"
+ else lib.concatMapStringsSep " " lib.escapeShellArg dhcpInterfaces;
udhcpcScript = pkgs.writeScript "udhcp-script"
''
@@ -62,6 +66,16 @@ in
'';
};
+ boot.initrd.network.flushBeforeStage2 = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether to clear the configuration of the interfaces that were set up in
+ the initrd right before stage 2 takes over. Stage 2 will do the regular network
+ configuration based on the NixOS networking options.
+ '';
+ };
+
boot.initrd.network.udhcpc.extraArgs = mkOption {
default = [];
type = types.listOf types.str;
@@ -89,49 +103,45 @@ in
boot.initrd.kernelModules = [ "af_packet" ];
boot.initrd.extraUtilsCommands = ''
- copy_bin_and_libs ${pkgs.mkinitcpio-nfs-utils}/bin/ipconfig
+ copy_bin_and_libs ${pkgs.klibc}/lib/klibc/bin.static/ipconfig
'';
boot.initrd.preLVMCommands = mkBefore (
# Search for interface definitions in command line.
''
+ ifaces=""
for o in $(cat /proc/cmdline); do
case $o in
ip=*)
- ipconfig $o && hasNetwork=1
+ ipconfig $o && ifaces="$ifaces $(echo $o | cut -d: -f6)"
;;
esac
done
''
# Otherwise, use DHCP.
- + optionalString (config.networking.useDHCP || dhcpinterfaces != []) ''
- if [ -z "$hasNetwork" ]; then
-
- # Bring up all interfaces.
- for iface in $(ls /sys/class/net/); do
- echo "bringing up network interface $iface..."
- ip link set "$iface" up
- done
+ + optionalString doDhcp ''
+ # Bring up all interfaces.
+ for iface in ${dhcpIfShellExpr}; do
+ echo "bringing up network interface $iface..."
+ ip link set "$iface" up && ifaces="$ifaces $iface"
+ done
- # Acquire DHCP leases.
- for iface in ${ if config.networking.useDHCP then
- "$(ls /sys/class/net/ | grep -v ^lo$)"
- else
- lib.concatMapStringsSep " " lib.escapeShellArg dhcpinterfaces
- }; do
- echo "acquiring IP address via DHCP on $iface..."
- udhcpc --quit --now -i $iface -O staticroutes --script ${udhcpcScript} ${udhcpcArgs} && hasNetwork=1
- done
- fi
+ # Acquire DHCP leases.
+ for iface in ${dhcpIfShellExpr}; do
+ echo "acquiring IP address via DHCP on $iface..."
+ udhcpc --quit --now -i $iface -O staticroutes --script ${udhcpcScript} ${udhcpcArgs}
+ done
''
- + ''
- if [ -n "$hasNetwork" ]; then
- echo "networking is up!"
- ${cfg.postCommands}
- fi
- '');
+ + cfg.postCommands);
+
+ boot.initrd.postMountCommands = mkIf cfg.flushBeforeStage2 ''
+ for iface in $ifaces; do
+ ip address flush "$iface"
+ ip link down "$iface"
+ done
+ '';
};
diff --git a/nixpkgs/nixos/modules/system/boot/kernel.nix b/nixpkgs/nixos/modules/system/boot/kernel.nix
index 6edb9082e75..43871f439f7 100644
--- a/nixpkgs/nixos/modules/system/boot/kernel.nix
+++ b/nixpkgs/nixos/modules/system/boot/kernel.nix
@@ -101,7 +101,12 @@ in
type = types.bool;
default = false;
description = ''
- Whether to activate VESA video mode on boot.
+ (Deprecated) This option, if set, activates the VESA 800x600 video
+ mode on boot and disables kernel modesetting. It is equivalent to
+ specifying <literal>[ "vga=0x317" "nomodeset" ]</literal> in the
+ <option>boot.kernelParams</option> option. This option is
+ deprecated as of 2020: Xorg now works better with modesetting, and
+ you might want a different VESA vga setting, anyway.
'';
};
@@ -187,139 +192,144 @@ in
###### implementation
- config = mkIf (!config.boot.isContainer) {
-
- system.build = { inherit kernel; };
-
- system.modulesTree = [ kernel ] ++ config.boot.extraModulePackages;
-
- # Implement consoleLogLevel both in early boot and using sysctl
- # (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" "nomodeset" ];
-
- boot.kernel.sysctl."kernel.printk" = mkDefault config.boot.consoleLogLevel;
-
- boot.kernelModules = [ "loop" "atkbd" ];
-
- boot.initrd.availableKernelModules =
- [ # Note: most of these (especially the SATA/PATA modules)
- # shouldn't be included by default since nixos-generate-config
- # detects them, but I'm keeping them for now for backwards
- # compatibility.
-
- # Some SATA/PATA stuff.
- "ahci"
- "sata_nv"
- "sata_via"
- "sata_sis"
- "sata_uli"
- "ata_piix"
- "pata_marvell"
-
- # Standard SCSI stuff.
- "sd_mod"
- "sr_mod"
-
- # SD cards and internal eMMC drives.
- "mmc_block"
-
- # Support USB keyboards, in case the boot fails and we only have
- # a USB keyboard, or for LUKS passphrase prompt.
- "uhci_hcd"
- "ehci_hcd"
- "ehci_pci"
- "ohci_hcd"
- "ohci_pci"
- "xhci_hcd"
- "xhci_pci"
- "usbhid"
- "hid_generic" "hid_lenovo" "hid_apple" "hid_roccat"
- "hid_logitech_hidpp" "hid_logitech_dj"
-
- ] ++ optionals (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) [
- # Misc. x86 keyboard stuff.
- "pcips2" "atkbd" "i8042"
-
- # x86 RTC needed by the stage 2 init script.
- "rtc_cmos"
- ];
-
- boot.initrd.kernelModules =
- [ # For LVM.
- "dm_mod"
- ];
-
- # The Linux kernel >= 2.6.27 provides firmware.
- hardware.firmware = [ kernel ];
-
- # Create /etc/modules-load.d/nixos.conf, which is read by
- # systemd-modules-load.service to load required kernel modules.
- environment.etc =
- { "modules-load.d/nixos.conf".source = kernelModulesConf;
- };
-
- systemd.services.systemd-modules-load =
- { wantedBy = [ "multi-user.target" ];
- restartTriggers = [ kernelModulesConf ];
- serviceConfig =
- { # Ignore failed module loads. Typically some of the
- # modules in ‘boot.kernelModules’ are "nice to have but
- # not required" (e.g. acpi-cpufreq), so we don't want to
- # barf on those.
- SuccessExitStatus = "0 1";
+ config = mkMerge
+ [ (mkIf config.boot.initrd.enable {
+ boot.initrd.availableKernelModules =
+ [ # Note: most of these (especially the SATA/PATA modules)
+ # shouldn't be included by default since nixos-generate-config
+ # detects them, but I'm keeping them for now for backwards
+ # compatibility.
+
+ # Some SATA/PATA stuff.
+ "ahci"
+ "sata_nv"
+ "sata_via"
+ "sata_sis"
+ "sata_uli"
+ "ata_piix"
+ "pata_marvell"
+
+ # Standard SCSI stuff.
+ "sd_mod"
+ "sr_mod"
+
+ # SD cards and internal eMMC drives.
+ "mmc_block"
+
+ # Support USB keyboards, in case the boot fails and we only have
+ # a USB keyboard, or for LUKS passphrase prompt.
+ "uhci_hcd"
+ "ehci_hcd"
+ "ehci_pci"
+ "ohci_hcd"
+ "ohci_pci"
+ "xhci_hcd"
+ "xhci_pci"
+ "usbhid"
+ "hid_generic" "hid_lenovo" "hid_apple" "hid_roccat"
+ "hid_logitech_hidpp" "hid_logitech_dj"
+
+ ] ++ optionals (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) [
+ # Misc. x86 keyboard stuff.
+ "pcips2" "atkbd" "i8042"
+
+ # x86 RTC needed by the stage 2 init script.
+ "rtc_cmos"
+ ];
+
+ boot.initrd.kernelModules =
+ [ # For LVM.
+ "dm_mod"
+ ];
+ })
+
+ (mkIf (!config.boot.isContainer) {
+ system.build = { inherit kernel; };
+
+ system.modulesTree = [ kernel ] ++ config.boot.extraModulePackages;
+
+ # Implement consoleLogLevel both in early boot and using sysctl
+ # (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" "nomodeset" ];
+
+ boot.kernel.sysctl."kernel.printk" = mkDefault config.boot.consoleLogLevel;
+
+ boot.kernelModules = [ "loop" "atkbd" ];
+
+ # The Linux kernel >= 2.6.27 provides firmware.
+ hardware.firmware = [ kernel ];
+
+ # Create /etc/modules-load.d/nixos.conf, which is read by
+ # systemd-modules-load.service to load required kernel modules.
+ environment.etc =
+ { "modules-load.d/nixos.conf".source = kernelModulesConf;
};
- };
-
- lib.kernelConfig = {
- isYes = option: {
- assertion = config: config.isYes option;
- message = "CONFIG_${option} is not yes!";
- configLine = "CONFIG_${option}=y";
- };
-
- isNo = option: {
- assertion = config: config.isNo option;
- message = "CONFIG_${option} is not no!";
- configLine = "CONFIG_${option}=n";
- };
-
- isModule = option: {
- assertion = config: config.isModule option;
- message = "CONFIG_${option} is not built as a module!";
- configLine = "CONFIG_${option}=m";
- };
-
- ### Usually you will just want to use these two
- # True if yes or module
- isEnabled = option: {
- assertion = config: config.isEnabled option;
- message = "CONFIG_${option} is not enabled!";
- configLine = "CONFIG_${option}=y";
- };
-
- # True if no or omitted
- isDisabled = option: {
- assertion = config: config.isDisabled option;
- message = "CONFIG_${option} is not disabled!";
- configLine = "CONFIG_${option}=n";
- };
- };
- # The config options that all modules can depend upon
- system.requiredKernelConfig = with config.lib.kernelConfig; [
- # !!! Should this really be needed?
- (isYes "MODULES")
- (isYes "BINFMT_ELF")
- ] ++ (optional (randstructSeed != "") (isYes "GCC_PLUGIN_RANDSTRUCT"));
+ systemd.services.systemd-modules-load =
+ { wantedBy = [ "multi-user.target" ];
+ restartTriggers = [ kernelModulesConf ];
+ serviceConfig =
+ { # Ignore failed module loads. Typically some of the
+ # modules in ‘boot.kernelModules’ are "nice to have but
+ # not required" (e.g. acpi-cpufreq), so we don't want to
+ # barf on those.
+ SuccessExitStatus = "0 1";
+ };
+ };
- # nixpkgs kernels are assumed to have all required features
- assertions = if config.boot.kernelPackages.kernel ? features then [] else
- let cfg = config.boot.kernelPackages.kernel.config; in map (attrs:
- { assertion = attrs.assertion cfg; inherit (attrs) message; }
- ) config.system.requiredKernelConfig;
+ lib.kernelConfig = {
+ isYes = option: {
+ assertion = config: config.isYes option;
+ message = "CONFIG_${option} is not yes!";
+ configLine = "CONFIG_${option}=y";
+ };
- };
+ isNo = option: {
+ assertion = config: config.isNo option;
+ message = "CONFIG_${option} is not no!";
+ configLine = "CONFIG_${option}=n";
+ };
+
+ isModule = option: {
+ assertion = config: config.isModule option;
+ message = "CONFIG_${option} is not built as a module!";
+ configLine = "CONFIG_${option}=m";
+ };
+
+ ### Usually you will just want to use these two
+ # True if yes or module
+ isEnabled = option: {
+ assertion = config: config.isEnabled option;
+ message = "CONFIG_${option} is not enabled!";
+ configLine = "CONFIG_${option}=y";
+ };
+
+ # True if no or omitted
+ isDisabled = option: {
+ assertion = config: config.isDisabled option;
+ message = "CONFIG_${option} is not disabled!";
+ configLine = "CONFIG_${option}=n";
+ };
+ };
+
+ # The config options that all modules can depend upon
+ system.requiredKernelConfig = with config.lib.kernelConfig;
+ [
+ # !!! Should this really be needed?
+ (isYes "MODULES")
+ (isYes "BINFMT_ELF")
+ ] ++ (optional (randstructSeed != "") (isYes "GCC_PLUGIN_RANDSTRUCT"));
+
+ # nixpkgs kernels are assumed to have all required features
+ assertions = if config.boot.kernelPackages.kernel ? features then [] else
+ let cfg = config.boot.kernelPackages.kernel.config; in map (attrs:
+ { assertion = attrs.assertion cfg; inherit (attrs) message; }
+ ) config.system.requiredKernelConfig;
+
+ })
+
+ ];
}
diff --git a/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix b/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix
index 9a4db84f7b7..b97ef88a7ca 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix
+++ b/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix
@@ -224,7 +224,11 @@ in
extraConfig = mkOption {
default = "";
- example = "serial; terminal_output.serial";
+ example = ''
+ serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1
+ terminal_input --append serial
+ terminal_output --append serial
+ '';
type = types.lines;
description = ''
Additional GRUB commands inserted in the configuration file
@@ -630,7 +634,7 @@ in
boot.loader.grub.extraPrepareConfig =
concatStrings (mapAttrsToList (n: v: ''
- ${pkgs.coreutils}/bin/cp -pf "${v}" "/boot/${n}"
+ ${pkgs.coreutils}/bin/cp -pf "${v}" "@bootPath@/${n}"
'') config.boot.loader.grub.extraFiles);
assertions = [
diff --git a/nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl
index a09c5dc4761..ca0fb0248e0 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl
+++ b/nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl
@@ -475,6 +475,9 @@ if ($grubVersion == 2) {
}
}
+# extraPrepareConfig could refer to @bootPath@, which we have to substitute
+$extraPrepareConfig =~ s/\@bootPath\@/$bootPath/g;
+
# Run extraPrepareConfig in sh
if ($extraPrepareConfig ne "") {
system((get("shell"), "-c", $extraPrepareConfig));
diff --git a/nixpkgs/nixos/modules/system/boot/loader/grub/memtest.nix b/nixpkgs/nixos/modules/system/boot/loader/grub/memtest.nix
index 94e5a14174b..71e50dd0577 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/grub/memtest.nix
+++ b/nixpkgs/nixos/modules/system/boot/loader/grub/memtest.nix
@@ -1,4 +1,4 @@
-# This module adds Memtest86+ to the GRUB boot menu.
+# This module adds Memtest86+/Memtest86 to the GRUB boot menu.
{ config, lib, pkgs, ... }:
@@ -6,6 +6,7 @@ with lib;
let
memtest86 = pkgs.memtest86plus;
+ efiSupport = config.boot.loader.grub.efiSupport;
cfg = config.boot.loader.grub.memtest86;
in
@@ -18,8 +19,11 @@ in
default = false;
type = types.bool;
description = ''
- Make Memtest86+, a memory testing program, available from the
- GRUB boot menu.
+ Make Memtest86+ (or MemTest86 if EFI support is enabled),
+ a memory testing program, available from the
+ GRUB boot menu. MemTest86 is an unfree program, so
+ this requires <literal>allowUnfree</literal> to be set to
+ <literal>true</literal>.
'';
};
@@ -75,19 +79,38 @@ in
};
};
- config = mkIf cfg.enable {
-
- boot.loader.grub.extraEntries =
- if config.boot.loader.grub.version == 2 then
- ''
- menuentry "Memtest86+" {
- linux16 @bootRoot@/memtest.bin ${toString cfg.params}
- }
- ''
- else
- throw "Memtest86+ is not supported with GRUB 1.";
-
- boot.loader.grub.extraFiles."memtest.bin" = "${memtest86}/memtest.bin";
+ config = mkMerge [
+ (mkIf (cfg.enable && efiSupport) {
+ assertions = [
+ {
+ assertion = cfg.params == [];
+ message = "Parameters are not available for MemTest86";
+ }
+ ];
+
+ boot.loader.grub.extraFiles = {
+ "memtest86.efi" = "${pkgs.memtest86-efi}/BOOTX64.efi";
+ };
- };
+ boot.loader.grub.extraEntries = ''
+ menuentry "Memtest86" {
+ chainloader /memtest86.efi
+ }
+ '';
+ })
+
+ (mkIf (cfg.enable && !efiSupport) {
+ boot.loader.grub.extraEntries =
+ if config.boot.loader.grub.version == 2 then
+ ''
+ menuentry "Memtest86+" {
+ linux16 @bootRoot@/memtest.bin ${toString cfg.params}
+ }
+ ''
+ else
+ throw "Memtest86+ is not supported with GRUB 1.";
+
+ boot.loader.grub.extraFiles."memtest.bin" = "${memtest86}/memtest.bin";
+ })
+ ];
}
diff --git a/nixpkgs/nixos/modules/system/boot/networkd.nix b/nixpkgs/nixos/modules/system/boot/networkd.nix
index 56a9d6b1138..3078f84f6e9 100644
--- a/nixpkgs/nixos/modules/system/boot/networkd.nix
+++ b/nixpkgs/nixos/modules/system/boot/networkd.nix
@@ -55,6 +55,11 @@ let
(assertMacAddress "MACAddress")
];
+ checkVRF = checkUnitConfig "VRF" [
+ (assertOnlyFields [ "Table" ])
+ (assertMinimum "Table" 0)
+ ];
+
# NOTE The PrivateKey directive is missing on purpose here, please
# do not add it to this list. The nix store is world-readable let's
# refrain ourselves from providing a footgun.
@@ -62,7 +67,12 @@ let
(assertOnlyFields [
"PrivateKeyFile" "ListenPort" "FwMark"
])
- (assertRange "FwMark" 1 4294967295)
+ # The following check won't work on nix <= 2.2
+ # see https://github.com/NixOS/nix/pull/2378
+ #
+ # Add this again when we'll have drop the
+ # nix < 2.2 support.
+ # (assertRange "FwMark" 1 4294967295)
];
# NOTE The PresharedKey directive is missing on purpose here, please
@@ -176,7 +186,12 @@ let
(assertOnlyFields [
"InterfaceId" "Independent"
])
- (assertRange "InterfaceId" 1 4294967295)
+ # The following check won't work on nix <= 2.2
+ # see https://github.com/NixOS/nix/pull/2378
+ #
+ # Add this again when we'll have drop the
+ # nix < 2.2 support.
+ # (assertRange "InterfaceId" 1 4294967295)
(assertValueOneOf "Independent" boolValues)
];
@@ -230,6 +245,26 @@ let
(assertValueOneOf "AutoJoin" boolValues)
];
+ checkRoutingPolicyRule = checkUnitConfig "RoutingPolicyRule" [
+ (assertOnlyFields [
+ "TypeOfService" "From" "To" "FirewallMark" "Table" "Priority"
+ "IncomingInterface" "OutgoingInterface" "SourcePort" "DestinationPort"
+ "IPProtocol" "InvertRule" "Family"
+ ])
+ (assertRange "TypeOfService" 0 255)
+ # The following check won't work on nix <= 2.2
+ # see https://github.com/NixOS/nix/pull/2378
+ #
+ # Add this again when we'll have drop the
+ # nix < 2.2 support.
+ # (assertRange "FirewallMark" 1 4294967295)
+ (assertInt "Priority")
+ (assertPort "SourcePort")
+ (assertPort "DestinationPort")
+ (assertValueOneOf "InvertRule" boolValues)
+ (assertValueOneOf "Family" ["ipv4" "ipv6" "both"])
+ ];
+
checkRoute = checkUnitConfig "Route" [
(assertOnlyFields [
"Gateway" "GatewayOnLink" "Destination" "Source" "Metric"
@@ -320,6 +355,14 @@ let
};
linkOptions = commonNetworkOptions // {
+ # overwrite enable option from above
+ enable = mkOption {
+ default = true;
+ type = types.bool;
+ description = ''
+ Whether to enable this .link unit. It's handled by udev no matter if <command>systemd-networkd</command> is enabled or not
+ '';
+ };
linkConfig = mkOption {
default = {};
@@ -349,6 +392,21 @@ let
'';
};
+ vrfConfig = mkOption {
+ default = {};
+ example = { Table = 2342; };
+ type = types.addCheck (types.attrsOf unitOption) checkVRF;
+ description = ''
+ Each attribute in this set specifies an option in the
+ <literal>[VRF]</literal> section of the unit. See
+ <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
+ <manvolnum>5</manvolnum></citerefentry> for details.
+ A detailed explanation about how VRFs work can be found in the
+ <link xlink:href="https://www.kernel.org/doc/Documentation/networking/vrf.txt">kernel
+ docs</link>.
+ '';
+ };
+
wireguardConfig = mkOption {
default = {};
example = {
@@ -515,6 +573,22 @@ let
};
};
+ routingPolicyRulesOptions = {
+ options = {
+ routingPolicyRuleConfig = mkOption {
+ default = { };
+ example = { routingPolicyRuleConfig = { Table = 10; IncomingInterface = "eth1"; Family = "both"; } ;};
+ type = types.addCheck (types.attrsOf unitOption) checkRoutingPolicyRule;
+ description = ''
+ Each attribute in this set specifies an option in the
+ <literal>[RoutingPolicyRule]</literal> section of the unit. See
+ <citerefentry><refentrytitle>systemd.network</refentrytitle>
+ <manvolnum>5</manvolnum></citerefentry> for details.
+ '';
+ };
+ };
+ };
+
routeOptions = {
options = {
routeConfig = mkOption {
@@ -752,6 +826,16 @@ let
'';
};
+ routingPolicyRules = mkOption {
+ default = [ ];
+ type = with types; listOf (submodule routingPolicyRulesOptions);
+ description = ''
+ A list of routing policy rules sections to be added to the unit. See
+ <citerefentry><refentrytitle>systemd.network</refentrytitle>
+ <manvolnum>5</manvolnum></citerefentry> for details.
+ '';
+ };
+
routes = mkOption {
default = [ ];
type = with types; listOf (submodule routeOptions);
@@ -845,6 +929,11 @@ let
${attrsToSection def.xfrmConfig}
''}
+ ${optionalString (def.vrfConfig != { }) ''
+ [VRF]
+ ${attrsToSection def.vrfConfig}
+
+ ''}
${optionalString (def.wireguardConfig != { }) ''
[WireGuard]
${attrsToSection def.wireguardConfig}
@@ -904,6 +993,11 @@ let
${attrsToSection x.routeConfig}
'')}
+ ${flip concatMapStrings def.routingPolicyRules (x: ''
+ [RoutingPolicyRule]
+ ${attrsToSection x.routingPolicyRuleConfig}
+
+ '')}
${def.extraConfig}
'';
};
@@ -947,9 +1041,10 @@ in
systemd.network.units = mkOption {
description = "Definition of networkd units.";
default = {};
+ internal = true;
type = with types; attrsOf (submodule (
{ name, config, ... }:
- { options = concreteUnitOptions;
+ { options = mapAttrs (_: x: x // { internal = true; }) concreteUnitOptions;
config = {
unit = mkDefault (makeUnit name config);
};
@@ -958,44 +1053,49 @@ in
};
- config = mkIf config.systemd.network.enable {
+ config = mkMerge [
+ # .link units are honored by udev, no matter if systemd-networkd is enabled or not.
+ {
+ systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.links;
+ environment.etc = unitFiles;
+ }
- users.users.systemd-network.group = "systemd-network";
+ (mkIf config.systemd.network.enable {
- systemd.additionalUpstreamSystemUnits = [
- "systemd-networkd.service" "systemd-networkd-wait-online.service"
- ];
+ users.users.systemd-network.group = "systemd-network";
- systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.links
- // mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.netdevs
- // mapAttrs' (n: v: nameValuePair "${n}.network" (networkToUnit n v)) cfg.networks;
+ systemd.additionalUpstreamSystemUnits = [
+ "systemd-networkd.service" "systemd-networkd-wait-online.service"
+ ];
- environment.etc = unitFiles;
+ systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.netdevs
+ // mapAttrs' (n: v: nameValuePair "${n}.network" (networkToUnit n v)) cfg.networks;
- systemd.services.systemd-networkd = {
- wantedBy = [ "multi-user.target" ];
- restartTriggers = attrNames unitFiles;
- # prevent race condition with interface renaming (#39069)
- requires = [ "systemd-udev-settle.service" ];
- after = [ "systemd-udev-settle.service" ];
- };
+ systemd.services.systemd-networkd = {
+ wantedBy = [ "multi-user.target" ];
+ restartTriggers = attrNames unitFiles;
+ # prevent race condition with interface renaming (#39069)
+ requires = [ "systemd-udev-settle.service" ];
+ after = [ "systemd-udev-settle.service" ];
+ };
- systemd.services.systemd-networkd-wait-online = {
- wantedBy = [ "network-online.target" ];
- };
+ systemd.services.systemd-networkd-wait-online = {
+ wantedBy = [ "network-online.target" ];
+ };
- systemd.services."systemd-network-wait-online@" = {
- description = "Wait for Network Interface %I to be Configured";
- conflicts = [ "shutdown.target" ];
- requisite = [ "systemd-networkd.service" ];
- after = [ "systemd-networkd.service" ];
- serviceConfig = {
- Type = "oneshot";
- RemainAfterExit = true;
- ExecStart = "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online -i %I";
+ systemd.services."systemd-network-wait-online@" = {
+ description = "Wait for Network Interface %I to be Configured";
+ conflicts = [ "shutdown.target" ];
+ requisite = [ "systemd-networkd.service" ];
+ after = [ "systemd-networkd.service" ];
+ serviceConfig = {
+ Type = "oneshot";
+ RemainAfterExit = true;
+ ExecStart = "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online -i %I";
+ };
};
- };
- services.resolved.enable = mkDefault true;
- };
+ services.resolved.enable = mkDefault true;
+ })
+ ];
}
diff --git a/nixpkgs/nixos/modules/system/boot/stage-1-init.sh b/nixpkgs/nixos/modules/system/boot/stage-1-init.sh
index f520bf54ad1..607aec87f01 100644
--- a/nixpkgs/nixos/modules/system/boot/stage-1-init.sh
+++ b/nixpkgs/nixos/modules/system/boot/stage-1-init.sh
@@ -210,6 +210,8 @@ done
# Create device nodes in /dev.
@preDeviceCommands@
echo "running udev..."
+mkdir -p /etc/systemd
+ln -sfn @linkUnits@ /etc/systemd/network
mkdir -p /etc/udev
ln -sfn @udevRules@ /etc/udev/rules.d
mkdir -p /dev/.mdadm
@@ -266,7 +268,7 @@ checkFS() {
return 0
fi
- # Device might be already mounted manually
+ # Device might be already mounted manually
# e.g. NBD-device or the host filesystem of the file which contains encrypted root fs
if mount | grep -q "^$device on "; then
echo "skip checking already mounted $device"
@@ -334,8 +336,10 @@ mountFS() {
# Filter out x- options, which busybox doesn't do yet.
local optionsFiltered="$(IFS=,; for i in $options; do if [ "${i:0:2}" != "x-" ]; then echo -n $i,; fi; done)"
+ # Prefix (lower|upper|work)dir with /mnt-root (overlayfs)
+ local optionsPrefixed="$( echo "$optionsFiltered" | sed -E 's#\<(lowerdir|upperdir|workdir)=#\1=/mnt-root#g' )"
- echo "$device /mnt-root$mountPoint $fsType $optionsFiltered" >> /etc/fstab
+ echo "$device /mnt-root$mountPoint $fsType $optionsPrefixed" >> /etc/fstab
checkFS "$device" "$fsType"
@@ -349,15 +353,16 @@ mountFS() {
elif [ "$fsType" = f2fs ]; then
echo "resizing $device..."
fsck.f2fs -fp "$device"
- resize.f2fs "$device"
+ resize.f2fs "$device"
fi
;;
esac
- # Create backing directories for unionfs-fuse.
- if [ "$fsType" = unionfs-fuse ]; then
- for i in $(IFS=:; echo ${options##*,dirs=}); do
- mkdir -m 0700 -p /mnt-root"${i%=*}"
+ # Create backing directories for overlayfs
+ if [ "$fsType" = overlay ]; then
+ for i in upper work; do
+ dir="$( echo "$optionsPrefixed" | grep -o "${i}dir=[^,]*" )"
+ mkdir -m 0700 -p "${dir##*=}"
done
fi
diff --git a/nixpkgs/nixos/modules/system/boot/stage-1.nix b/nixpkgs/nixos/modules/system/boot/stage-1.nix
index 4c2d130d5a5..93cd801ef80 100644
--- a/nixpkgs/nixos/modules/system/boot/stage-1.nix
+++ b/nixpkgs/nixos/modules/system/boot/stage-1.nix
@@ -120,6 +120,7 @@ let
# Copy udev.
copy_bin_and_libs ${udev}/lib/systemd/systemd-udevd
+ copy_bin_and_libs ${udev}/lib/systemd/systemd-sysctl
copy_bin_and_libs ${udev}/bin/udevadm
for BIN in ${udev}/lib/udev/*_id; do
copy_bin_and_libs $BIN
@@ -198,6 +199,14 @@ let
''; # */
+ linkUnits = pkgs.runCommand "link-units" {
+ allowedReferences = [ extraUtils ];
+ preferLocalBuild = true;
+ } ''
+ mkdir -p $out
+ cp -v ${udev}/lib/systemd/network/*.link $out/
+ '';
+
udevRules = pkgs.runCommand "udev-rules" {
allowedReferences = [ extraUtils ];
preferLocalBuild = true;
@@ -208,7 +217,9 @@ let
cp -v ${udev}/lib/udev/rules.d/60-cdrom_id.rules $out/
cp -v ${udev}/lib/udev/rules.d/60-persistent-storage.rules $out/
+ cp -v ${udev}/lib/udev/rules.d/75-net-description.rules $out/
cp -v ${udev}/lib/udev/rules.d/80-drivers.rules $out/
+ cp -v ${udev}/lib/udev/rules.d/80-net-setup-link.rules $out/
cp -v ${pkgs.lvm2}/lib/udev/rules.d/*.rules $out/
${config.boot.initrd.extraUdevRulesCommands}
@@ -222,7 +233,7 @@ let
--replace ${pkgs.lvm2}/sbin ${extraUtils}/bin \
--replace ${pkgs.mdadm}/sbin ${extraUtils}/sbin \
--replace ${pkgs.bash}/bin/sh ${extraUtils}/bin/sh \
- --replace ${udev}/bin/udevadm ${extraUtils}/bin/udevadm
+ --replace ${udev} ${extraUtils}
done
# Work around a bug in QEMU, which doesn't implement the "READ
@@ -257,7 +268,7 @@ let
${pkgs.buildPackages.busybox}/bin/ash -n $target
'';
- inherit udevRules extraUtils modulesClosure;
+ inherit linkUnits udevRules extraUtils modulesClosure;
inherit (config.boot) resumeDevice;
@@ -379,6 +390,17 @@ in
'';
};
+ boot.initrd.enable = mkOption {
+ type = types.bool;
+ default = !config.boot.isContainer;
+ defaultText = "!config.boot.isContainer";
+ description = ''
+ Whether to enable the NixOS initial RAM disk (initrd). This may be
+ needed to perform some initialisation tasks (like mounting
+ network/encrypted file systems) before continuing the boot process.
+ '';
+ };
+
boot.initrd.prepend = mkOption {
default = [ ];
type = types.listOf types.str;
@@ -544,7 +566,7 @@ in
};
- config = mkIf (!config.boot.isContainer) {
+ config = mkIf config.boot.initrd.enable {
assertions = [
{ assertion = any (fs: fs.mountPoint == "/") fileSystems;
message = "The ‘fileSystems’ option does not specify your root file system.";
diff --git a/nixpkgs/nixos/modules/system/boot/systemd-lib.nix b/nixpkgs/nixos/modules/system/boot/systemd-lib.nix
index fd1a5b9f62c..a3360291586 100644
--- a/nixpkgs/nixos/modules/system/boot/systemd-lib.nix
+++ b/nixpkgs/nixos/modules/system/boot/systemd-lib.nix
@@ -59,6 +59,11 @@ in rec {
optional (attr ? ${name} && ! isMacAddress attr.${name})
"Systemd ${group} field `${name}' must be a valid mac address.";
+ isPort = i: i >= 0 && i <= 65535;
+
+ assertPort = name: group: attr:
+ optional (attr ? ${name} && ! isPort attr.${name})
+ "Error on the systemd ${group} field `${name}': ${attr.name} is not a valid port number.";
assertValueOneOf = name: values: group: attr:
optional (attr ? ${name} && !elem attr.${name} values)
diff --git a/nixpkgs/nixos/modules/system/boot/systemd.nix b/nixpkgs/nixos/modules/system/boot/systemd.nix
index 941df5797c6..cdc9d237939 100644
--- a/nixpkgs/nixos/modules/system/boot/systemd.nix
+++ b/nixpkgs/nixos/modules/system/boot/systemd.nix
@@ -697,6 +697,16 @@ in
'';
};
+ systemd.sleep.extraConfig = mkOption {
+ default = "";
+ type = types.lines;
+ example = "HibernateDelaySec=1h";
+ description = ''
+ Extra config options for systemd sleep state logic.
+ See sleep.conf.d(5) man page for available options.
+ '';
+ };
+
systemd.user.extraConfig = mkOption {
default = "";
type = types.lines;
@@ -776,6 +786,18 @@ in
'';
};
+ systemd.suppressedSystemUnits = mkOption {
+ default = [ ];
+ type = types.listOf types.str;
+ example = [ "systemd-backlight@.service" ];
+ description = ''
+ A list of units to suppress when generating system systemd configuration directory. This has
+ priority over upstream units, <option>systemd.units</option>, and
+ <option>systemd.additionalUpstreamSystemUnits</option>. The main purpose of this is to
+ suppress a upstream systemd unit with any modifications made to it by other NixOS modules.
+ '';
+ };
+
};
@@ -808,8 +830,11 @@ in
done
${concatStrings (mapAttrsToList (exec: target: "ln -s ${target} $out/${exec};\n") links)}
'';
+
+ enabledUpstreamSystemUnits = filter (n: ! elem n cfg.suppressedSystemUnits) upstreamSystemUnits;
+ enabledUnits = filterAttrs (n: v: ! elem n cfg.suppressedSystemUnits) cfg.units;
in ({
- "systemd/system".source = generateUnits "system" cfg.units upstreamSystemUnits upstreamSystemWants;
+ "systemd/system".source = generateUnits "system" enabledUnits enabledUpstreamSystemUnits upstreamSystemWants;
"systemd/user".source = generateUnits "user" cfg.user.units upstreamUserUnits [];
@@ -863,6 +888,7 @@ in
"systemd/sleep.conf".text = ''
[Sleep]
+ ${config.systemd.sleep.extraConfig}
'';
# install provided sysctl snippets
diff --git a/nixpkgs/nixos/modules/system/etc/etc.nix b/nixpkgs/nixos/modules/system/etc/etc.nix
index 57ade288096..1f4d54a1ae2 100644
--- a/nixpkgs/nixos/modules/system/etc/etc.nix
+++ b/nixpkgs/nixos/modules/system/etc/etc.nix
@@ -94,7 +94,7 @@ in
default = 0;
type = types.int;
description = ''
- UID of created file. Only takes affect when the file is
+ UID of created file. Only takes effect when the file is
copied (that is, the mode is not 'symlink').
'';
};
@@ -103,7 +103,7 @@ in
default = 0;
type = types.int;
description = ''
- GID of created file. Only takes affect when the file is
+ GID of created file. Only takes effect when the file is
copied (that is, the mode is not 'symlink').
'';
};
@@ -113,7 +113,7 @@ in
type = types.str;
description = ''
User name of created file.
- Only takes affect when the file is copied (that is, the mode is not 'symlink').
+ Only takes effect when the file is copied (that is, the mode is not 'symlink').
Changing this option takes precedence over <literal>uid</literal>.
'';
};
@@ -123,7 +123,7 @@ in
type = types.str;
description = ''
Group name of created file.
- Only takes affect when the file is copied (that is, the mode is not 'symlink').
+ Only takes effect when the file is copied (that is, the mode is not 'symlink').
Changing this option takes precedence over <literal>gid</literal>.
'';
};
diff --git a/nixpkgs/nixos/modules/tasks/auto-upgrade.nix b/nixpkgs/nixos/modules/tasks/auto-upgrade.nix
index 7fe06699191..bfc1e301efa 100644
--- a/nixpkgs/nixos/modules/tasks/auto-upgrade.nix
+++ b/nixpkgs/nixos/modules/tasks/auto-upgrade.nix
@@ -63,6 +63,19 @@ let cfg = config.system.autoUpgrade; in
'';
};
+ randomizedDelaySec = mkOption {
+ default = "0";
+ type = types.str;
+ example = "45min";
+ description = ''
+ Add a randomized delay before each automatic upgrade.
+ The delay will be chozen between zero and this value.
+ This value must be a time span in the format specified by
+ <citerefentry><refentrytitle>systemd.time</refentrytitle>
+ <manvolnum>7</manvolnum></citerefentry>
+ '';
+ };
+
};
};
@@ -109,6 +122,8 @@ let cfg = config.system.autoUpgrade; in
startAt = cfg.dates;
};
+ systemd.timers.nixos-upgrade.timerConfig.RandomizedDelaySec = cfg.randomizedDelaySec;
+
};
}
diff --git a/nixpkgs/nixos/modules/tasks/encrypted-devices.nix b/nixpkgs/nixos/modules/tasks/encrypted-devices.nix
index 2c9231f5523..bc0933f16fe 100644
--- a/nixpkgs/nixos/modules/tasks/encrypted-devices.nix
+++ b/nixpkgs/nixos/modules/tasks/encrypted-devices.nix
@@ -65,7 +65,7 @@ in
boot.initrd = {
luks = {
devices =
- map (dev: { name = dev.encrypted.label; device = dev.encrypted.blkDev; } ) keylessEncDevs;
+ builtins.listToAttrs (map (dev: { name = dev.encrypted.label; value = { device = dev.encrypted.blkDev; }; }) keylessEncDevs);
forceLuksSupportInInitrd = true;
};
postMountCommands =
diff --git a/nixpkgs/nixos/modules/tasks/filesystems.nix b/nixpkgs/nixos/modules/tasks/filesystems.nix
index 688c77cb22d..0ade74b957a 100644
--- a/nixpkgs/nixos/modules/tasks/filesystems.nix
+++ b/nixpkgs/nixos/modules/tasks/filesystems.nix
@@ -304,6 +304,11 @@ in
in listToAttrs (map formatDevice (filter (fs: fs.autoFormat) fileSystems));
+ systemd.tmpfiles.rules = [
+ "d /run/keys 0750 root ${toString config.ids.gids.keys}"
+ "z /run/keys 0750 root ${toString config.ids.gids.keys}"
+ ];
+
# Sync mount options with systemd's src/core/mount-setup.c: mount_table.
boot.specialFileSystems = {
"/proc" = { fsType = "proc"; options = [ "nosuid" "noexec" "nodev" ]; };
@@ -312,8 +317,8 @@ in
"/dev/shm" = { fsType = "tmpfs"; options = [ "nosuid" "nodev" "strictatime" "mode=1777" "size=${config.boot.devShmSize}" ]; };
"/dev/pts" = { fsType = "devpts"; options = [ "nosuid" "noexec" "mode=620" "ptmxmode=0666" "gid=${toString config.ids.gids.tty}" ]; };
- # To hold secrets that shouldn't be written to disk (generally used for NixOps, harmless elsewhere)
- "/run/keys" = { fsType = "ramfs"; options = [ "nosuid" "nodev" "mode=750" "gid=${toString config.ids.gids.keys}" ]; };
+ # To hold secrets that shouldn't be written to disk
+ "/run/keys" = { fsType = "ramfs"; options = [ "nosuid" "nodev" "mode=750" ]; };
} // optionalAttrs (!config.boot.isContainer) {
# systemd-nspawn populates /sys by itself, and remounting it causes all
# kinds of weird issues (most noticeably, waiting for host disk device
diff --git a/nixpkgs/nixos/modules/tasks/filesystems/btrfs.nix b/nixpkgs/nixos/modules/tasks/filesystems/btrfs.nix
index 48be18c7102..f64493e1a3c 100644
--- a/nixpkgs/nixos/modules/tasks/filesystems/btrfs.nix
+++ b/nixpkgs/nixos/modules/tasks/filesystems/btrfs.nix
@@ -118,12 +118,17 @@ in
fs' = utils.escapeSystemdPath fs;
in nameValuePair "btrfs-scrub-${fs'}" {
description = "btrfs scrub on ${fs}";
+ # scrub prevents suspend2ram or proper shutdown
+ conflicts = [ "shutdown.target" "sleep.target" ];
+ before = [ "shutdown.target" "sleep.target" ];
serviceConfig = {
- Type = "oneshot";
+ # simple and not oneshot, otherwise ExecStop is not used
+ Type = "simple";
Nice = 19;
IOSchedulingClass = "idle";
ExecStart = "${pkgs.btrfs-progs}/bin/btrfs scrub start -B ${fs}";
+ ExecStop = "${pkgs.btrfs-progs}/bin/btrfs scrub cancel ${fs}";
};
};
in listToAttrs (map scrubService cfgScrub.fileSystems);
diff --git a/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix b/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix
index d14ba98ec48..09c7e074e12 100644
--- a/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix
+++ b/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix
@@ -623,7 +623,11 @@ in
after = [ "zfs-import.target" ];
path = [ packages.zfsUser ];
startAt = cfgTrim.interval;
- serviceConfig.ExecStart = "${pkgs.runtimeShell} -c 'zpool list -H -o name | xargs --no-run-if-empty -n1 zpool trim'";
+ # By default we ignore errors returned by the trim command, in case:
+ # - HDDs are mixed with SSDs
+ # - There is a SSDs in a pool that is currently trimmed.
+ # - There are only HDDs and we would set the system in a degraded state
+ serviceConfig.ExecStart = ''${pkgs.runtimeShell} -c 'for pool in $(zpool list -H -o name); do zpool trim $pool; done || true' '';
};
})
];
diff --git a/nixpkgs/nixos/modules/tasks/network-interfaces-scripted.nix b/nixpkgs/nixos/modules/tasks/network-interfaces-scripted.nix
index 1726d05115e..4d25137c5df 100644
--- a/nixpkgs/nixos/modules/tasks/network-interfaces-scripted.nix
+++ b/nixpkgs/nixos/modules/tasks/network-interfaces-scripted.nix
@@ -10,7 +10,7 @@ let
slaves = concatMap (i: i.interfaces) (attrValues cfg.bonds)
++ concatMap (i: i.interfaces) (attrValues cfg.bridges)
- ++ concatMap (i: i.interfaces) (attrValues cfg.vswitches)
+ ++ concatMap (i: attrNames (filterAttrs (_: config: config.type != "internal") i.interfaces)) (attrValues cfg.vswitches)
++ concatMap (i: [i.interface]) (attrValues cfg.macvlans)
++ concatMap (i: [i.interface]) (attrValues cfg.vlans);
@@ -336,34 +336,47 @@ let
createVswitchDevice = n: v: nameValuePair "${n}-netdev"
(let
- deps = concatLists (map deviceDependency v.interfaces);
+ deps = concatLists (map deviceDependency (attrNames (filterAttrs (_: config: config.type != "internal") v.interfaces)));
+ internalConfigs = concatMap (i: ["network-link-${i}.service" "network-addresses-${i}.service"]) (attrNames (filterAttrs (_: config: config.type == "internal") v.interfaces));
ofRules = pkgs.writeText "vswitch-${n}-openFlowRules" v.openFlowRules;
in
{ description = "Open vSwitch Interface ${n}";
- wantedBy = [ "network-setup.service" "vswitchd.service" ] ++ deps;
- bindsTo = [ "vswitchd.service" (subsystemDevice n) ] ++ deps;
- partOf = [ "network-setup.service" "vswitchd.service" ];
- after = [ "network-pre.target" "vswitchd.service" ] ++ deps;
- before = [ "network-setup.service" ];
+ wantedBy = [ "network-setup.service" (subsystemDevice n) ] ++ internalConfigs;
+ # before = [ "network-setup.service" ];
+ # should work without internalConfigs dependencies because address/link configuration depends
+ # on the device, which is created by ovs-vswitchd with type=internal, but it does not...
+ before = [ "network-setup.service" ] ++ internalConfigs;
+ partOf = [ "network-setup.service" ]; # shutdown the bridge when network is shutdown
+ bindsTo = [ "ovs-vswitchd.service" ]; # requires ovs-vswitchd to be alive at all times
+ after = [ "network-pre.target" "ovs-vswitchd.service" ] ++ deps; # start switch after physical interfaces and vswitch daemon
+ wants = deps; # if one or more interface fails, the switch should continue to run
serviceConfig.Type = "oneshot";
serviceConfig.RemainAfterExit = true;
path = [ pkgs.iproute config.virtualisation.vswitch.package ];
+ preStart = ''
+ echo "Resetting Open vSwitch ${n}..."
+ ovs-vsctl --if-exists del-br ${n} -- add-br ${n} \
+ -- set bridge ${n} protocols=${concatStringsSep "," v.supportedOpenFlowVersions}
+ '';
script = ''
- echo "Removing old Open vSwitch ${n}..."
- ovs-vsctl --if-exists del-br ${n}
-
- echo "Adding Open vSwitch ${n}..."
- ovs-vsctl -- add-br ${n} ${concatMapStrings (i: " -- add-port ${n} ${i}") v.interfaces} \
+ echo "Configuring Open vSwitch ${n}..."
+ ovs-vsctl ${concatStrings (mapAttrsToList (name: config: " -- add-port ${n} ${name}" + optionalString (config.vlan != null) " tag=${toString config.vlan}") v.interfaces)} \
+ ${concatStrings (mapAttrsToList (name: config: optionalString (config.type != null) " -- set interface ${name} type=${config.type}") v.interfaces)} \
${concatMapStrings (x: " -- set-controller ${n} " + x) v.controllers} \
${concatMapStrings (x: " -- " + x) (splitString "\n" v.extraOvsctlCmds)}
+
echo "Adding OpenFlow rules for Open vSwitch ${n}..."
- ovs-ofctl add-flows ${n} ${ofRules}
+ ovs-ofctl --protocols=${v.openFlowVersion} add-flows ${n} ${ofRules}
'';
postStop = ''
+ echo "Cleaning Open vSwitch ${n}"
+ echo "Shuting down internal ${n} interface"
ip link set ${n} down || true
- ovs-ofctl del-flows ${n} || true
- ovs-vsctl --if-exists del-br ${n}
+ echo "Deleting flows for ${n}"
+ ovs-ofctl --protocols=${v.openFlowVersion} del-flows ${n} || true
+ echo "Deleting Open vSwitch ${n}"
+ ovs-vsctl --if-exists del-br ${n} || true
'';
});
@@ -476,9 +489,9 @@ let
# Remove Dead Interfaces
ip link show "${n}" >/dev/null 2>&1 && ip link delete "${n}"
ip link add link "${v.interface}" name "${n}" type vlan id "${toString v.id}"
-
- # We try to bring up the logical VLAN interface. If the master
- # interface the logical interface is dependent upon is not up yet we will
+
+ # We try to bring up the logical VLAN interface. If the master
+ # interface the logical interface is dependent upon is not up yet we will
# fail to immediately bring up the logical interface. The resulting logical
# interface will brought up later when the master interface is up.
ip link set "${n}" up || true
diff --git a/nixpkgs/nixos/modules/tasks/network-interfaces-systemd.nix b/nixpkgs/nixos/modules/tasks/network-interfaces-systemd.nix
index e25dc0c0b39..41deceb000e 100644
--- a/nixpkgs/nixos/modules/tasks/network-interfaces-systemd.nix
+++ b/nixpkgs/nixos/modules/tasks/network-interfaces-systemd.nix
@@ -1,4 +1,4 @@
-{ config, lib, utils, ... }:
+{ config, lib, utils, pkgs, ... }:
with utils;
with lib;
@@ -18,7 +18,10 @@ let
concatLists (map (bond: bond.interfaces) (attrValues cfg.bonds))
++ concatLists (map (bridge: bridge.interfaces) (attrValues cfg.bridges))
++ map (sit: sit.dev) (attrValues cfg.sits)
- ++ map (vlan: vlan.interface) (attrValues cfg.vlans);
+ ++ map (vlan: vlan.interface) (attrValues cfg.vlans)
+ # add dependency to physical or independently created vswitch member interface
+ # TODO: warn the user that any address configured on those interfaces will be useless
+ ++ concatMap (i: attrNames (filterAttrs (_: config: config.type != "internal") i.interfaces)) (attrValues cfg.vswitches);
in
@@ -51,11 +54,6 @@ in
networking.dhcpcd.enable = mkDefault false;
- systemd.services.network-local-commands = {
- after = [ "systemd-networkd.service" ];
- bindsTo = [ "systemd-networkd.service" ];
- };
-
systemd.network =
let
domains = cfg.search ++ (optional (cfg.domain != null) cfg.domain);
@@ -233,6 +231,63 @@ in
# This forces the network interface creator to initialize slaves.
networking.interfaces = listToAttrs (map (i: nameValuePair i { }) slaves);
+ systemd.services = let
+ # We must escape interfaces due to the systemd interpretation
+ subsystemDevice = interface:
+ "sys-subsystem-net-devices-${escapeSystemdPath interface}.device";
+ # support for creating openvswitch switches
+ createVswitchDevice = n: v: nameValuePair "${n}-netdev"
+ (let
+ deps = map subsystemDevice (attrNames (filterAttrs (_: config: config.type != "internal") v.interfaces));
+ ofRules = pkgs.writeText "vswitch-${n}-openFlowRules" v.openFlowRules;
+ in
+ { description = "Open vSwitch Interface ${n}";
+ wantedBy = [ "network.target" (subsystemDevice n) ];
+ # and create bridge before systemd-networkd starts because it might create internal interfaces
+ before = [ "systemd-networkd.service" ];
+ # shutdown the bridge when network is shutdown
+ partOf = [ "network.target" ];
+ # requires ovs-vswitchd to be alive at all times
+ bindsTo = [ "ovs-vswitchd.service" ];
+ # start switch after physical interfaces and vswitch daemon
+ after = [ "network-pre.target" "ovs-vswitchd.service" ] ++ deps;
+ wants = deps; # if one or more interface fails, the switch should continue to run
+ serviceConfig.Type = "oneshot";
+ serviceConfig.RemainAfterExit = true;
+ path = [ pkgs.iproute config.virtualisation.vswitch.package ];
+ preStart = ''
+ echo "Resetting Open vSwitch ${n}..."
+ ovs-vsctl --if-exists del-br ${n} -- add-br ${n} \
+ -- set bridge ${n} protocols=${concatStringsSep "," v.supportedOpenFlowVersions}
+ '';
+ script = ''
+ echo "Configuring Open vSwitch ${n}..."
+ ovs-vsctl ${concatStrings (mapAttrsToList (name: config: " -- add-port ${n} ${name}" + optionalString (config.vlan != null) " tag=${toString config.vlan}") v.interfaces)} \
+ ${concatStrings (mapAttrsToList (name: config: optionalString (config.type != null) " -- set interface ${name} type=${config.type}") v.interfaces)} \
+ ${concatMapStrings (x: " -- set-controller ${n} " + x) v.controllers} \
+ ${concatMapStrings (x: " -- " + x) (splitString "\n" v.extraOvsctlCmds)}
+
+
+ echo "Adding OpenFlow rules for Open vSwitch ${n}..."
+ ovs-ofctl --protocols=${v.openFlowVersion} add-flows ${n} ${ofRules}
+ '';
+ postStop = ''
+ echo "Cleaning Open vSwitch ${n}"
+ echo "Shuting down internal ${n} interface"
+ ip link set ${n} down || true
+ echo "Deleting flows for ${n}"
+ ovs-ofctl --protocols=${v.openFlowVersion} del-flows ${n} || true
+ echo "Deleting Open vSwitch ${n}"
+ ovs-vsctl --if-exists del-br ${n} || true
+ '';
+ });
+ in mapAttrs' createVswitchDevice cfg.vswitches
+ // {
+ "network-local-commands" = {
+ after = [ "systemd-networkd.service" ];
+ bindsTo = [ "systemd-networkd.service" ];
+ };
+ };
};
}
diff --git a/nixpkgs/nixos/modules/tasks/network-interfaces.nix b/nixpkgs/nixos/modules/tasks/network-interfaces.nix
index 31e2ed1cd1e..9542a60beee 100644
--- a/nixpkgs/nixos/modules/tasks/network-interfaces.nix
+++ b/nixpkgs/nixos/modules/tasks/network-interfaces.nix
@@ -13,7 +13,7 @@ let
slaves = concatMap (i: i.interfaces) (attrValues cfg.bonds)
++ concatMap (i: i.interfaces) (attrValues cfg.bridges)
- ++ concatMap (i: i.interfaces) (attrValues cfg.vswitches);
+ ++ concatMap (i: attrNames (filterAttrs (name: config: ! (config.type == "internal" || hasAttr name cfg.interfaces)) i.interfaces)) (attrValues cfg.vswitches);
slaveIfs = map (i: cfg.interfaces.${i}) (filter (i: cfg.interfaces ? ${i}) slaves);
@@ -143,13 +143,34 @@ let
description = "Name of the interface.";
};
- preferTempAddress = mkOption {
- type = types.bool;
- default = cfg.enableIPv6;
- defaultText = literalExample "config.networking.enableIPv6";
+ tempAddress = mkOption {
+ type = types.enum [ "default" "enabled" "disabled" ];
+ default = if cfg.enableIPv6 then "default" else "disabled";
+ defaultText = literalExample ''if cfg.enableIPv6 then "default" else "disabled"'';
description = ''
- When using SLAAC prefer a temporary (IPv6) address over the EUI-64
- address for originating connections. This is used to reduce tracking.
+ When IPv6 is enabled with SLAAC, this option controls the use of
+ temporary address (aka privacy extensions). This is used to reduce tracking.
+ The three possible values are:
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>"default"</literal> to generate temporary addresses and use
+ them by default;
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>"enabled"</literal> to generate temporary addresses but keep
+ using the standard EUI-64 ones by default;
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>"disabled"</literal> to completely disable temporary addresses.
+ </para>
+ </listitem>
+ </itemizedlist>
'';
};
@@ -287,6 +308,11 @@ let
let
defined = x: x != "_mkMergedOptionModule";
in [
+ (mkChangedOptionModule [ "preferTempAddress" ] [ "tempAddress" ]
+ (config:
+ let bool = getAttrFromPath [ "preferTempAddress" ] config;
+ in if bool then "default" else "enabled"
+ ))
(mkRenamedOptionModule [ "ip4" ] [ "ipv4" "addresses"])
(mkRenamedOptionModule [ "ip6" ] [ "ipv6" "addresses"])
(mkRemovedOptionModule [ "subnetMask" ] ''
@@ -310,6 +336,32 @@ let
};
+ vswitchInterfaceOpts = {name, ...}: {
+
+ options = {
+
+ name = mkOption {
+ description = "Name of the interface";
+ example = "eth0";
+ type = types.str;
+ };
+
+ vlan = mkOption {
+ description = "Vlan tag to apply to interface";
+ example = 10;
+ type = types.nullOr types.int;
+ default = null;
+ };
+
+ type = mkOption {
+ description = "Openvswitch type to assign to interface";
+ example = "internal";
+ type = types.nullOr types.str;
+ default = null;
+ };
+ };
+ };
+
hexChars = stringToCharacters "0123456789abcdef";
isHexString = s: all (c: elem c hexChars) (stringToCharacters (toLower s));
@@ -460,8 +512,8 @@ in
networking.vswitches = mkOption {
default = { };
example =
- { vs0.interfaces = [ "eth0" "eth1" ];
- vs1.interfaces = [ "eth2" "wlan0" ];
+ { vs0.interfaces = { eth0 = { }; lo1 = { type="internal"; }; };
+ vs1.interfaces = [ { name = "eth2"; } { name = "lo2"; type="internal"; } ];
};
description =
''
@@ -478,9 +530,8 @@ in
interfaces = mkOption {
example = [ "eth0" "eth1" ];
- type = types.listOf types.str;
- description =
- "The physical network interfaces connected by the vSwitch.";
+ description = "The physical network interfaces connected by the vSwitch.";
+ type = with types; loaOf (submodule vswitchInterfaceOpts);
};
controllers = mkOption {
@@ -504,6 +555,25 @@ in
'';
};
+ # TODO: custom "openflow version" type, with list from existing openflow protocols
+ supportedOpenFlowVersions = mkOption {
+ type = types.listOf types.str;
+ example = [ "OpenFlow10" "OpenFlow13" "OpenFlow14" ];
+ default = [ "OpenFlow13" ];
+ description = ''
+ Supported versions to enable on this switch.
+ '';
+ };
+
+ # TODO: use same type as elements from supportedOpenFlowVersions
+ openFlowVersion = mkOption {
+ type = types.str;
+ default = "OpenFlow13";
+ description = ''
+ Version of OpenFlow protocol to use when communicating with the switch internally (e.g. with <literal>openFlowRules</literal>).
+ '';
+ };
+
extraOvsctlCmds = mkOption {
type = types.lines;
default = "";
@@ -945,7 +1015,7 @@ in
The networking.interfaces."${i.name}" must not have any defined ips when it is a slave.
'';
})) ++ (forEach interfaces (i: {
- assertion = i.preferTempAddress -> cfg.enableIPv6;
+ assertion = i.tempAddress != "disabled" -> cfg.enableIPv6;
message = ''
Temporary addresses are only needed when IPv6 is enabled.
'';
@@ -973,8 +1043,11 @@ in
"net.ipv6.conf.all.forwarding" = mkDefault (any (i: i.proxyARP) interfaces);
} // listToAttrs (flip concatMap (filter (i: i.proxyARP) interfaces)
(i: forEach [ "4" "6" ] (v: nameValuePair "net.ipv${v}.conf.${replaceChars ["."] ["/"] i.name}.proxy_arp" true)))
- // listToAttrs (forEach (filter (i: i.preferTempAddress) interfaces)
- (i: nameValuePair "net.ipv6.conf.${replaceChars ["."] ["/"] i.name}.use_tempaddr" 2));
+ // listToAttrs (forEach interfaces
+ (i: let
+ opt = i.tempAddress;
+ val = { disabled = 0; enabled = 1; default = 2; }.${opt};
+ in nameValuePair "net.ipv6.conf.${replaceChars ["."] ["/"] i.name}.use_tempaddr" val));
# Capabilities won't work unless we have at-least a 4.3 Linux
# kernel because we need the ambient capability
@@ -1103,10 +1176,18 @@ in
(pkgs.writeTextFile rec {
name = "ipv6-privacy-extensions.rules";
destination = "/etc/udev/rules.d/99-${name}";
- text = concatMapStrings (i: ''
- # enable IPv6 privacy addresses but prefer EUI-64 addresses for ${i.name}
- ACTION=="add", SUBSYSTEM=="net", RUN+="${pkgs.procps}/bin/sysctl net.ipv6.conf.${replaceChars ["."] ["/"] i.name}.use_tempaddr=1"
- '') (filter (i: !i.preferTempAddress) interfaces);
+ text = concatMapStrings (i:
+ let
+ opt = i.tempAddress;
+ val = if opt == "disabled" then 0 else 1;
+ msg = if opt == "disabled"
+ then "completely disable IPv6 privacy addresses"
+ else "enable IPv6 privacy addresses but prefer EUI-64 addresses";
+ in
+ ''
+ # override to ${msg} for ${i.name}
+ ACTION=="add", SUBSYSTEM=="net", RUN+="${pkgs.procps}/bin/sysctl net.ipv6.conf.${replaceChars ["."] ["/"] i.name}.use_tempaddr=${toString val}"
+ '') (filter (i: i.tempAddress != "default") interfaces);
})
] ++ lib.optional (cfg.wlanInterfaces != {})
(pkgs.writeTextFile {
diff --git a/nixpkgs/nixos/modules/testing/service-runner.nix b/nixpkgs/nixos/modules/testing/service-runner.nix
index 17d5e337690..99a9f979068 100644
--- a/nixpkgs/nixos/modules/testing/service-runner.nix
+++ b/nixpkgs/nixos/modules/testing/service-runner.nix
@@ -12,7 +12,10 @@ let
sub run {
my ($cmd) = @_;
- my @args = split " ", $cmd;
+ my @args = ();
+ while ($cmd =~ /([^ \t\n']+)|(\'([^'])\')\s*/g) {
+ push @args, $1;
+ }
my $prog;
if (substr($args[0], 0, 1) eq "@") {
$prog = substr($args[0], 1);
@@ -48,15 +51,20 @@ let
'') service.environment)}
# Run the ExecStartPre program. FIXME: this could be a list.
- my $preStart = '${service.serviceConfig.ExecStartPre or ""}';
- if ($preStart ne "") {
+ my $preStart = <<END_CMD;
+ ${service.serviceConfig.ExecStartPre or ""}
+ END_CMD
+ if (defined $preStart && $preStart ne "\n") {
print STDERR "running ExecStartPre: $preStart\n";
my $res = run_wait $preStart;
die "$0: ExecStartPre failed with status $res\n" if $res;
};
# Run the ExecStart program.
- my $cmd = '${service.serviceConfig.ExecStart}';
+ my $cmd = <<END_CMD;
+ ${service.serviceConfig.ExecStart}
+ END_CMD
+
print STDERR "running ExecStart: $cmd\n";
my $mainPid = run $cmd;
$ENV{'MAINPID'} = $mainPid;
@@ -70,8 +78,10 @@ let
$SIG{'QUIT'} = \&intHandler;
# Run the ExecStartPost program.
- my $postStart = '${service.serviceConfig.ExecStartPost or ""}';
- if ($postStart ne "") {
+ my $postStart = <<END_CMD;
+ ${service.serviceConfig.ExecStartPost or ""}
+ END_CMD
+ if (defined $postStart && $postStart ne "\n") {
print STDERR "running ExecStartPost: $postStart\n";
my $res = run_wait $postStart;
die "$0: ExecStartPost failed with status $res\n" if $res;
@@ -82,8 +92,10 @@ let
my $mainRes = $?;
# Run the ExecStopPost program.
- my $postStop = '${service.serviceConfig.ExecStopPost or ""}';
- if ($postStop ne "") {
+ my $postStop = <<END_CMD;
+ ${service.serviceConfig.ExecStopPost or ""}
+ END_CMD
+ if (defined $postStop && $postStop ne "\n") {
print STDERR "running ExecStopPost: $postStop\n";
my $res = run_wait $postStop;
die "$0: ExecStopPost failed with status $res\n" if $res;
diff --git a/nixpkgs/nixos/modules/virtualisation/docker-containers.nix b/nixpkgs/nixos/modules/virtualisation/docker-containers.nix
index 3a2eb97d1bf..5ab990a3d7c 100644
--- a/nixpkgs/nixos/modules/virtualisation/docker-containers.nix
+++ b/nixpkgs/nixos/modules/virtualisation/docker-containers.nix
@@ -39,7 +39,7 @@ let
entrypoint = mkOption {
type = with types; nullOr str;
- description = "Overwrite the default entrypoint of the image.";
+ description = "Override the default entrypoint of the image.";
default = null;
example = "/bin/my-app";
};
@@ -145,7 +145,7 @@ let
Note that this is a list of <literal>"src:dst"</literal> strings to
allow for <literal>src</literal> to refer to
- <literal>/nix/store</literal> paths, which would difficult with an
+ <literal>/nix/store</literal> paths, which would be difficult with an
attribute set. There are also a variety of mount options available
as a third field; please refer to the
<link xlink:href="https://docs.docker.com/engine/reference/run/#volume-shared-filesystems">
@@ -192,16 +192,34 @@ let
["--network=host"]
'';
};
+
+ autoStart = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ When enabled, the container is automatically started on boot.
+ If this option is set to false, the container has to be started on-demand via its service.
+ '';
+ };
};
};
mkService = name: container: let
mkAfter = map (x: "docker-${x}.service") container.dependsOn;
in rec {
- wantedBy = [ "multi-user.target" ];
+ wantedBy = [] ++ optional (container.autoStart) "multi-user.target";
after = [ "docker.service" "docker.socket" ] ++ mkAfter;
requires = after;
-
+ path = [ pkgs.docker ];
+
+ preStart = ''
+ docker rm -f ${name} || true
+ ${optionalString (container.imageFile != null) ''
+ docker load -i ${container.imageFile}
+ ''}
+ '';
+ postStop = "docker rm -f ${name} || true";
+
serviceConfig = {
ExecStart = concatStringsSep " \\\n " ([
"${pkgs.docker}/bin/docker run"
@@ -220,13 +238,7 @@ let
++ map escapeShellArg container.cmd
);
- ExecStartPre = ["-${pkgs.docker}/bin/docker rm -f ${name}"
- "-${pkgs.docker}/bin/docker image prune -f"] ++
- (optional (container.imageFile != null)
- ["${pkgs.docker}/bin/docker load -i ${container.imageFile}"]);
-
- ExecStop = ''${pkgs.bash}/bin/sh -c "[ $SERVICE_RESULT = success ] || ${pkgs.docker}/bin/docker stop ${name}"'';
- ExecStopPost = "-${pkgs.docker}/bin/docker rm -f ${name}";
+ ExecStop = ''${pkgs.bash}/bin/sh -c "[ $SERVICE_RESULT = success ] || docker stop ${name}"'';
### There is no generalized way of supporting `reload` for docker
### containers. Some containers may respond well to SIGHUP sent to their
diff --git a/nixpkgs/nixos/modules/virtualisation/hyperv-guest.nix b/nixpkgs/nixos/modules/virtualisation/hyperv-guest.nix
index 0f1f052880c..adc2810a993 100644
--- a/nixpkgs/nixos/modules/virtualisation/hyperv-guest.nix
+++ b/nixpkgs/nixos/modules/virtualisation/hyperv-guest.nix
@@ -32,7 +32,7 @@ in {
];
kernelParams = [
- "video=hyperv_fb:${cfg.videoMode}"
+ "video=hyperv_fb:${cfg.videoMode} elevator=noop"
];
};
diff --git a/nixpkgs/nixos/modules/virtualisation/kvmgt.nix b/nixpkgs/nixos/modules/virtualisation/kvmgt.nix
index 36ef6d17df6..0902d2dc2cb 100644
--- a/nixpkgs/nixos/modules/virtualisation/kvmgt.nix
+++ b/nixpkgs/nixos/modules/virtualisation/kvmgt.nix
@@ -19,7 +19,8 @@ in {
virtualisation.kvmgt = {
enable = mkEnableOption ''
KVMGT (iGVT-g) VGPU support. Allows Qemu/KVM guests to share host's Intel integrated graphics card.
- Currently only one graphical device can be shared
+ Currently only one graphical device can be shared. To allow users to access the device without root add them
+ to the kvm group: <literal>users.extraUsers.&lt;yourusername&gt;.extraGroups = [ "kvm" ];</literal>
'';
# multi GPU support is under the question
device = mkOption {
@@ -35,9 +36,7 @@ in {
and find info about device via <command>cat /sys/bus/pci/devices/*/mdev_supported_types/i915-GVTg_V5_4/description</command>
'';
example = {
- i915-GVTg_V5_8 = {
- uuid = "a297db4a-f4c2-11e6-90f6-d3b88d6c9525";
- };
+ i915-GVTg_V5_8.uuid = "a297db4a-f4c2-11e6-90f6-d3b88d6c9525";
};
};
};
@@ -50,10 +49,7 @@ in {
};
boot.kernelModules = [ "kvmgt" ];
-
- boot.extraModprobeConfig = ''
- options i915 enable_gvt=1
- '';
+ boot.kernelParams = [ "i915.enable_gvt=1" ];
systemd.paths = mapAttrs' (name: value:
nameValuePair "kvmgt-${name}" {
@@ -65,6 +61,10 @@ in {
}
) cfg.vgpus;
+ services.udev.extraRules = ''
+ SUBSYSTEM=="vfio", OWNER="root", GROUP="kvm"
+ '';
+
systemd.services = mapAttrs' (name: value:
nameValuePair "kvmgt-${name}" {
description = "KVMGT VGPU ${name}";
diff --git a/nixpkgs/nixos/modules/virtualisation/libvirtd.nix b/nixpkgs/nixos/modules/virtualisation/libvirtd.nix
index 52d852894ce..9f7bac480e3 100644
--- a/nixpkgs/nixos/modules/virtualisation/libvirtd.nix
+++ b/nixpkgs/nixos/modules/virtualisation/libvirtd.nix
@@ -219,7 +219,7 @@ in {
wantedBy = [ "multi-user.target" ];
requires = [ "libvirtd-config.service" ];
after = [ "systemd-udev-settle.service" "libvirtd-config.service" ]
- ++ optional vswitch.enable "vswitchd.service";
+ ++ optional vswitch.enable "ovs-vswitchd.service";
environment.LIBVIRTD_ARGS = ''--config "${configFile}" ${concatStringsSep " " cfg.extraOptions}'';
diff --git a/nixpkgs/nixos/modules/virtualisation/openvswitch.nix b/nixpkgs/nixos/modules/virtualisation/openvswitch.nix
index 6b8ad83661f..c6a3ceddc3e 100644
--- a/nixpkgs/nixos/modules/virtualisation/openvswitch.nix
+++ b/nixpkgs/nixos/modules/virtualisation/openvswitch.nix
@@ -124,7 +124,7 @@ in {
'';
};
- systemd.services.vswitchd = {
+ systemd.services.ovs-vswitchd = {
description = "Open_vSwitch Daemon";
wantedBy = [ "multi-user.target" ];
bindsTo = [ "ovsdb.service" ];
@@ -139,6 +139,8 @@ in {
PIDFile = "/run/openvswitch/ovs-vswitchd.pid";
# Use service type 'forking' to correctly determine when vswitchd is ready.
Type = "forking";
+ Restart = "always";
+ RestartSec = 3;
};
};
@@ -182,4 +184,7 @@ in {
'';
};
})]));
+
+ meta.maintainers = with maintainers; [ netixx ];
+
}
diff --git a/nixpkgs/nixos/modules/virtualisation/virtualbox-image.nix b/nixpkgs/nixos/modules/virtualisation/virtualbox-image.nix
index ab65523592d..788b4d9d976 100644
--- a/nixpkgs/nixos/modules/virtualisation/virtualbox-image.nix
+++ b/nixpkgs/nixos/modules/virtualisation/virtualbox-image.nix
@@ -45,10 +45,41 @@ in {
The file name of the VirtualBox appliance.
'';
};
+ params = mkOption {
+ type = with types; attrsOf (oneOf [ str int bool (listOf str) ]);
+ example = {
+ audio = "alsa";
+ rtcuseutc = "on";
+ usb = "off";
+ };
+ description = ''
+ Parameters passed to the Virtualbox appliance.
+
+ Run <literal>VBoxManage modifyvm --help</literal> to see more options.
+ '';
+ };
};
};
config = {
+
+ virtualbox.params = mkMerge [
+ (mapAttrs (name: mkDefault) {
+ acpi = "on";
+ vram = 32;
+ nictype1 = "virtio";
+ nic1 = "nat";
+ audiocontroller = "ac97";
+ audio = "alsa";
+ audioout = "on";
+ rtcuseutc = "on";
+ usb = "on";
+ usbehci = "on";
+ mouse = "usbtablet";
+ })
+ (mkIf (pkgs.stdenv.hostPlatform.system == "i686-linux") { pae = "on"; })
+ ];
+
system.build.virtualBoxOVA = import ../../lib/make-disk-image.nix {
name = cfg.vmDerivationName;
@@ -69,12 +100,8 @@ in {
VBoxManage createvm --name "$vmName" --register \
--ostype ${if pkgs.stdenv.hostPlatform.system == "x86_64-linux" then "Linux26_64" else "Linux26"}
VBoxManage modifyvm "$vmName" \
- --memory ${toString cfg.memorySize} --acpi on --vram 32 \
- ${optionalString (pkgs.stdenv.hostPlatform.system == "i686-linux") "--pae on"} \
- --nictype1 virtio --nic1 nat \
- --audiocontroller ac97 --audio alsa --audioout on \
- --rtcuseutc on \
- --usb on --usbehci on --mouse usbtablet
+ --memory ${toString cfg.memorySize} \
+ ${lib.cli.toGNUCommandLineShell { } cfg.params}
VBoxManage storagectl "$vmName" --name SATA --add sata --portcount 4 --bootable on --hostiocache on
VBoxManage storageattach "$vmName" --storagectl SATA --port 0 --device 0 --type hdd \
--medium disk.vmdk