aboutsummaryrefslogtreecommitdiff
path: root/nixpkgs/nixos/modules
diff options
context:
space:
mode:
authorKatharina Fey <kookie@spacekookie.de>2020-08-07 12:29:39 +0200
committerKatharina Fey <kookie@spacekookie.de>2020-08-07 12:29:39 +0200
commit5581b5521e14317c3507a6e8451a3f14996e5c4d (patch)
tree7aadee5a9ef5d6e2acc8929818c6eb2d2099e2ae /nixpkgs/nixos/modules
parentde94c6c62e2f86b3667386a42690d6bb376a2f58 (diff)
parent8e2b14aceb1d40c7e8b84c03a7c78955359872bb (diff)
Merge commit '8e2b14aceb1d40c7e8b84c03a7c78955359872bb'
Diffstat (limited to 'nixpkgs/nixos/modules')
-rw-r--r--nixpkgs/nixos/modules/config/fonts/fontconfig.nix25
-rw-r--r--nixpkgs/nixos/modules/config/i18n.nix3
-rw-r--r--nixpkgs/nixos/modules/config/system-path.nix1
-rw-r--r--nixpkgs/nixos/modules/config/update-users-groups.pl55
-rw-r--r--nixpkgs/nixos/modules/config/users-groups.nix113
-rw-r--r--nixpkgs/nixos/modules/hardware/device-tree.nix13
-rw-r--r--nixpkgs/nixos/modules/hardware/logitech.nix94
-rw-r--r--nixpkgs/nixos/modules/hardware/printers.nix2
-rw-r--r--nixpkgs/nixos/modules/hardware/video/hidpi.nix16
-rw-r--r--nixpkgs/nixos/modules/hardware/video/uvcvideo/default.nix2
-rw-r--r--nixpkgs/nixos/modules/hardware/xpadneo.nix29
-rw-r--r--nixpkgs/nixos/modules/i18n/input-method/ibus.nix2
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix20
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-plasma5.nix4
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix2
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix8
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix8
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix8
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/sd-image-raspberrypi4.nix7
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/sd-image.nix24
-rw-r--r--nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix8
-rw-r--r--nixpkgs/nixos/modules/installer/tools/nixos-generate-config.pl5
-rw-r--r--nixpkgs/nixos/modules/installer/tools/nixos-install.sh11
-rw-r--r--nixpkgs/nixos/modules/misc/documentation.nix38
-rw-r--r--nixpkgs/nixos/modules/misc/ids.nix4
-rw-r--r--nixpkgs/nixos/modules/module-list.nix20
-rw-r--r--nixpkgs/nixos/modules/profiles/demo.nix10
-rw-r--r--nixpkgs/nixos/modules/programs/dconf.nix37
-rw-r--r--nixpkgs/nixos/modules/programs/fish.nix3
-rw-r--r--nixpkgs/nixos/modules/programs/gnupg.nix3
-rw-r--r--nixpkgs/nixos/modules/programs/hamster.nix15
-rw-r--r--nixpkgs/nixos/modules/programs/ssh.nix30
-rw-r--r--nixpkgs/nixos/modules/programs/ssmtp.nix77
-rw-r--r--nixpkgs/nixos/modules/programs/steam.nix25
-rw-r--r--nixpkgs/nixos/modules/rename.nix8
-rw-r--r--nixpkgs/nixos/modules/security/acme.nix39
-rw-r--r--nixpkgs/nixos/modules/security/pam.nix51
-rw-r--r--nixpkgs/nixos/modules/security/sudo.nix4
-rw-r--r--nixpkgs/nixos/modules/services/audio/mpd.nix14
-rw-r--r--nixpkgs/nixos/modules/services/audio/roon-server.nix6
-rw-r--r--nixpkgs/nixos/modules/services/audio/snapserver.nix166
-rw-r--r--nixpkgs/nixos/modules/services/audio/spotifyd.nix2
-rw-r--r--nixpkgs/nixos/modules/services/backup/restic.nix66
-rw-r--r--nixpkgs/nixos/modules/services/backup/zfs-replication.nix2
-rw-r--r--nixpkgs/nixos/modules/services/computing/slurm/slurm.nix4
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix10
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/buildbot/worker.nix11
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/gitlab-runner.nix93
-rw-r--r--nixpkgs/nixos/modules/services/databases/mysql.nix44
-rw-r--r--nixpkgs/nixos/modules/services/databases/openldap.nix32
-rw-r--r--nixpkgs/nixos/modules/services/databases/redis.nix2
-rw-r--r--nixpkgs/nixos/modules/services/desktops/flatpak.nix1
-rw-r--r--nixpkgs/nixos/modules/services/desktops/malcontent.nix5
-rw-r--r--nixpkgs/nixos/modules/services/development/jupyter/default.nix28
-rw-r--r--nixpkgs/nixos/modules/services/games/teeworlds.nix119
-rw-r--r--nixpkgs/nixos/modules/services/hardware/fwupd.nix35
-rw-r--r--nixpkgs/nixos/modules/services/hardware/tlp.nix59
-rw-r--r--nixpkgs/nixos/modules/services/hardware/u2f.nix23
-rw-r--r--nixpkgs/nixos/modules/services/hardware/undervolt.nix82
-rw-r--r--nixpkgs/nixos/modules/services/mail/dovecot.nix35
-rw-r--r--nixpkgs/nixos/modules/services/mail/mailman.nix455
-rw-r--r--nixpkgs/nixos/modules/services/mail/mailman.xml59
-rw-r--r--nixpkgs/nixos/modules/services/mail/opensmtpd.nix23
-rw-r--r--nixpkgs/nixos/modules/services/mail/postfix.nix80
-rw-r--r--nixpkgs/nixos/modules/services/mail/roundcube.nix18
-rw-r--r--nixpkgs/nixos/modules/services/misc/gitlab.nix10
-rw-r--r--nixpkgs/nixos/modules/services/misc/gitolite.nix33
-rw-r--r--nixpkgs/nixos/modules/services/misc/home-assistant.nix1
-rw-r--r--nixpkgs/nixos/modules/services/misc/matrix-synapse.nix13
-rw-r--r--nixpkgs/nixos/modules/services/misc/matrix-synapse.xml38
-rw-r--r--nixpkgs/nixos/modules/services/misc/mautrix-telegram.nix2
-rw-r--r--nixpkgs/nixos/modules/services/misc/nix-daemon.nix164
-rw-r--r--nixpkgs/nixos/modules/services/misc/zigbee2mqtt.nix98
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/do-agent.nix17
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix14
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/apcupsd.nix38
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/keylight.nix19
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/lnd.nix46
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/modemmanager.nix33
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/redis.nix19
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/tuptime.nix9
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/zabbix-agent.nix41
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/zabbix-proxy.nix60
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/zabbix-server.nix57
-rw-r--r--nixpkgs/nixos/modules/services/network-filesystems/ipfs.nix171
-rw-r--r--nixpkgs/nixos/modules/services/networking/3proxy.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/bitcoind.nix206
-rw-r--r--nixpkgs/nixos/modules/services/networking/blockbook-frontend.nix272
-rw-r--r--nixpkgs/nixos/modules/services/networking/corerad.nix47
-rw-r--r--nixpkgs/nixos/modules/services/networking/dhcpd.nix12
-rw-r--r--nixpkgs/nixos/modules/services/networking/dnschain.nix184
-rw-r--r--nixpkgs/nixos/modules/services/networking/go-neb.nix53
-rw-r--r--nixpkgs/nixos/modules/services/networking/jicofo.nix152
-rw-r--r--nixpkgs/nixos/modules/services/networking/jitsi-videobridge.nix276
-rw-r--r--nixpkgs/nixos/modules/services/networking/kresd.nix3
-rw-r--r--nixpkgs/nixos/modules/services/networking/namecoind.nix5
-rw-r--r--nixpkgs/nixos/modules/services/networking/ncdns.nix278
-rw-r--r--nixpkgs/nixos/modules/services/networking/nsd.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/onedrive.nix72
-rw-r--r--nixpkgs/nixos/modules/services/networking/onedrive.xml34
-rw-r--r--nixpkgs/nixos/modules/services/networking/radicale.nix11
-rw-r--r--nixpkgs/nixos/modules/services/networking/resilio.nix20
-rw-r--r--nixpkgs/nixos/modules/services/networking/skydns.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/sslh.nix18
-rw-r--r--nixpkgs/nixos/modules/services/networking/tinc.nix16
-rw-r--r--nixpkgs/nixos/modules/services/networking/unifi.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/wasabibackend.nix158
-rw-r--r--nixpkgs/nixos/modules/services/networking/wg-quick.nix20
-rw-r--r--nixpkgs/nixos/modules/services/networking/wireguard.nix15
-rw-r--r--nixpkgs/nixos/modules/services/networking/wpa_supplicant.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/xandikos.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/yggdrasil.nix5
-rw-r--r--nixpkgs/nixos/modules/services/networking/yggdrasil.xml157
-rw-r--r--nixpkgs/nixos/modules/services/security/nginx-sso.nix11
-rw-r--r--nixpkgs/nixos/modules/services/security/oauth2_proxy.nix12
-rw-r--r--nixpkgs/nixos/modules/services/security/physlock.nix1
-rw-r--r--nixpkgs/nixos/modules/services/security/tor.nix2
-rw-r--r--nixpkgs/nixos/modules/services/security/yubikey-agent.nix60
-rw-r--r--nixpkgs/nixos/modules/services/torrent/transmission.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/codimd.nix4
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/convos.nix72
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/dokuwiki.nix4
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/gerrit.nix21
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/jitsi-meet.nix333
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/moodle.nix14
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/nextcloud.nix31
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/nextcloud.xml6
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix1
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/molly-brown.nix117
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/nginx/default.nix4
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/unit/default.nix2
-rw-r--r--nixpkgs/nixos/modules/services/x11/colord.nix2
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/gnome3.nix6
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix1
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix2
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/default.nix33
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/gdm.nix65
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/pantheon.nix2
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/lightdm.nix73
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/sddm.nix63
-rw-r--r--nixpkgs/nixos/modules/services/x11/xserver.nix2
-rw-r--r--nixpkgs/nixos/modules/system/activation/top-level.nix19
-rw-r--r--nixpkgs/nixos/modules/system/boot/initrd-network.nix2
-rw-r--r--nixpkgs/nixos/modules/system/boot/initrd-openvpn.nix81
-rw-r--r--nixpkgs/nixos/modules/system/boot/kernel_config.nix7
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/generic-extlinux-compatible/default.nix29
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh17
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix108
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl163
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.sh5
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py20
-rw-r--r--nixpkgs/nixos/modules/system/boot/luksroot.nix34
-rw-r--r--nixpkgs/nixos/modules/system/boot/modprobe.nix2
-rw-r--r--nixpkgs/nixos/modules/system/boot/networkd.nix14
-rw-r--r--nixpkgs/nixos/modules/system/boot/plymouth.nix3
-rw-r--r--nixpkgs/nixos/modules/system/boot/resolved.nix1
-rw-r--r--nixpkgs/nixos/modules/system/boot/stage-1-init.sh16
-rw-r--r--nixpkgs/nixos/modules/system/boot/stage-1.nix18
-rw-r--r--nixpkgs/nixos/modules/system/boot/stage-2-init.sh2
-rw-r--r--nixpkgs/nixos/modules/system/boot/stage-2.nix10
-rw-r--r--nixpkgs/nixos/modules/system/boot/systemd-unit-options.nix1
-rw-r--r--nixpkgs/nixos/modules/system/boot/systemd.nix144
-rw-r--r--nixpkgs/nixos/modules/system/boot/timesyncd.nix1
-rw-r--r--nixpkgs/nixos/modules/tasks/encrypted-devices.nix19
-rw-r--r--nixpkgs/nixos/modules/tasks/filesystems/btrfs.nix5
-rw-r--r--nixpkgs/nixos/modules/tasks/filesystems/zfs.nix25
-rw-r--r--nixpkgs/nixos/modules/tasks/lvm.nix67
-rw-r--r--nixpkgs/nixos/modules/tasks/network-interfaces-scripted.nix24
-rw-r--r--nixpkgs/nixos/modules/virtualisation/containers.nix63
-rw-r--r--nixpkgs/nixos/modules/virtualisation/docker.nix1
-rw-r--r--nixpkgs/nixos/modules/virtualisation/libvirtd.nix4
-rw-r--r--nixpkgs/nixos/modules/virtualisation/lxd.nix17
-rw-r--r--nixpkgs/nixos/modules/virtualisation/podman.nix28
-rw-r--r--nixpkgs/nixos/modules/virtualisation/qemu-vm.nix169
-rw-r--r--nixpkgs/nixos/modules/virtualisation/virtualbox-guest.nix2
-rw-r--r--nixpkgs/nixos/modules/virtualisation/virtualbox-image.nix66
176 files changed, 5811 insertions, 1534 deletions
diff --git a/nixpkgs/nixos/modules/config/fonts/fontconfig.nix b/nixpkgs/nixos/modules/config/fonts/fontconfig.nix
index 6ac64b0ec9c..52d284f739b 100644
--- a/nixpkgs/nixos/modules/config/fonts/fontconfig.nix
+++ b/nixpkgs/nixos/modules/config/fonts/fontconfig.nix
@@ -214,15 +214,7 @@ let
# fontconfig default config files
ln -s ${supportPkg.out}/etc/fonts/conf.d/*.conf \
$support_folder/
- ln -s ${latestPkg.out}/etc/fonts/conf.d/*.conf \
- $latest_folder/
-
- # update latest 51-local.conf path to look at the latest local.conf
- rm $latest_folder/51-local.conf
-
- substitute ${latestPkg.out}/etc/fonts/conf.d/51-local.conf \
- $latest_folder/51-local.conf \
- --replace local.conf /etc/fonts/${latestVersion}/local.conf
+ # Latest fontconfig is configured to look for the upstream defaults inside the package.
# 00-nixos-cache.conf
ln -s ${cacheConfSupport} \
@@ -236,7 +228,11 @@ let
# 50-user.conf
${optionalString (!cfg.includeUserConf) ''
rm $support_folder/50-user.conf
- rm $latest_folder/50-user.conf
+ ''}
+ # Since latest fontconfig looks for default files inside the package,
+ # we had to move this one elsewhere to be able to exclude it here.
+ ${optionalString cfg.includeUserConf ''
+ ln -s ${latestPkg.out}/etc/fonts/conf.d.bak/50-user.conf $latest_folder/50-user.conf
''}
# local.conf (indirect priority 51)
@@ -278,7 +274,14 @@ in
(mkRemovedOptionModule [ "fonts" "fontconfig" "hinting" "style" ] "")
(mkRemovedOptionModule [ "fonts" "fontconfig" "forceAutohint" ] "")
(mkRemovedOptionModule [ "fonts" "fontconfig" "renderMonoTTFAsBitmap" ] "")
- ];
+ ] ++ lib.forEach [ "enable" "substitutions" "preset" ]
+ (opt: lib.mkRemovedOptionModule [ "fonts" "fontconfig" "ultimate" "${opt}" ] ''
+ The fonts.fontconfig.ultimate module and configuration is obsolete.
+ The repository has since been archived and activity has ceased.
+ https://github.com/bohoomil/fontconfig-ultimate/issues/171.
+ No action should be needed for font configuration, as the fonts.fontconfig
+ module is already used by default.
+ '');
options = {
diff --git a/nixpkgs/nixos/modules/config/i18n.nix b/nixpkgs/nixos/modules/config/i18n.nix
index cc2ddda9d32..feb76581a72 100644
--- a/nixpkgs/nixos/modules/config/i18n.nix
+++ b/nixpkgs/nixos/modules/config/i18n.nix
@@ -68,7 +68,8 @@ with lib;
config = {
environment.systemPackages =
- optional (config.i18n.supportedLocales != []) config.i18n.glibcLocales;
+ # We increase the priority a little, so that plain glibc in systemPackages can't win.
+ optional (config.i18n.supportedLocales != []) (lib.setPrio (-1) config.i18n.glibcLocales);
environment.sessionVariables =
{ LANG = config.i18n.defaultLocale;
diff --git a/nixpkgs/nixos/modules/config/system-path.nix b/nixpkgs/nixos/modules/config/system-path.nix
index cba357171d7..ae9710e3518 100644
--- a/nixpkgs/nixos/modules/config/system-path.nix
+++ b/nixpkgs/nixos/modules/config/system-path.nix
@@ -41,6 +41,7 @@ let
pkgs.time
pkgs.utillinux
pkgs.which # 88K size
+ pkgs.zstd
];
in
diff --git a/nixpkgs/nixos/modules/config/update-users-groups.pl b/nixpkgs/nixos/modules/config/update-users-groups.pl
index 15e448b787a..e1c7a46e430 100644
--- a/nixpkgs/nixos/modules/config/update-users-groups.pl
+++ b/nixpkgs/nixos/modules/config/update-users-groups.pl
@@ -281,3 +281,58 @@ foreach my $u (values %usersOut) {
}
updateFile("/etc/shadow", \@shadowNew, 0600);
+
+# Rewrite /etc/subuid & /etc/subgid to include default container mappings
+
+my $subUidMapFile = "/var/lib/nixos/auto-subuid-map";
+my $subUidMap = -e $subUidMapFile ? decode_json(read_file($subUidMapFile)) : {};
+
+my (%subUidsUsed, %subUidsPrevUsed);
+
+$subUidsPrevUsed{$_} = 1 foreach values %{$subUidMap};
+
+sub allocSubUid {
+ my ($name, @rest) = @_;
+
+ # TODO: No upper bounds?
+ my ($min, $max, $up) = (100000, 100000 * 100, 1);
+ my $prevId = $subUidMap->{$name};
+ if (defined $prevId && !defined $subUidsUsed{$prevId}) {
+ $subUidsUsed{$prevId} = 1;
+ return $prevId;
+ }
+
+ my $id = allocId(\%subUidsUsed, \%subUidsPrevUsed, $min, $max, $up, sub { my ($uid) = @_; getpwuid($uid) });
+ my $offset = $id - 100000;
+ my $count = $offset * 65536;
+ my $subordinate = 100000 + $count;
+ return $subordinate;
+}
+
+my @subGids;
+my @subUids;
+foreach my $u (values %usersOut) {
+ my $name = $u->{name};
+
+ foreach my $range (@{$u->{subUidRanges}}) {
+ my $value = join(":", ($name, $range->{startUid}, $range->{count}));
+ push @subUids, $value;
+ }
+
+ foreach my $range (@{$u->{subGidRanges}}) {
+ my $value = join(":", ($name, $range->{startGid}, $range->{count}));
+ push @subGids, $value;
+ }
+
+ if($u->{isNormalUser}) {
+ my $subordinate = allocSubUid($name);
+ $subUidMap->{$name} = $subordinate;
+ my $value = join(":", ($name, $subordinate, 65536));
+ push @subUids, $value;
+ push @subGids, $value;
+ }
+}
+
+updateFile("/etc/subuid", join("\n", @subUids) . "\n");
+updateFile("/etc/subgid", join("\n", @subGids) . "\n");
+updateFile($subUidMapFile, encode_json($subUidMap) . "\n");
diff --git a/nixpkgs/nixos/modules/config/users-groups.nix b/nixpkgs/nixos/modules/config/users-groups.nix
index 141e43fec39..56b7af98b61 100644
--- a/nixpkgs/nixos/modules/config/users-groups.nix
+++ b/nixpkgs/nixos/modules/config/users-groups.nix
@@ -6,6 +6,16 @@ let
ids = config.ids;
cfg = config.users;
+ # Check whether a password hash will allow login.
+ allowsLogin = hash:
+ hash == "" # login without password
+ || !(lib.elem hash
+ [ null # password login disabled
+ "!" # password login disabled
+ "!!" # a variant of "!"
+ "*" # password unset
+ ]);
+
passwordDescription = ''
The options <option>hashedPassword</option>,
<option>password</option> and <option>passwordFile</option>
@@ -25,8 +35,19 @@ let
'';
hashedPasswordDescription = ''
- To generate hashed password install <literal>mkpasswd</literal>
+ To generate a hashed password install the <literal>mkpasswd</literal>
package and run <literal>mkpasswd -m sha-512</literal>.
+
+ If set to an empty string (<literal>""</literal>), this user will
+ be able to log in without being asked for a password (but not via remote
+ services such as SSH, or indirectly via <command>su</command> or
+ <command>sudo</command>). This should only be used for e.g. bootable
+ live systems. Note: this is different from setting an empty password,
+ which ca be achieved using <option>users.users.&lt;name?&gt;.password</option>.
+
+ If set to <literal>null</literal> (default) this user will not
+ be able to log in using a password (i.e. via <command>login</command>
+ command).
'';
userOpts = { name, config, ... }: {
@@ -354,18 +375,6 @@ let
};
};
- mkSubuidEntry = user: concatStrings (
- map (range: "${user.name}:${toString range.startUid}:${toString range.count}\n")
- user.subUidRanges);
-
- subuidFile = concatStrings (map mkSubuidEntry (attrValues cfg.users));
-
- mkSubgidEntry = user: concatStrings (
- map (range: "${user.name}:${toString range.startGid}:${toString range.count}\n")
- user.subGidRanges);
-
- subgidFile = concatStrings (map mkSubgidEntry (attrValues cfg.users));
-
idsAreUnique = set: idAttr: !(fold (name: args@{ dup, acc }:
let
id = builtins.toString (builtins.getAttr idAttr (builtins.getAttr name set));
@@ -385,6 +394,7 @@ let
{ inherit (u)
name uid group description home createHome isSystemUser
password passwordFile hashedPassword
+ isNormalUser subUidRanges subGidRanges
initialPassword initialHashedPassword;
shell = utils.toShellPath u.shell;
}) cfg.users;
@@ -406,6 +416,12 @@ in {
imports = [
(mkAliasOptionModule [ "users" "extraUsers" ] [ "users" "users" ])
(mkAliasOptionModule [ "users" "extraGroups" ] [ "users" "groups" ])
+ (mkChangedOptionModule
+ [ "security" "initialRootPassword" ]
+ [ "users" "users" "root" "initialHashedPassword" ]
+ (cfg: if cfg.security.initialRootPassword == "!"
+ then null
+ else cfg.security.initialRootPassword))
];
###### interface
@@ -477,14 +493,6 @@ in {
'';
};
- # FIXME: obsolete - will remove.
- security.initialRootPassword = mkOption {
- type = types.str;
- default = "!";
- example = "";
- visible = false;
- };
-
};
@@ -499,7 +507,6 @@ in {
home = "/root";
shell = mkDefault cfg.defaultUserShell;
group = "root";
- initialHashedPassword = mkDefault config.security.initialRootPassword;
};
nobody = {
uid = ids.uids.nobody;
@@ -549,16 +556,7 @@ in {
# Install all the user shells
environment.systemPackages = systemShells;
- environment.etc = {
- subuid = {
- text = subuidFile;
- mode = "0644";
- };
- subgid = {
- text = subgidFile;
- mode = "0644";
- };
- } // (mapAttrs' (name: { packages, ... }: {
+ environment.etc = (mapAttrs' (name: { packages, ... }: {
name = "profiles/per-user/${name}";
value.source = pkgs.buildEnv {
name = "user-environment";
@@ -583,22 +581,65 @@ in {
# password or an SSH authorized key. Privileged accounts are
# root and users in the wheel group.
assertion = !cfg.mutableUsers ->
- any id (mapAttrsToList (name: cfg:
+ any id ((mapAttrsToList (name: cfg:
(name == "root"
|| cfg.group == "wheel"
|| elem "wheel" cfg.extraGroups)
&&
- ((cfg.hashedPassword != null && cfg.hashedPassword != "!")
+ (allowsLogin cfg.hashedPassword
|| cfg.password != null
|| cfg.passwordFile != null
|| cfg.openssh.authorizedKeys.keys != []
|| cfg.openssh.authorizedKeys.keyFiles != [])
- ) cfg.users);
+ ) cfg.users) ++ [
+ config.security.googleOsLogin.enable
+ ]);
message = ''
Neither the root account nor any wheel user has a password or SSH authorized key.
You must set one to prevent being locked out of your system.'';
}
- ];
+ ] ++ flip mapAttrsToList cfg.users (name: user:
+ {
+ assertion = (user.hashedPassword != null)
+ -> (builtins.match ".*:.*" user.hashedPassword == null);
+ message = ''
+ The password hash of user "${name}" contains a ":" character.
+ This is invalid and would break the login system because the fields
+ of /etc/shadow (file where hashes are stored) are colon-separated.
+ Please check the value of option `users.users."${name}".hashedPassword`.'';
+ }
+ );
+
+ warnings =
+ builtins.filter (x: x != null) (
+ flip mapAttrsToList cfg.users (name: user:
+ # This regex matches a subset of the Modular Crypto Format (MCF)[1]
+ # informal standard. Since this depends largely on the OS or the
+ # specific implementation of crypt(3) we only support the (sane)
+ # schemes implemented by glibc and BSDs. In particular the original
+ # DES hash is excluded since, having no structure, it would validate
+ # common mistakes like typing the plaintext password.
+ #
+ # [1]: https://en.wikipedia.org/wiki/Crypt_(C)
+ let
+ sep = "\\$";
+ base64 = "[a-zA-Z0-9./]+";
+ id = "[a-z0-9-]+";
+ value = "[a-zA-Z0-9/+.-]+";
+ options = "${id}(=${value})?(,${id}=${value})*";
+ scheme = "${id}(${sep}${options})?";
+ content = "${base64}${sep}${base64}";
+ mcf = "^${sep}${scheme}${sep}${content}$";
+ in
+ if (allowsLogin user.hashedPassword
+ && user.hashedPassword != "" # login without password
+ && builtins.match mcf user.hashedPassword == null)
+ then ''
+ The password hash of user "${name}" may be invalid. You must set a
+ valid hash or the user will be locked out of their account. Please
+ check the value of option `users.users."${name}".hashedPassword`.''
+ else null
+ ));
};
diff --git a/nixpkgs/nixos/modules/hardware/device-tree.nix b/nixpkgs/nixos/modules/hardware/device-tree.nix
index cf553497c89..b3f1dda98c8 100644
--- a/nixpkgs/nixos/modules/hardware/device-tree.nix
+++ b/nixpkgs/nixos/modules/hardware/device-tree.nix
@@ -22,11 +22,22 @@ in {
example = literalExample "pkgs.device-tree_rpi";
type = types.path;
description = ''
- The package containing the base device-tree (.dtb) to boot. Contains
+ The path containing the base device-tree (.dtb) to boot. Contains
device trees bundled with the Linux kernel by default.
'';
};
+ name = mkOption {
+ default = null;
+ example = "some-dtb.dtb";
+ type = types.nullOr types.str;
+ description = ''
+ The name of an explicit dtb to be loaded, relative to the dtb base.
+ Useful in extlinux scenarios if the bootloader doesn't pick the
+ right .dtb file from FDTDIR.
+ '';
+ };
+
overlays = mkOption {
default = [];
example = literalExample
diff --git a/nixpkgs/nixos/modules/hardware/logitech.nix b/nixpkgs/nixos/modules/hardware/logitech.nix
index d6f43bdddcc..3ebe6aacf5d 100644
--- a/nixpkgs/nixos/modules/hardware/logitech.nix
+++ b/nixpkgs/nixos/modules/hardware/logitech.nix
@@ -5,24 +5,92 @@ with lib;
let
cfg = config.hardware.logitech;
-in {
+ vendor = "046d";
+
+ daemon = "g15daemon";
+
+in
+{
+ imports = [
+ (mkRenamedOptionModule [ "hardware" "logitech" "enable" ] [ "hardware" "logitech" "wireless" "enable" ])
+ (mkRenamedOptionModule [ "hardware" "logitech" "enableGraphical" ] [ "hardware" "logitech" "wireless" "enableGraphical" ])
+ ];
+
options.hardware.logitech = {
- enable = mkEnableOption "Logitech Devices";
- enableGraphical = mkOption {
- type = types.bool;
- default = false;
- description = "Enable graphical support applications.";
+ lcd = {
+ enable = mkEnableOption "Logitech LCD Devices";
+
+ startWhenNeeded = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Only run the service when an actual supported device is plugged.
+ '';
+ };
+
+ devices = mkOption {
+ type = types.listOf types.str;
+ default = [ "0a07" "c222" "c225" "c227" "c251" ];
+ description = ''
+ List of USB device ids supported by g15daemon.
+ </para>
+ <para>
+ You most likely do not need to change this.
+ '';
+ };
+ };
+
+ wireless = {
+ enable = mkEnableOption "Logitech Wireless Devices";
+
+ enableGraphical = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Enable graphical support applications.";
+ };
};
};
- config = lib.mkIf cfg.enable {
- environment.systemPackages = [
- pkgs.ltunify
- ] ++ lib.optional cfg.enableGraphical pkgs.solaar;
+ config = lib.mkIf (cfg.wireless.enable || cfg.lcd.enable) {
+ environment.systemPackages = []
+ ++ lib.optional cfg.wireless.enable pkgs.ltunify
+ ++ lib.optional cfg.wireless.enableGraphical pkgs.solaar;
+
+ services.udev = {
+ # ltunifi and solaar both provide udev rules but the most up-to-date have been split
+ # out into a dedicated derivation
- # ltunifi and solaar both provide udev rules but the most up-to-date have been split
- # out into a dedicated derivation
- services.udev.packages = with pkgs; [ logitech-udev-rules ];
+ packages = []
+ ++ lib.optional cfg.wireless.enable pkgs.logitech-udev-rules
+ ++ lib.optional cfg.lcd.enable pkgs.g15daemon;
+
+ extraRules = ''
+ # nixos: hardware.logitech.lcd
+ '' + lib.concatMapStringsSep "\n" (
+ dev:
+ ''ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="${vendor}", ATTRS{idProduct}=="${dev}", TAG+="systemd", ENV{SYSTEMD_WANTS}+="${daemon}.service"''
+ ) cfg.lcd.devices;
+ };
+
+ systemd.services."${daemon}" = lib.mkIf cfg.lcd.enable {
+ description = "Logitech LCD Support Daemon";
+ documentation = [ "man:g15daemon(1)" ];
+ wantedBy = lib.mkIf (! cfg.lcd.startWhenNeeded) "multi-user.target";
+
+ serviceConfig = {
+ Type = "forking";
+ ExecStart = "${pkgs.g15daemon}/bin/g15daemon";
+ # we patch it to write to /run/g15daemon/g15daemon.pid instead of
+ # /run/g15daemon.pid so systemd will do the cleanup for us.
+ PIDFile = "/run/${daemon}/g15daemon.pid";
+ PrivateTmp = true;
+ PrivateNetwork = true;
+ ProtectHome = "tmpfs";
+ ProtectSystem = "full"; # strict doesn't work
+ RuntimeDirectory = daemon;
+ Restart = "on-failure";
+ };
+ };
};
}
diff --git a/nixpkgs/nixos/modules/hardware/printers.nix b/nixpkgs/nixos/modules/hardware/printers.nix
index 56b91933477..752de41f26d 100644
--- a/nixpkgs/nixos/modules/hardware/printers.nix
+++ b/nixpkgs/nixos/modules/hardware/printers.nix
@@ -84,7 +84,7 @@ in {
model = mkOption {
type = types.str;
example = literalExample ''
- gutenprint.''${lib.version.majorMinor (lib.getVersion pkgs.cups)}://brother-hl-5140/expert
+ gutenprint.''${lib.versions.majorMinor (lib.getVersion pkgs.gutenprint)}://brother-hl-5140/expert
'';
description = ''
Location of the ppd driver file for the printer.
diff --git a/nixpkgs/nixos/modules/hardware/video/hidpi.nix b/nixpkgs/nixos/modules/hardware/video/hidpi.nix
new file mode 100644
index 00000000000..ac72b652504
--- /dev/null
+++ b/nixpkgs/nixos/modules/hardware/video/hidpi.nix
@@ -0,0 +1,16 @@
+{ lib, pkgs, config, ...}:
+with lib;
+
+{
+ options.hardware.video.hidpi.enable = mkEnableOption "Font/DPI configuration optimized for HiDPI displays";
+
+ config = mkIf config.hardware.video.hidpi.enable {
+ console.font = lib.mkDefault "${pkgs.terminus_font}/share/consolefonts/ter-v32n.psf.gz";
+
+ # Needed when typing in passwords for full disk encryption
+ console.earlySetup = mkDefault true;
+ boot.loader.systemd-boot.consoleMode = mkDefault "1";
+
+ # TODO Find reasonable defaults X11 & wayland
+ };
+}
diff --git a/nixpkgs/nixos/modules/hardware/video/uvcvideo/default.nix b/nixpkgs/nixos/modules/hardware/video/uvcvideo/default.nix
index 7e3e94fdf2b..cf6aa052abb 100644
--- a/nixpkgs/nixos/modules/hardware/video/uvcvideo/default.nix
+++ b/nixpkgs/nixos/modules/hardware/video/uvcvideo/default.nix
@@ -26,7 +26,7 @@ in
Whether to enable <command>uvcvideo</command> dynamic controls.
Note that enabling this brings the <command>uvcdynctrl</command> tool
- into your environement and register all dynamic controls from
+ into your environment and register all dynamic controls from
specified <command>packages</command> to the <command>uvcvideo</command> driver.
'';
};
diff --git a/nixpkgs/nixos/modules/hardware/xpadneo.nix b/nixpkgs/nixos/modules/hardware/xpadneo.nix
new file mode 100644
index 00000000000..d504697e61f
--- /dev/null
+++ b/nixpkgs/nixos/modules/hardware/xpadneo.nix
@@ -0,0 +1,29 @@
+{ config, lib, ... }:
+
+with lib;
+let
+ cfg = config.hardware.xpadneo;
+in
+{
+ options.hardware.xpadneo = {
+ enable = mkEnableOption "the xpadneo driver for Xbox One wireless controllers";
+ };
+
+ config = mkIf cfg.enable {
+ boot = {
+ # Must disable Enhanced Retransmission Mode to support bluetooth pairing
+ # https://wiki.archlinux.org/index.php/Gamepad#Connect_Xbox_Wireless_Controller_with_Bluetooth
+ extraModprobeConfig =
+ mkIf
+ config.hardware.bluetooth.enable
+ "options bluetooth disable_ertm=1";
+
+ extraModulePackages = with config.boot.kernelPackages; [ xpadneo ];
+ kernelModules = [ "hid_xpadneo" ];
+ };
+ };
+
+ meta = {
+ maintainers = with maintainers; [ metadark ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/i18n/input-method/ibus.nix b/nixpkgs/nixos/modules/i18n/input-method/ibus.nix
index b4746b21b65..cf24ecf5863 100644
--- a/nixpkgs/nixos/modules/i18n/input-method/ibus.nix
+++ b/nixpkgs/nixos/modules/i18n/input-method/ibus.nix
@@ -64,7 +64,7 @@ in
# Without dconf enabled it is impossible to use IBus
programs.dconf.enable = true;
- programs.dconf.profiles.ibus = "${ibusPackage}/etc/dconf/profile/ibus";
+ programs.dconf.packages = [ ibusPackage ];
services.dbus.packages = [
ibusAutostart
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 3707c4b7ec6..8c98691116d 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
@@ -11,15 +11,17 @@ with lib;
services.xserver.desktopManager.gnome3.enable = true;
- services.xserver.displayManager.gdm = {
- enable = true;
- # 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;
+ services.xserver.displayManager = {
+ gdm = {
+ enable = true;
+ # 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/installation-cd-graphical-plasma5.nix b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-plasma5.nix
index e76e06654ac..098c2b2870b 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-plasma5.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-plasma5.nix
@@ -16,8 +16,8 @@ with lib;
};
# Automatically login as nixos.
- displayManager.sddm = {
- enable = true;
+ displayManager = {
+ sddm.enable = true;
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 cce7cc235ec..1cd2252ecf2 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -413,7 +413,7 @@ in
default = false;
description = ''
Whether the ISO image should be compressed using
- <command>bzip2</command>.
+ <command>zstd</command>.
'';
};
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix b/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix
index 2d34406a032..bef6cd2fb5a 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix
@@ -2,12 +2,6 @@
# nix-build nixos -I nixos-config=nixos/modules/installer/cd-dvd/sd-image-aarch64.nix -A config.system.build.sdImage
{ config, lib, pkgs, ... }:
-let
- extlinux-conf-builder =
- import ../../system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix {
- pkgs = pkgs.buildPackages;
- };
-in
{
imports = [
../../profiles/base.nix
@@ -56,7 +50,7 @@ in
'';
populateRootCommands = ''
mkdir -p ./files/boot
- ${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./files/boot
+ ${config.boot.loader.generic-extlinux-compatible.populateCmd} -c ${config.system.build.toplevel} -d ./files/boot
'';
};
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix b/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix
index 651d1a36dc1..d2ba611532e 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix
@@ -2,12 +2,6 @@
# nix-build nixos -I nixos-config=nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix -A config.system.build.sdImage
{ config, lib, pkgs, ... }:
-let
- extlinux-conf-builder =
- import ../../system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix {
- pkgs = pkgs.buildPackages;
- };
-in
{
imports = [
../../profiles/base.nix
@@ -53,7 +47,7 @@ in
'';
populateRootCommands = ''
mkdir -p ./files/boot
- ${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./files/boot
+ ${config.boot.loader.generic-extlinux-compatible.populateCmd} -c ${config.system.build.toplevel} -d ./files/boot
'';
};
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix b/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix
index ba4127eaa0e..40a01f96177 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix
@@ -2,12 +2,6 @@
# nix-build nixos -I nixos-config=nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix -A config.system.build.sdImage
{ config, lib, pkgs, ... }:
-let
- extlinux-conf-builder =
- import ../../system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix {
- pkgs = pkgs.buildPackages;
- };
-in
{
imports = [
../../profiles/base.nix
@@ -42,7 +36,7 @@ in
'';
populateRootCommands = ''
mkdir -p ./files/boot
- ${extlinux-conf-builder} -t 3 -c ${config.system.build.toplevel} -d ./files/boot
+ ${config.boot.loader.generic-extlinux-compatible.populateCmd} -c ${config.system.build.toplevel} -d ./files/boot
'';
};
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-raspberrypi4.nix b/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-raspberrypi4.nix
index c545a1e7e24..79c835dc390 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-raspberrypi4.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/sd-image-raspberrypi4.nix
@@ -18,6 +18,7 @@
sdImage = {
firmwareSize = 128;
+ firmwarePartitionName = "NIXOS_BOOT";
# This is a hack to avoid replicating config.txt from boot.loader.raspberryPi
populateFirmwareCommands =
"${config.system.build.installBootLoader} ${config.system.build.toplevel} -d ./firmware";
@@ -25,6 +26,12 @@
populateRootCommands = "";
};
+ fileSystems."/boot/firmware" = {
+ # This effectively "renames" the loaOf entry set in sd-image.nix
+ mountPoint = "/boot";
+ neededForBoot = true;
+ };
+
# the installation media is also the installation target,
# so we don't want to provide the installation configuration.nix.
installer.cloneConfig = false;
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/sd-image.nix b/nixpkgs/nixos/modules/installer/cd-dvd/sd-image.nix
index 4187c01d70e..ddad1116c94 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/sd-image.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/sd-image.nix
@@ -63,6 +63,14 @@ in
'';
};
+ firmwarePartitionName = mkOption {
+ type = types.str;
+ default = "FIRMWARE";
+ description = ''
+ Name of the filesystem which holds the boot firmware.
+ '';
+ };
+
rootPartitionUUID = mkOption {
type = types.nullOr types.str;
default = null;
@@ -91,7 +99,7 @@ in
};
populateRootCommands = mkOption {
- example = literalExample "''\${extlinux-conf-builder} -t 3 -c \${config.system.build.toplevel} -d ./files/boot''";
+ example = literalExample "''\${config.boot.loader.generic-extlinux-compatible.populateCmd} -c \${config.system.build.toplevel} -d ./files/boot''";
description = ''
Shell commands to populate the ./files directory.
All files in that directory are copied to the
@@ -105,7 +113,7 @@ in
default = true;
description = ''
Whether the SD image should be compressed using
- <command>bzip2</command>.
+ <command>zstd</command>.
'';
};
@@ -114,7 +122,7 @@ in
config = {
fileSystems = {
"/boot/firmware" = {
- device = "/dev/disk/by-label/FIRMWARE";
+ device = "/dev/disk/by-label/${config.sdImage.firmwarePartitionName}";
fsType = "vfat";
# Alternatively, this could be removed from the configuration.
# The filesystem is not needed at runtime, it could be treated
@@ -130,10 +138,10 @@ in
sdImage.storePaths = [ config.system.build.toplevel ];
system.build.sdImage = pkgs.callPackage ({ stdenv, dosfstools, e2fsprogs,
- mtools, libfaketime, utillinux, bzip2, zstd }: stdenv.mkDerivation {
+ mtools, libfaketime, utillinux, zstd }: stdenv.mkDerivation {
name = config.sdImage.imageName;
- nativeBuildInputs = [ dosfstools e2fsprogs mtools libfaketime utillinux bzip2 zstd ];
+ nativeBuildInputs = [ dosfstools e2fsprogs mtools libfaketime utillinux zstd ];
inherit (config.sdImage) compressImage;
@@ -143,7 +151,7 @@ in
echo "${pkgs.stdenv.buildPlatform.system}" > $out/nix-support/system
if test -n "$compressImage"; then
- echo "file sd-image $img.bz2" >> $out/nix-support/hydra-build-products
+ echo "file sd-image $img.zst" >> $out/nix-support/hydra-build-products
else
echo "file sd-image $img" >> $out/nix-support/hydra-build-products
fi
@@ -178,7 +186,7 @@ in
# Create a FAT32 /boot/firmware partition of suitable size into firmware_part.img
eval $(partx $img -o START,SECTORS --nr 1 --pairs)
truncate -s $((SECTORS * 512)) firmware_part.img
- faketime "1970-01-01 00:00:00" mkfs.vfat -i ${config.sdImage.firmwarePartitionID} -n FIRMWARE firmware_part.img
+ faketime "1970-01-01 00:00:00" mkfs.vfat -i ${config.sdImage.firmwarePartitionID} -n ${config.sdImage.firmwarePartitionName} firmware_part.img
# Populate the files intended for /boot/firmware
mkdir firmware
@@ -190,7 +198,7 @@ in
fsck.vfat -vn firmware_part.img
dd conv=notrunc if=firmware_part.img of=$img seek=$START count=$SECTORS
if test -n "$compressImage"; then
- bzip2 $img
+ zstd -T$NIX_BUILD_CORES --rm $img
fi
'';
}) {};
diff --git a/nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix b/nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix
index 35a7b382b7c..a15a2dbadb8 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/j8dbv5w6jl34caywh2ygdy88knx1mdf7-nix-2.3.6";
- i686-linux = "/nix/store/9fqvbdisahqp0238vrs7wn5anpri0a65-nix-2.3.6";
- aarch64-linux = "/nix/store/72pwn0nm9bjqx9vpi8sgh4bl6g5wh814-nix-2.3.6";
- x86_64-darwin = "/nix/store/g37vk77m90p5zcl5nixjlzp3vqpisfn5-nix-2.3.6";
+ x86_64-linux = "/nix/store/4vz8sh9ngx34ivi0bw5hlycxdhvy5hvz-nix-2.3.7";
+ i686-linux = "/nix/store/dzxkg9lpp60bjmzvagns42vqlz3yq5kx-nix-2.3.7";
+ aarch64-linux = "/nix/store/cfvf8nl8mwyw817by5y8zd3s8pnf5m9f-nix-2.3.7";
+ x86_64-darwin = "/nix/store/5ira7xgs92inqz1x8l0n1wci4r79hnd0-nix-2.3.7";
}
diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-generate-config.pl b/nixpkgs/nixos/modules/installer/tools/nixos-generate-config.pl
index 422c405054d..c8303a6eb60 100644
--- a/nixpkgs/nixos/modules/installer/tools/nixos-generate-config.pl
+++ b/nixpkgs/nixos/modules/installer/tools/nixos-generate-config.pl
@@ -497,8 +497,8 @@ if (-f $fb_modes_file && -r $fb_modes_file) {
$modes =~ m/([0-9]+)x([0-9]+)/;
my $console_width = $1, my $console_height = $2;
if ($console_width > 1920) {
- push @attrs, "# High-DPI console";
- push @attrs, 'console.font = lib.mkDefault "${pkgs.terminus_font}/share/consolefonts/ter-u28n.psf.gz";';
+ push @attrs, "# high-resolution display";
+ push @attrs, 'hardware.video.hidpi.enable = lib.mkDefault true;';
}
}
@@ -628,6 +628,7 @@ EOF
write_file($fn, <<EOF);
@configuration@
EOF
+ print STDERR "For more hardware-specific settings, see https://github.com/NixOS/nixos-hardware"
} else {
print STDERR "warning: not overwriting existing $fn\n";
}
diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-install.sh b/nixpkgs/nixos/modules/installer/tools/nixos-install.sh
index 1bccbbfaf24..0b62bca8367 100644
--- a/nixpkgs/nixos/modules/installer/tools/nixos-install.sh
+++ b/nixpkgs/nixos/modules/installer/tools/nixos-install.sh
@@ -71,6 +71,17 @@ if ! test -e "$mountPoint"; then
exit 1
fi
+# Verify permissions are okay-enough
+checkPath="$(realpath "$mountPoint")"
+while [[ "$checkPath" != "/" ]]; do
+ mode="$(stat -c '%a' "$checkPath")"
+ if [[ "${mode: -1}" -lt "5" ]]; then
+ echo "path $checkPath should have permissions 755, but had permissions $mode. Consider running 'chmod o+rx $checkPath'."
+ exit 1
+ fi
+ checkPath="$(dirname "$checkPath")"
+done
+
# Get the path of the NixOS configuration file.
if [[ -z $NIXOS_CONFIG ]]; then
NIXOS_CONFIG=$mountPoint/etc/nixos/configuration.nix
diff --git a/nixpkgs/nixos/modules/misc/documentation.nix b/nixpkgs/nixos/modules/misc/documentation.nix
index 7ad4be9a02e..71a40b4f4d6 100644
--- a/nixpkgs/nixos/modules/misc/documentation.nix
+++ b/nixpkgs/nixos/modules/misc/documentation.nix
@@ -102,6 +102,16 @@ in
'';
};
+ man.generateCaches = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to generate the manual page index caches using
+ <literal>mandb(8)</literal>. This allows searching for a page or
+ keyword using utilities like <literal>apropos(1)</literal>.
+ '';
+ };
+
info.enable = mkOption {
type = types.bool;
default = true;
@@ -187,7 +197,33 @@ in
environment.systemPackages = [ pkgs.man-db ];
environment.pathsToLink = [ "/share/man" ];
environment.extraOutputsToInstall = [ "man" ] ++ optional cfg.dev.enable "devman";
- environment.etc."man.conf".source = "${pkgs.man-db}/etc/man_db.conf";
+ environment.etc."man_db.conf".text =
+ let
+ manualPages = pkgs.buildEnv {
+ name = "man-paths";
+ paths = config.environment.systemPackages;
+ pathsToLink = [ "/share/man" ];
+ extraOutputsToInstall = ["man"];
+ ignoreCollisions = true;
+ };
+ manualCache = pkgs.runCommandLocal "man-cache" { }
+ ''
+ echo "MANDB_MAP ${manualPages}/share/man $out" > man.conf
+ ${pkgs.man-db}/bin/mandb -C man.conf -psc
+ '';
+ in
+ ''
+ # Manual pages paths for NixOS
+ MANPATH_MAP /run/current-system/sw/bin /run/current-system/sw/share/man
+ MANPATH_MAP /run/wrappers/bin /run/current-system/sw/share/man
+
+ ${optionalString cfg.man.generateCaches ''
+ # Generated manual pages cache for NixOS (immutable)
+ MANDB_MAP /run/current-system/sw/share/man ${manualCache}
+ ''}
+ # Manual pages caches for NixOS
+ MANDB_MAP /run/current-system/sw/share/man /var/cache/man/nixos
+ '';
})
(mkIf cfg.info.enable {
diff --git a/nixpkgs/nixos/modules/misc/ids.nix b/nixpkgs/nixos/modules/misc/ids.nix
index 85e5534e906..4692ea32656 100644
--- a/nixpkgs/nixos/modules/misc/ids.nix
+++ b/nixpkgs/nixos/modules/misc/ids.nix
@@ -239,7 +239,6 @@ in
shout = 206;
gateone = 207;
namecoin = 208;
- dnschain = 209;
#lxd = 210; # unused
kibana = 211;
xtreemfs = 212;
@@ -346,6 +345,7 @@ in
zoneminder = 314;
paperless = 315;
#mailman = 316; # removed 2019-08-30
+ zigbee2mqtt = 317;
# When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
@@ -549,7 +549,6 @@ in
#shout = 206; #unused
gateone = 207;
namecoin = 208;
- #dnschain = 209; #unused
lxd = 210; # unused
#kibana = 211;
xtreemfs = 212;
@@ -647,6 +646,7 @@ in
zoneminder = 314;
paperless = 315;
#mailman = 316; # removed 2019-08-30
+ zigbee2mqtt = 317;
# When adding a gid, make sure it doesn't match an existing
# uid. Users and groups with the same name should have equal
diff --git a/nixpkgs/nixos/modules/module-list.nix b/nixpkgs/nixos/modules/module-list.nix
index 42491c1a9e9..5e78103f0dd 100644
--- a/nixpkgs/nixos/modules/module-list.nix
+++ b/nixpkgs/nixos/modules/module-list.nix
@@ -72,9 +72,11 @@
./hardware/video/capture/mwprocapture.nix
./hardware/video/bumblebee.nix
./hardware/video/displaylink.nix
+ ./hardware/video/hidpi.nix
./hardware/video/nvidia.nix
./hardware/video/uvcvideo/default.nix
./hardware/video/webcam/facetimehd.nix
+ ./hardware/xpadneo.nix
./i18n/input-method/default.nix
./i18n/input-method/fcitx.nix
./i18n/input-method/ibus.nix
@@ -126,6 +128,7 @@
./programs/gpaste.nix
./programs/gnupg.nix
./programs/gphoto2.nix
+ ./programs/hamster.nix
./programs/iftop.nix
./programs/iotop.nix
./programs/java.nix
@@ -153,6 +156,7 @@
./programs/ssmtp.nix
./programs/sysdig.nix
./programs/systemtap.nix
+ ./programs/steam.nix
./programs/sway.nix
./programs/system-config-printer.nix
./programs/thefuck.nix
@@ -334,6 +338,7 @@
./services/games/minecraft-server.nix
./services/games/minetest-server.nix
./services/games/openarena.nix
+ ./services/games/teeworlds.nix
./services/games/terraria.nix
./services/hardware/acpid.nix
./services/hardware/actkbd.nix
@@ -361,7 +366,6 @@
./services/hardware/throttled.nix
./services/hardware/trezord.nix
./services/hardware/triggerhappy.nix
- ./services/hardware/u2f.nix
./services/hardware/udev.nix
./services/hardware/udisks2.nix
./services/hardware/upower.nix
@@ -509,6 +513,7 @@
./services/misc/uhub.nix
./services/misc/weechat.nix
./services/misc/xmr-stak.nix
+ ./services/misc/zigbee2mqtt.nix
./services/misc/zoneminder.nix
./services/misc/zookeeper.nix
./services/monitoring/alerta.nix
@@ -588,6 +593,7 @@
./services/networking/autossh.nix
./services/networking/bird.nix
./services/networking/bitlbee.nix
+ ./services/networking/blockbook-frontend.nix
./services/networking/charybdis.nix
./services/networking/cjdns.nix
./services/networking/cntlm.nix
@@ -601,11 +607,11 @@
./services/networking/dhcpcd.nix
./services/networking/dhcpd.nix
./services/networking/dnscache.nix
- ./services/networking/dnschain.nix
./services/networking/dnscrypt-proxy2.nix
./services/networking/dnscrypt-wrapper.nix
./services/networking/dnsdist.nix
./services/networking/dnsmasq.nix
+ ./services/networking/ncdns.nix
./services/networking/ejabberd.nix
./services/networking/epmd.nix
./services/networking/ergo.nix
@@ -624,6 +630,7 @@
./services/networking/gdomap.nix
./services/networking/git-daemon.nix
./services/networking/gnunet.nix
+ ./services/networking/go-neb.nix
./services/networking/go-shadowsocks2.nix
./services/networking/gogoclient.nix
./services/networking/gvpe.nix
@@ -639,6 +646,8 @@
./services/networking/iperf3.nix
./services/networking/ircd-hybrid/default.nix
./services/networking/iwd.nix
+ ./services/networking/jicofo.nix
+ ./services/networking/jitsi-videobridge.nix
./services/networking/keepalived/default.nix
./services/networking/keybase.nix
./services/networking/kippo.nix
@@ -685,6 +694,7 @@
./services/networking/ocserv.nix
./services/networking/ofono.nix
./services/networking/oidentd.nix
+ ./services/networking/onedrive.nix
./services/networking/openfire.nix
./services/networking/openvpn.nix
./services/networking/ostinato.nix
@@ -757,6 +767,7 @@
./services/networking/v2ray.nix
./services/networking/vsftpd.nix
./services/networking/wakeonlan.nix
+ ./services/networking/wasabibackend.nix
./services/networking/websockify.nix
./services/networking/wg-quick.nix
./services/networking/wicd.nix
@@ -807,6 +818,7 @@
./services/security/torsocks.nix
./services/security/usbguard.nix
./services/security/vault.nix
+ ./services/security/yubikey-agent.nix
./services/system/cloud-init.nix
./services/system/dbus.nix
./services/system/earlyoom.nix
@@ -830,6 +842,7 @@
./services/web-apps/atlassian/crowd.nix
./services/web-apps/atlassian/jira.nix
./services/web-apps/codimd.nix
+ ./services/web-apps/convos.nix
./services/web-apps/cryptpad.nix
./services/web-apps/documize.nix
./services/web-apps/dokuwiki.nix
@@ -842,6 +855,7 @@
./services/web-apps/icingaweb2/module-monitoring.nix
./services/web-apps/ihatemoney
./services/web-apps/jirafeau.nix
+ ./services/web-apps/jitsi-meet.nix
./services/web-apps/limesurvey.nix
./services/web-apps/mattermost.nix
./services/web-apps/mediawiki.nix
@@ -877,6 +891,7 @@
./services/web-servers/meguca.nix
./services/web-servers/mighttpd2.nix
./services/web-servers/minio.nix
+ ./services/web-servers/molly-brown.nix
./services/web-servers/nginx/default.nix
./services/web-servers/nginx/gitweb.nix
./services/web-servers/phpfpm/default.nix
@@ -934,6 +949,7 @@
./system/boot/grow-partition.nix
./system/boot/initrd-network.nix
./system/boot/initrd-ssh.nix
+ ./system/boot/initrd-openvpn.nix
./system/boot/kernel.nix
./system/boot/kexec.nix
./system/boot/loader/efi.nix
diff --git a/nixpkgs/nixos/modules/profiles/demo.nix b/nixpkgs/nixos/modules/profiles/demo.nix
index 18f190071ba..4e8c74deedb 100644
--- a/nixpkgs/nixos/modules/profiles/demo.nix
+++ b/nixpkgs/nixos/modules/profiles/demo.nix
@@ -11,9 +11,11 @@
uid = 1000;
};
- services.xserver.displayManager.sddm.autoLogin = {
- enable = true;
- relogin = true;
- user = "demo";
+ services.xserver.displayManager = {
+ autoLogin = {
+ enable = true;
+ user = "demo";
+ };
+ sddm.autoLogin.relogin = true;
};
}
diff --git a/nixpkgs/nixos/modules/programs/dconf.nix b/nixpkgs/nixos/modules/programs/dconf.nix
index 6702e8efd1c..ec85cb9d18c 100644
--- a/nixpkgs/nixos/modules/programs/dconf.nix
+++ b/nixpkgs/nixos/modules/programs/dconf.nix
@@ -4,13 +4,24 @@ with lib;
let
cfg = config.programs.dconf;
-
- mkDconfProfile = name: path:
- {
- name = "dconf/profile/${name}";
- value.source = path;
- };
-
+ cfgDir = pkgs.symlinkJoin {
+ name = "dconf-system-config";
+ paths = map (x: "${x}/etc/dconf") cfg.packages;
+ postBuild = ''
+ mkdir -p $out/profile
+ mkdir -p $out/db
+ '' + (
+ concatStringsSep "\n" (
+ mapAttrsToList (
+ name: path: ''
+ ln -s ${path} $out/profile/${name}
+ ''
+ ) cfg.profiles
+ )
+ ) + ''
+ ${pkgs.dconf}/bin/dconf update $out/db
+ '';
+ };
in
{
###### interface
@@ -22,18 +33,24 @@ in
profiles = mkOption {
type = types.attrsOf types.path;
default = {};
- description = "Set of dconf profile files.";
+ description = "Set of dconf profile files, installed at <filename>/etc/dconf/profiles/<replaceable>name</replaceable></filename>.";
internal = true;
};
+ packages = mkOption {
+ type = types.listOf types.package;
+ default = [];
+ description = "A list of packages which provide dconf profiles and databases in <filename>/etc/dconf</filename>.";
+ };
};
};
###### implementation
config = mkIf (cfg.profiles != {} || cfg.enable) {
- environment.etc = optionalAttrs (cfg.profiles != {})
- (mapAttrs' mkDconfProfile cfg.profiles);
+ environment.etc.dconf = mkIf (cfg.profiles != {} || cfg.packages != []) {
+ source = cfgDir;
+ };
services.dbus.packages = [ pkgs.dconf ];
diff --git a/nixpkgs/nixos/modules/programs/fish.nix b/nixpkgs/nixos/modules/programs/fish.nix
index 48b324a0fe8..39b92edf2ac 100644
--- a/nixpkgs/nixos/modules/programs/fish.nix
+++ b/nixpkgs/nixos/modules/programs/fish.nix
@@ -102,6 +102,9 @@ in
programs.fish.shellAliases = mapAttrs (name: mkDefault) cfge.shellAliases;
+ # Required for man completions
+ documentation.man.generateCaches = true;
+
environment.etc."fish/foreign-env/shellInit".text = cfge.shellInit;
environment.etc."fish/foreign-env/loginShellInit".text = cfge.loginShellInit;
environment.etc."fish/foreign-env/interactiveShellInit".text = cfge.interactiveShellInit;
diff --git a/nixpkgs/nixos/modules/programs/gnupg.nix b/nixpkgs/nixos/modules/programs/gnupg.nix
index 7a3cb588ee7..ce8799b21d6 100644
--- a/nixpkgs/nixos/modules/programs/gnupg.nix
+++ b/nixpkgs/nixos/modules/programs/gnupg.nix
@@ -70,6 +70,7 @@ in
agent.pinentryFlavor = mkOption {
type = types.nullOr (types.enum pkgs.pinentry.flavors);
example = "gnome3";
+ default = defaultPinentryFlavor;
description = ''
Which pinentry interface to use. If not null, the path to the
pinentry binary will be passed to gpg-agent via commandline and
@@ -91,8 +92,6 @@ in
};
config = mkIf cfg.agent.enable {
- programs.gnupg.agent.pinentryFlavor = mkDefault defaultPinentryFlavor;
-
# This overrides the systemd user unit shipped with the gnupg package
systemd.user.services.gpg-agent = mkIf (cfg.agent.pinentryFlavor != null) {
serviceConfig.ExecStart = [ "" ''
diff --git a/nixpkgs/nixos/modules/programs/hamster.nix b/nixpkgs/nixos/modules/programs/hamster.nix
new file mode 100644
index 00000000000..b2f4a82b260
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/hamster.nix
@@ -0,0 +1,15 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ meta.maintainers = pkgs.hamster.meta.maintainers;
+
+ options.programs.hamster.enable =
+ mkEnableOption "Whether to enable hamster time tracking.";
+
+ config = lib.mkIf config.programs.hamster.enable {
+ environment.systemPackages = [ pkgs.hamster ];
+ services.dbus.packages = [ pkgs.hamster ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/programs/ssh.nix b/nixpkgs/nixos/modules/programs/ssh.nix
index 44e65ee8a9a..a983ffa4b89 100644
--- a/nixpkgs/nixos/modules/programs/ssh.nix
+++ b/nixpkgs/nixos/modules/programs/ssh.nix
@@ -194,6 +194,33 @@ in
'';
};
+ kexAlgorithms = mkOption {
+ type = types.nullOr (types.listOf types.str);
+ default = null;
+ example = [ "curve25519-sha256@libssh.org" "diffie-hellman-group-exchange-sha256" ];
+ description = ''
+ Specifies the available KEX (Key Exchange) algorithms.
+ '';
+ };
+
+ ciphers = mkOption {
+ type = types.nullOr (types.listOf types.str);
+ default = null;
+ example = [ "chacha20-poly1305@openssh.com" "aes256-gcm@openssh.com" ];
+ description = ''
+ Specifies the ciphers allowed and their order of preference.
+ '';
+ };
+
+ macs = mkOption {
+ type = types.nullOr (types.listOf types.str);
+ default = null;
+ example = [ "hmac-sha2-512-etm@openssh.com" "hmac-sha1" ];
+ description = ''
+ Specifies the MAC (message authentication code) algorithms in order of preference. The MAC algorithm is used
+ for data integrity protection.
+ '';
+ };
};
};
@@ -232,6 +259,9 @@ in
${optionalString (cfg.pubkeyAcceptedKeyTypes != []) "PubkeyAcceptedKeyTypes ${concatStringsSep "," cfg.pubkeyAcceptedKeyTypes}"}
${optionalString (cfg.hostKeyAlgorithms != []) "HostKeyAlgorithms ${concatStringsSep "," cfg.hostKeyAlgorithms}"}
+ ${optionalString (cfg.kexAlgorithms != null) "KexAlgorithms ${concatStringsSep "," cfg.kexAlgorithms}"}
+ ${optionalString (cfg.ciphers != null) "Ciphers ${concatStringsSep "," cfg.ciphers}"}
+ ${optionalString (cfg.macs != null) "MACs ${concatStringsSep "," cfg.macs}"}
'';
environment.etc."ssh/ssh_known_hosts".text = knownHostsText;
diff --git a/nixpkgs/nixos/modules/programs/ssmtp.nix b/nixpkgs/nixos/modules/programs/ssmtp.nix
index c7a94739349..15d2750c193 100644
--- a/nixpkgs/nixos/modules/programs/ssmtp.nix
+++ b/nixpkgs/nixos/modules/programs/ssmtp.nix
@@ -21,9 +21,11 @@ in
(mkRenamedOptionModule [ "networking" "defaultMailServer" "useTLS" ] [ "services" "ssmtp" "useTLS" ])
(mkRenamedOptionModule [ "networking" "defaultMailServer" "useSTARTTLS" ] [ "services" "ssmtp" "useSTARTTLS" ])
(mkRenamedOptionModule [ "networking" "defaultMailServer" "authUser" ] [ "services" "ssmtp" "authUser" ])
- (mkRenamedOptionModule [ "networking" "defaultMailServer" "authPass" ] [ "services" "ssmtp" "authPass" ])
(mkRenamedOptionModule [ "networking" "defaultMailServer" "authPassFile" ] [ "services" "ssmtp" "authPassFile" ])
(mkRenamedOptionModule [ "networking" "defaultMailServer" "setSendmail" ] [ "services" "ssmtp" "setSendmail" ])
+
+ (mkRemovedOptionModule [ "networking" "defaultMailServer" "authPass" ] "authPass has been removed since it leaks the clear-text password into the world-readable store. Use authPassFile instead and make sure it's not a store path")
+ (mkRemovedOptionModule [ "services" "ssmtp" "authPass" ] "authPass has been removed since it leaks the clear-text password into the world-readable store. Use authPassFile instead and make sure it's not a store path")
];
options = {
@@ -45,6 +47,21 @@ in
'';
};
+ settings = mkOption {
+ type = with types; attrsOf (oneOf [ bool str ]);
+ default = {};
+ description = ''
+ <citerefentry><refentrytitle>ssmtp</refentrytitle><manvolnum>5</manvolnum></citerefentry> configuration. Refer
+ to <link xlink:href="https://linux.die.net/man/5/ssmtp.conf"/> for details on supported values.
+ '';
+ example = literalExample ''
+ {
+ Debug = true;
+ FromLineOverride = false;
+ }
+ '';
+ };
+
hostName = mkOption {
type = types.str;
example = "mail.example.org";
@@ -101,18 +118,6 @@ in
'';
};
- authPass = mkOption {
- type = types.str;
- default = "";
- example = "correctHorseBatteryStaple";
- description = ''
- Password used for SMTP auth. (STORED PLAIN TEXT, WORLD-READABLE IN NIX STORE)
-
- It's recommended to use <option>authPassFile</option>
- which takes precedence over <option>authPass</option>.
- '';
- };
-
authPassFile = mkOption {
type = types.nullOr types.str;
default = null;
@@ -121,11 +126,6 @@ in
Path to a file that contains the password used for SMTP auth. The file
should not contain a trailing newline, if the password does not contain one.
This file should be readable by the users that need to execute ssmtp.
-
- <option>authPassFile</option> takes precedence over <option>authPass</option>.
-
- Warning: when <option>authPass</option> is non-empty <option>authPassFile</option>
- defaults to a file in the WORLD-READABLE Nix store containing that password.
'';
};
@@ -142,25 +142,28 @@ in
config = mkIf cfg.enable {
- services.ssmtp.authPassFile = mkIf (cfg.authPass != "")
- (mkDefault (toString (pkgs.writeTextFile {
- name = "ssmtp-authpass";
- text = cfg.authPass;
- })));
-
- environment.etc."ssmtp/ssmtp.conf".text =
- let yesNo = yes : if yes then "YES" else "NO"; in
- ''
- MailHub=${cfg.hostName}
- FromLineOverride=YES
- ${optionalString (cfg.root != "") "root=${cfg.root}"}
- ${optionalString (cfg.domain != "") "rewriteDomain=${cfg.domain}"}
- UseTLS=${yesNo cfg.useTLS}
- UseSTARTTLS=${yesNo cfg.useSTARTTLS}
- #Debug=YES
- ${optionalString (cfg.authUser != "") "AuthUser=${cfg.authUser}"}
- ${optionalString (cfg.authPassFile != null) "AuthPassFile=${cfg.authPassFile}"}
- '';
+ services.ssmtp.settings = mkMerge [
+ ({
+ MailHub = cfg.hostName;
+ FromLineOverride = mkDefault true;
+ UseTLS = cfg.useTLS;
+ UseSTARTTLS = cfg.useSTARTTLS;
+ })
+ (mkIf (cfg.root != "") { root = cfg.root; })
+ (mkIf (cfg.domain != "") { rewriteDomain = cfg.domain; })
+ (mkIf (cfg.authUser != "") { AuthUser = cfg.authUser; })
+ (mkIf (cfg.authPassFile != null) { AuthPassFile = cfg.authPassFile; })
+ ];
+
+ environment.etc."ssmtp/ssmtp.conf".source =
+ let
+ toStr = value:
+ if value == true then "YES"
+ else if value == false then "NO"
+ else builtins.toString value
+ ;
+ in
+ pkgs.writeText "ssmtp.conf" (concatStringsSep "\n" (mapAttrsToList (key: value: "${key}=${toStr value}") cfg.settings));
environment.systemPackages = [pkgs.ssmtp];
diff --git a/nixpkgs/nixos/modules/programs/steam.nix b/nixpkgs/nixos/modules/programs/steam.nix
new file mode 100644
index 00000000000..3c919c47a0c
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/steam.nix
@@ -0,0 +1,25 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.programs.steam;
+in {
+ options.programs.steam.enable = mkEnableOption "steam";
+
+ config = mkIf cfg.enable {
+ hardware.opengl = { # this fixes the "glXChooseVisual failed" bug, context: https://github.com/NixOS/nixpkgs/issues/47932
+ enable = true;
+ driSupport32Bit = true;
+ };
+
+ # optionally enable 32bit pulseaudio support if pulseaudio is enabled
+ hardware.pulseaudio.support32Bit = config.hardware.pulseaudio.enable;
+
+ hardware.steam-hardware.enable = true;
+
+ environment.systemPackages = [ pkgs.steam ];
+ };
+
+ meta.maintainers = with maintainers; [ mkg20001 ];
+}
diff --git a/nixpkgs/nixos/modules/rename.nix b/nixpkgs/nixos/modules/rename.nix
index c91febdb710..cfe216d512b 100644
--- a/nixpkgs/nixos/modules/rename.nix
+++ b/nixpkgs/nixos/modules/rename.nix
@@ -39,7 +39,7 @@ with lib;
The services.xserver.displayManager.auto module has been removed
because it was only intended for use in internal NixOS tests, and gave the
false impression of it being a special display manager when it's actually
- LightDM. Please use the services.xserver.displayManager.lightdm.autoLogin options
+ LightDM. Please use the services.xserver.displayManager.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")
@@ -55,6 +55,12 @@ with lib;
prey-bash-client is deprecated upstream
'')
+ (mkRemovedOptionModule ["hardware" "u2f" ] ''
+ The U2F modules module was removed, as all it did was adding the
+ udev rules from libu2f-host to the system. Udev gained native support
+ to handle FIDO security tokens, so this isn't necessary anymore.
+ '')
+
# 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 776ef07d716..1f63e7b88bd 100644
--- a/nixpkgs/nixos/modules/security/acme.nix
+++ b/nixpkgs/nixos/modules/security/acme.nix
@@ -23,16 +23,16 @@ let
type = types.nullOr types.str;
default = null;
description = ''
- ACME Directory Resource URI. Defaults to let's encrypt
+ ACME Directory Resource URI. Defaults to Let's Encrypt's
production endpoint,
- https://acme-v02.api.letsencrypt.org/directory, if unset.
+ <link xlink:href="https://acme-v02.api.letsencrypt.org/directory"/>, if unset.
'';
};
domain = mkOption {
type = types.str;
default = name;
- description = "Domain to fetch certificate for (defaults to the entry name)";
+ description = "Domain to fetch certificate for (defaults to the entry name).";
};
email = mkOption {
@@ -103,7 +103,7 @@ let
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.
+ at <link xlink:href="https://go-acme.github.io/lego/usage/cli/#usage"/>.
'';
};
@@ -113,7 +113,7 @@ let
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/.
+ field of the DNS providers listed at <link xlink:href="https://go-acme.github.io/lego/dns/"/>.
'';
};
@@ -123,7 +123,7 @@ let
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.
+ <link xlink:href="https://go-acme.github.io/lego/dns/"/> for the corresponding dnsProvider.
'';
example = "/var/src/secrets/example.org-route53-api-token";
};
@@ -169,7 +169,7 @@ in
(mkRemovedOptionModule [ "security" "acme" "production" ] ''
Use security.acme.server to define your staging ACME server URL instead.
- To use the let's encrypt staging server, use security.acme.server =
+ To use Let's Encrypt's staging server, use security.acme.server =
"https://acme-staging-v02.api.letsencrypt.org/directory".
''
)
@@ -207,9 +207,9 @@ in
type = types.nullOr types.str;
default = null;
description = ''
- ACME Directory Resource URI. Defaults to let's encrypt
+ ACME Directory Resource URI. Defaults to Let's Encrypt's
production endpoint,
- <literal>https://acme-v02.api.letsencrypt.org/directory</literal>, if unset.
+ <link xlink:href="https://acme-v02.api.letsencrypt.org/directory"/>, if unset.
'';
};
@@ -230,8 +230,8 @@ in
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/
+ Accept the CA's terms of service. The default provider is Let's Encrypt,
+ you can find their ToS at <link xlink:href="https://letsencrypt.org/repository/"/>.
'';
};
@@ -302,6 +302,11 @@ in
lpath = "acme/${cert}";
apath = "/var/lib/${lpath}";
spath = "/var/lib/acme/.lego/${cert}";
+ keyName = builtins.replaceStrings ["*"] ["_"] data.domain;
+ requestedDomains = pipe ([ data.domain ] ++ (attrNames data.extraDomains)) [
+ (domains: sort builtins.lessThan domains)
+ (domains: concatStringsSep "," domains)
+ ];
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" ]
@@ -316,6 +321,7 @@ in
certOpts ++ data.extraLegoRenewFlags);
acmeService = {
description = "Renew ACME Certificate for ${cert}";
+ path = with pkgs; [ openssl ];
after = [ "network.target" "network-online.target" ];
wants = [ "network-online.target" ];
wantedBy = mkIf (!config.boot.isContainer) [ "multi-user.target" ];
@@ -332,11 +338,18 @@ in
ExecStart = pkgs.writeScript "acme-start" ''
#!${pkgs.runtimeShell} -e
test -L ${spath}/accounts -o -d ${spath}/accounts || ln -s ../accounts ${spath}/accounts
- ${pkgs.lego}/bin/lego ${renewOpts} || ${pkgs.lego}/bin/lego ${runOpts}
+ LEGO_ARGS=(${runOpts})
+ if [ -e ${spath}/certificates/${keyName}.crt ]; then
+ REQUESTED_DOMAINS="${requestedDomains}"
+ EXISTING_DOMAINS="$(openssl x509 -in ${spath}/certificates/${keyName}.crt -noout -ext subjectAltName | tail -n1 | sed -e 's/ *DNS://g')"
+ if [ "''${REQUESTED_DOMAINS}" == "''${EXISTING_DOMAINS}" ]; then
+ LEGO_ARGS=(${renewOpts})
+ fi
+ fi
+ ${pkgs.lego}/bin/lego ''${LEGO_ARGS[@]}
'';
ExecStartPost =
let
- keyName = builtins.replaceStrings ["*"] ["_"] data.domain;
script = pkgs.writeScript "acme-post-start" ''
#!${pkgs.runtimeShell} -e
cd ${apath}
diff --git a/nixpkgs/nixos/modules/security/pam.nix b/nixpkgs/nixos/modules/security/pam.nix
index e1a94b0121a..565c15dec24 100644
--- a/nixpkgs/nixos/modules/security/pam.nix
+++ b/nixpkgs/nixos/modules/security/pam.nix
@@ -36,6 +36,17 @@ let
'';
};
+ p11Auth = mkOption {
+ default = config.security.pam.p11.enable;
+ type = types.bool;
+ description = ''
+ If set, keys listed in
+ <filename>~/.ssh/authorized_keys</filename> and
+ <filename>~/.eid/authorized_certificates</filename>
+ can be used to log in with the associated PKCS#11 tokens.
+ '';
+ };
+
u2fAuth = mkOption {
default = config.security.pam.u2f.enable;
type = types.bool;
@@ -352,6 +363,8 @@ let
"auth sufficient ${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so file=~/.ssh/authorized_keys:~/.ssh/authorized_keys2:/etc/ssh/authorized_keys.d/%u"}
${optionalString cfg.fprintAuth
"auth sufficient ${pkgs.fprintd}/lib/security/pam_fprintd.so"}
+ ${let p11 = config.security.pam.p11; in optionalString cfg.p11Auth
+ "auth ${p11.control} ${pkgs.pam_p11}/lib/security/pam_p11.so ${pkgs.opensc}/lib/opensc-pkcs11.so"}
${let u2f = config.security.pam.u2f; in optionalString cfg.u2fAuth
"auth ${u2f.control} ${pkgs.pam_u2f}/lib/security/pam_u2f.so ${optionalString u2f.debug "debug"} ${optionalString (u2f.authFile != null) "authfile=${u2f.authFile}"} ${optionalString u2f.interactive "interactive"} ${optionalString u2f.cue "cue"}"}
${optionalString cfg.usbAuth
@@ -436,6 +449,8 @@ let
"session required ${pkgs.pam}/lib/security/pam_lastlog.so silent"}
${optionalString config.security.pam.enableEcryptfs
"session optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"}
+ ${optionalString cfg.pamMount
+ "session optional ${pkgs.pam_mount}/lib/security/pam_mount.so"}
${optionalString use_ldap
"session optional ${pam_ldap}/lib/security/pam_ldap.so"}
${optionalString config.services.sssd.enable
@@ -452,8 +467,6 @@ let
"session required ${pkgs.pam}/lib/security/pam_limits.so conf=${makeLimitsConf cfg.limits}"}
${optionalString (cfg.showMotd && config.users.motd != null)
"session optional ${pkgs.pam}/lib/security/pam_motd.so motd=${motd}"}
- ${optionalString cfg.pamMount
- "session optional ${pkgs.pam_mount}/lib/security/pam_mount.so"}
${optionalString (cfg.enableAppArmor && config.security.apparmor.enable)
"session optional ${pkgs.apparmor-pam}/lib/security/pam_apparmor.so order=user,group,default debug"}
${optionalString (cfg.enableKwallet)
@@ -566,6 +579,39 @@ in
security.pam.enableOTPW = mkEnableOption "the OTPW (one-time password) PAM module";
+ security.pam.p11 = {
+ enable = mkOption {
+ default = false;
+ type = types.bool;
+ description = ''
+ Enables P11 PAM (<literal>pam_p11</literal>) module.
+
+ If set, users can log in with SSH keys and PKCS#11 tokens.
+
+ More information can be found <link
+ xlink:href="https://github.com/OpenSC/pam_p11">here</link>.
+ '';
+ };
+
+ control = mkOption {
+ default = "sufficient";
+ type = types.enum [ "required" "requisite" "sufficient" "optional" ];
+ description = ''
+ This option sets pam "control".
+ If you want to have multi factor authentication, use "required".
+ If you want to use the PKCS#11 device instead of the regular password,
+ use "sufficient".
+
+ Read
+ <citerefentry>
+ <refentrytitle>pam.conf</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </citerefentry>
+ for better understanding of this option.
+ '';
+ };
+ };
+
security.pam.u2f = {
enable = mkOption {
default = false;
@@ -747,6 +793,7 @@ in
++ optionals config.krb5.enable [pam_krb5 pam_ccreds]
++ optionals config.security.pam.enableOTPW [ pkgs.otpw ]
++ optionals config.security.pam.oath.enable [ pkgs.oathToolkit ]
+ ++ optionals config.security.pam.p11.enable [ pkgs.pam_p11 ]
++ optionals config.security.pam.u2f.enable [ pkgs.pam_u2f ];
boot.supportedFilesystems = optionals config.security.pam.enableEcryptfs [ "ecryptfs" ];
diff --git a/nixpkgs/nixos/modules/security/sudo.nix b/nixpkgs/nixos/modules/security/sudo.nix
index e3e43177def..1ed5269c5ae 100644
--- a/nixpkgs/nixos/modules/security/sudo.nix
+++ b/nixpkgs/nixos/modules/security/sudo.nix
@@ -173,7 +173,9 @@ in
config = mkIf cfg.enable {
- security.sudo.extraRules = [
+ # We `mkOrder 600` so that the default rule shows up first, but there is
+ # still enough room for a user to `mkBefore` it.
+ security.sudo.extraRules = mkOrder 600 [
{ groups = [ "wheel" ];
commands = [ { command = "ALL"; options = (if cfg.wheelNeedsPassword then [ "SETENV" ] else [ "NOPASSWD" "SETENV" ]); } ];
}
diff --git a/nixpkgs/nixos/modules/services/audio/mpd.nix b/nixpkgs/nixos/modules/services/audio/mpd.nix
index f4eb4a265a4..1d2a982ac53 100644
--- a/nixpkgs/nixos/modules/services/audio/mpd.nix
+++ b/nixpkgs/nixos/modules/services/audio/mpd.nix
@@ -21,6 +21,12 @@ let
${optionalString (cfg.network.listenAddress != "any") ''bind_to_address "${cfg.network.listenAddress}"''}
${optionalString (cfg.network.port != 6600) ''port "${toString cfg.network.port}"''}
+ ${optionalString (cfg.fluidsynth) ''
+ decoder {
+ plugin "fluidsynth"
+ soundfont "${pkgs.soundfont-fluid}/share/soundfonts/FluidR3_GM2-2.sf2"
+ }
+ ''}
${cfg.extraConfig}
'';
@@ -133,6 +139,14 @@ in {
parameter is omitted from the configuration.
'';
};
+
+ fluidsynth = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ If set, add fluidsynth soundfont and configure the plugin.
+ '';
+ };
};
};
diff --git a/nixpkgs/nixos/modules/services/audio/roon-server.nix b/nixpkgs/nixos/modules/services/audio/roon-server.nix
index 6aed485638c..eceb65044c5 100644
--- a/nixpkgs/nixos/modules/services/audio/roon-server.nix
+++ b/nixpkgs/nixos/modules/services/audio/roon-server.nix
@@ -45,14 +45,14 @@ in {
environment.ROON_DATAROOT = "/var/lib/${name}";
serviceConfig = {
- ExecStart = "${pkgs.roon-server}/opt/start.sh";
+ ExecStart = "${pkgs.roon-server}/start.sh";
LimitNOFILE = 8192;
User = cfg.user;
Group = cfg.group;
StateDirectory = name;
};
};
-
+
networking.firewall = mkIf cfg.openFirewall {
allowedTCPPortRanges = [
{ from = 9100; to = 9200; }
@@ -60,7 +60,7 @@ in {
allowedUDPPorts = [ 9003 ];
};
-
+
users.groups.${cfg.group} = {};
users.users.${cfg.user} =
if cfg.user == "roon-server" then {
diff --git a/nixpkgs/nixos/modules/services/audio/snapserver.nix b/nixpkgs/nixos/modules/services/audio/snapserver.nix
index b0b9264e816..f614f0ba3e1 100644
--- a/nixpkgs/nixos/modules/services/audio/snapserver.nix
+++ b/nixpkgs/nixos/modules/services/audio/snapserver.nix
@@ -31,27 +31,42 @@ let
let
os = val:
optionalString (val != null) "${val}";
- os' = prefixx: val:
- optionalString (val != null) (prefixx + "${val}");
+ os' = prefix: val:
+ optionalString (val != null) (prefix + "${val}");
flatten = key: value:
"&${key}=${value}";
in
- "-s ${opt.type}://" + os opt.location + "?" + os' "name=" name
- + concatStrings (mapAttrsToList flatten opt.query);
+ "--stream.stream=\"${opt.type}://" + os opt.location + "?" + os' "name=" name
+ + concatStrings (mapAttrsToList flatten opt.query) + "\"";
optionalNull = val: ret:
optional (val != null) ret;
optionString = concatStringsSep " " (mapAttrsToList streamToOption cfg.streams
- ++ ["-p ${toString cfg.port}"]
- ++ ["--controlPort ${toString cfg.controlPort}"]
- ++ optionalNull cfg.sampleFormat "--sampleFormat ${cfg.sampleFormat}"
- ++ optionalNull cfg.codec "-c ${cfg.codec}"
- ++ optionalNull cfg.streamBuffer "--streamBuffer ${cfg.streamBuffer}"
- ++ optionalNull cfg.buffer "-b ${cfg.buffer}"
- ++ optional cfg.sendToMuted "--sendToMuted");
+ # global options
+ ++ [ "--stream.bind_to_address ${cfg.listenAddress}" ]
+ ++ [ "--stream.port ${toString cfg.port}" ]
+ ++ optionalNull cfg.sampleFormat "--stream.sampleformat ${cfg.sampleFormat}"
+ ++ optionalNull cfg.codec "--stream.codec ${cfg.codec}"
+ ++ optionalNull cfg.streamBuffer "--stream.stream_buffer ${cfg.streamBuffer}"
+ ++ optionalNull cfg.buffer "--stream.buffer ${cfg.buffer}"
+ ++ optional cfg.sendToMuted "--stream.send_to_muted"
+ # tcp json rpc
+ ++ [ "--tcp.enabled ${toString cfg.tcp.enable}" ]
+ ++ optionals cfg.tcp.enable [
+ "--tcp.address ${cfg.tcp.listenAddress}"
+ "--tcp.port ${toString cfg.tcp.port}" ]
+ # http json rpc
+ ++ [ "--http.enabled ${toString cfg.http.enable}" ]
+ ++ optionals cfg.http.enable [
+ "--http.address ${cfg.http.listenAddress}"
+ "--http.port ${toString cfg.http.port}"
+ ] ++ optional (cfg.http.docRoot != null) "--http.doc_root \"${toString cfg.http.docRoot}\"");
in {
+ imports = [
+ (mkRenamedOptionModule [ "services" "snapserver" "controlPort"] [ "services" "snapserver" "tcp" "port" ])
+ ];
###### interface
@@ -67,6 +82,15 @@ in {
'';
};
+ listenAddress = mkOption {
+ type = types.str;
+ default = "::";
+ example = "0.0.0.0";
+ description = ''
+ The address where snapclients can connect.
+ '';
+ };
+
port = mkOption {
type = types.port;
default = 1704;
@@ -75,24 +99,100 @@ in {
'';
};
- controlPort = mkOption {
+ openFirewall = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether to automatically open the specified ports in the firewall.
+ '';
+ };
+
+ inherit sampleFormat;
+ inherit codec;
+
+ streamBuffer = mkOption {
+ type = with types; nullOr int;
+ default = null;
+ description = ''
+ Stream read (input) buffer in ms.
+ '';
+ example = 20;
+ };
+
+ buffer = mkOption {
+ type = with types; nullOr int;
+ default = null;
+ description = ''
+ Network buffer in ms.
+ '';
+ example = 1000;
+ };
+
+ sendToMuted = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Send audio to muted clients.
+ '';
+ };
+
+ tcp.enable = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether to enable the JSON-RPC via TCP.
+ '';
+ };
+
+ tcp.listenAddress = mkOption {
+ type = types.str;
+ default = "::";
+ example = "0.0.0.0";
+ description = ''
+ The address where the TCP JSON-RPC listens on.
+ '';
+ };
+
+ tcp.port = mkOption {
type = types.port;
default = 1705;
description = ''
- The port for control connections (JSON-RPC).
+ The port where the TCP JSON-RPC listens on.
'';
};
- openFirewall = mkOption {
+ http.enable = mkOption {
type = types.bool;
default = true;
description = ''
- Whether to automatically open the specified ports in the firewall.
+ Whether to enable the JSON-RPC via HTTP.
'';
};
- inherit sampleFormat;
- inherit codec;
+ http.listenAddress = mkOption {
+ type = types.str;
+ default = "::";
+ example = "0.0.0.0";
+ description = ''
+ The address where the HTTP JSON-RPC listens on.
+ '';
+ };
+
+ http.port = mkOption {
+ type = types.port;
+ default = 1780;
+ description = ''
+ The port where the HTTP JSON-RPC listens on.
+ '';
+ };
+
+ http.docRoot = mkOption {
+ type = with types; nullOr path;
+ default = null;
+ description = ''
+ Path to serve from the HTTP servers root.
+ '';
+ };
streams = mkOption {
type = with types; attrsOf (submodule {
@@ -147,34 +247,7 @@ in {
};
'';
};
-
- streamBuffer = mkOption {
- type = with types; nullOr int;
- default = null;
- description = ''
- Stream read (input) buffer in ms.
- '';
- example = 20;
- };
-
- buffer = mkOption {
- type = with types; nullOr int;
- default = null;
- description = ''
- Network buffer in ms.
- '';
- example = 1000;
- };
-
- sendToMuted = mkOption {
- type = types.bool;
- default = false;
- description = ''
- Send audio to muted clients.
- '';
- };
};
-
};
@@ -206,7 +279,10 @@ in {
};
};
- networking.firewall.allowedTCPPorts = optionals cfg.openFirewall [ cfg.port cfg.controlPort ];
+ networking.firewall.allowedTCPPorts =
+ optionals cfg.openFirewall [ cfg.port ]
+ ++ optional cfg.tcp.enable cfg.tcp.port
+ ++ optional cfg.http.enable cfg.http.port;
};
meta = {
diff --git a/nixpkgs/nixos/modules/services/audio/spotifyd.nix b/nixpkgs/nixos/modules/services/audio/spotifyd.nix
index 4b74e753279..a589153248f 100644
--- a/nixpkgs/nixos/modules/services/audio/spotifyd.nix
+++ b/nixpkgs/nixos/modules/services/audio/spotifyd.nix
@@ -16,7 +16,7 @@ in
type = types.lines;
description = ''
Configuration for Spotifyd. For syntax and directives, see
- https://github.com/Spotifyd/spotifyd#Configuration.
+ <link xlink:href="https://github.com/Spotifyd/spotifyd#Configuration"/>.
'';
};
};
diff --git a/nixpkgs/nixos/modules/services/backup/restic.nix b/nixpkgs/nixos/modules/services/backup/restic.nix
index 2388f1d6ca1..c38fd361d35 100644
--- a/nixpkgs/nixos/modules/services/backup/restic.nix
+++ b/nixpkgs/nixos/modules/services/backup/restic.nix
@@ -31,6 +31,59 @@ in
'';
};
+ rcloneOptions = mkOption {
+ type = with types; nullOr (attrsOf (oneOf [ str bool ]));
+ default = null;
+ description = ''
+ Options to pass to rclone to control its behavior.
+ See <link xlink:href="https://rclone.org/docs/#options"/> for
+ available options. When specifying option names, strip the
+ leading <literal>--</literal>. To set a flag such as
+ <literal>--drive-use-trash</literal>, which does not take a value,
+ set the value to the Boolean <literal>true</literal>.
+ '';
+ example = {
+ bwlimit = "10M";
+ drive-use-trash = "true";
+ };
+ };
+
+ rcloneConfig = mkOption {
+ type = with types; nullOr (attrsOf (oneOf [ str bool ]));
+ default = null;
+ description = ''
+ Configuration for the rclone remote being used for backup.
+ See the remote's specific options under rclone's docs at
+ <link xlink:href="https://rclone.org/docs/"/>. When specifying
+ option names, use the "config" name specified in the docs.
+ For example, to set <literal>--b2-hard-delete</literal> for a B2
+ remote, use <literal>hard_delete = true</literal> in the
+ attribute set.
+ Warning: Secrets set in here will be world-readable in the Nix
+ store! Consider using the <literal>rcloneConfigFile</literal>
+ option instead to specify secret values separately. Note that
+ options set here will override those set in the config file.
+ '';
+ example = {
+ type = "b2";
+ account = "xxx";
+ key = "xxx";
+ hard_delete = true;
+ };
+ };
+
+ rcloneConfigFile = mkOption {
+ type = with types; nullOr path;
+ default = null;
+ description = ''
+ Path to the file containing rclone configuration. This file
+ must contain configuration for the remote specified in this backup
+ set and also must be readable by root. Options set in
+ <literal>rcloneConfig</literal> will override those set in this
+ file.
+ '';
+ };
+
repository = mkOption {
type = types.str;
description = ''
@@ -170,11 +223,22 @@ in
( resticCmd + " forget --prune " + (concatStringsSep " " backup.pruneOpts) )
( resticCmd + " check" )
];
+ # Helper functions for rclone remotes
+ rcloneRemoteName = builtins.elemAt (splitString ":" backup.repository) 1;
+ rcloneAttrToOpt = v: "RCLONE_" + toUpper (builtins.replaceStrings [ "-" ] [ "_" ] v);
+ rcloneAttrToConf = v: "RCLONE_CONFIG_" + toUpper (rcloneRemoteName + "_" + v);
+ toRcloneVal = v: if lib.isBool v then lib.boolToString v else v;
in nameValuePair "restic-backups-${name}" ({
environment = {
RESTIC_PASSWORD_FILE = backup.passwordFile;
RESTIC_REPOSITORY = backup.repository;
- };
+ } // optionalAttrs (backup.rcloneOptions != null) (mapAttrs' (name: value:
+ nameValuePair (rcloneAttrToOpt name) (toRcloneVal value)
+ ) backup.rcloneOptions) // optionalAttrs (backup.rcloneConfigFile != null) {
+ RCLONE_CONFIG = backup.rcloneConfigFile;
+ } // optionalAttrs (backup.rcloneConfig != null) (mapAttrs' (name: value:
+ nameValuePair (rcloneAttrToConf name) (toRcloneVal value)
+ ) backup.rcloneConfig);
path = [ pkgs.openssh ];
restartIfChanged = false;
serviceConfig = {
diff --git a/nixpkgs/nixos/modules/services/backup/zfs-replication.nix b/nixpkgs/nixos/modules/services/backup/zfs-replication.nix
index 5a64304275d..6d75774c78f 100644
--- a/nixpkgs/nixos/modules/services/backup/zfs-replication.nix
+++ b/nixpkgs/nixos/modules/services/backup/zfs-replication.nix
@@ -18,7 +18,7 @@ in {
};
host = mkOption {
- description = "Remote host where snapshots should be sent.";
+ description = "Remote host where snapshots should be sent. <literal>lz4</literal> is expected to be installed on this host.";
example = "example.com";
type = types.str;
};
diff --git a/nixpkgs/nixos/modules/services/computing/slurm/slurm.nix b/nixpkgs/nixos/modules/services/computing/slurm/slurm.nix
index 050872e933f..705390a21d4 100644
--- a/nixpkgs/nixos/modules/services/computing/slurm/slurm.nix
+++ b/nixpkgs/nixos/modules/services/computing/slurm/slurm.nix
@@ -67,7 +67,7 @@ in
type = types.bool;
default = false;
description = ''
- Wether to enable the slurm control daemon.
+ Whether to enable the slurm control daemon.
Note that the standard authentication method is "munge".
The "munge" service needs to be provided with a password file in order for
slurm to work properly (see <literal>services.munge.password</literal>).
@@ -135,7 +135,7 @@ in
type = types.bool;
default = false;
description = ''
- Wether to provide a slurm.conf file.
+ Whether to provide a slurm.conf file.
Enable this option if you do not run a slurm daemon on this host
(i.e. <literal>server.enable</literal> and <literal>client.enable</literal> are <literal>false</literal>)
but you still want to run slurm commands from this host.
diff --git a/nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix b/nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix
index 0185f490b0c..e1950b91382 100644
--- a/nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix
+++ b/nixpkgs/nixos/modules/services/continuous-integration/buildbot/master.nix
@@ -25,7 +25,7 @@ let
change_source = [ ${concatStringsSep "," cfg.changeSource} ],
schedulers = [ ${concatStringsSep "," cfg.schedulers} ],
builders = [ ${concatStringsSep "," cfg.builders} ],
- status = [ ${concatStringsSep "," cfg.status} ],
+ services = [ ${concatStringsSep "," cfg.reporters} ],
)
for step in [ ${concatStringsSep "," cfg.factorySteps} ]:
factory.addStep(step)
@@ -119,10 +119,10 @@ in {
default = [ "worker.Worker('example-worker', 'pass')" ];
};
- status = mkOption {
+ reporters = mkOption {
default = [];
type = types.listOf types.str;
- description = "List of status notification endpoints.";
+ description = "List of reporter objects used to present build status to various users.";
};
user = mkOption {
@@ -276,6 +276,10 @@ in {
imports = [
(mkRenamedOptionModule [ "services" "buildbot-master" "bpPort" ] [ "services" "buildbot-master" "pbPort" ])
+ (mkRemovedOptionModule [ "services" "buildbot-master" "status" ] ''
+ Since Buildbot 0.9.0, status targets are deprecated and ignored.
+ Review your configuration and migrate to reporters (available at services.buildbot-master.reporters).
+ '')
];
meta.maintainers = with lib.maintainers; [ nand0p mic92 ];
diff --git a/nixpkgs/nixos/modules/services/continuous-integration/buildbot/worker.nix b/nixpkgs/nixos/modules/services/continuous-integration/buildbot/worker.nix
index 52f24b8cee3..7b8a35f54bf 100644
--- a/nixpkgs/nixos/modules/services/continuous-integration/buildbot/worker.nix
+++ b/nixpkgs/nixos/modules/services/continuous-integration/buildbot/worker.nix
@@ -29,7 +29,7 @@ let
with open('${cfg.workerPassFile}', 'r', encoding='utf-8') as passwd_file:
passwd = passwd_file.read().strip('\r\n')
- keepalive = 600
+ keepalive = ${toString cfg.keepalive}
umask = None
maxdelay = 300
numcpus = None
@@ -116,6 +116,15 @@ in {
description = "Specifies the Buildbot Worker connection string.";
};
+ keepalive = mkOption {
+ default = 600;
+ type = types.int;
+ description = "
+ This is a number that indicates how frequently keepalive messages should be sent
+ from the worker to the buildmaster, expressed in seconds.
+ ";
+ };
+
package = mkOption {
type = types.package;
default = pkgs.python3Packages.buildbot-worker;
diff --git a/nixpkgs/nixos/modules/services/continuous-integration/gitlab-runner.nix b/nixpkgs/nixos/modules/services/continuous-integration/gitlab-runner.nix
index eacfed85ddf..431555309cc 100644
--- a/nixpkgs/nixos/modules/services/continuous-integration/gitlab-runner.nix
+++ b/nixpkgs/nixos/modules/services/continuous-integration/gitlab-runner.nix
@@ -1,14 +1,16 @@
{ config, lib, pkgs, ... }:
+with builtins;
with lib;
let
cfg = config.services.gitlab-runner;
hasDocker = config.virtualisation.docker.enable;
- hashedServices = with builtins; (mapAttrs' (name: service: nameValuePair
- "${name}_${config.networking.hostName}_${
+ hashedServices = mapAttrs'
+ (name: service: nameValuePair
+ "${name}_${config.networking.hostName}_${
substring 0 12
(hashString "md5" (unsafeDiscardStringContext (toJSON service)))}"
service)
- cfg.services);
+ cfg.services;
configPath = "$HOME/.gitlab-runner/config.toml";
configureScript = pkgs.writeShellScriptBin "gitlab-runner-configure" (
if (cfg.configFile != null) then ''
@@ -47,6 +49,8 @@ let
] ++ service.registrationFlags
++ optional (service.buildsDir != null)
"--builds-dir ${service.buildsDir}"
+ ++ optional (service.cloneUrl != null)
+ "--clone-url ${service.cloneUrl}"
++ optional (service.preCloneScript != null)
"--pre-clone-script ${service.preCloneScript}"
++ optional (service.preBuildScript != null)
@@ -76,7 +80,7 @@ let
++ map (v: "--docker-allowed-images ${escapeShellArg v}") service.dockerAllowedImages
++ map (v: "--docker-allowed-services ${escapeShellArg v}") service.dockerAllowedServices
)
- ))} && sleep 1
+ ))} && sleep 1 || exit 1
fi
'') hashedServices)}
@@ -89,8 +93,17 @@ let
# update global options
remarshal --if toml --of json ${configPath} \
- | jq -cM '.check_interval = ${toString cfg.checkInterval} |
- .concurrent = ${toString cfg.concurrent}' \
+ | jq -cM ${escapeShellArg (concatStringsSep " | " [
+ ".check_interval = ${toJSON cfg.checkInterval}"
+ ".concurrent = ${toJSON cfg.concurrent}"
+ ".sentry_dsn = ${toJSON cfg.sentryDSN}"
+ ".listen_address = ${toJSON cfg.prometheusListenAddress}"
+ ".session_server.listen_address = ${toJSON cfg.sessionServer.listenAddress}"
+ ".session_server.advertise_address = ${toJSON cfg.sessionServer.advertiseAddress}"
+ ".session_server.session_timeout = ${toJSON cfg.sessionServer.sessionTimeout}"
+ "del(.[] | nulls)"
+ "del(.session_server[] | nulls)"
+ ])} \
| remarshal --if json --of toml \
| sponge ${configPath}
@@ -141,6 +154,66 @@ in
0 does not mean unlimited.
'';
};
+ sentryDSN = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "https://public:private@host:port/1";
+ description = ''
+ Data Source Name for tracking of all system level errors to Sentry.
+ '';
+ };
+ prometheusListenAddress = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "localhost:8080";
+ description = ''
+ Address (&lt;host&gt;:&lt;port&gt;) on which the Prometheus metrics HTTP server
+ should be listening.
+ '';
+ };
+ sessionServer = mkOption {
+ type = types.submodule {
+ options = {
+ listenAddress = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "0.0.0.0:8093";
+ description = ''
+ An internal URL to be used for the session server.
+ '';
+ };
+ advertiseAddress = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "runner-host-name.tld:8093";
+ description = ''
+ The URL that the Runner will expose to GitLab to be used
+ to access the session server.
+ Fallbacks to <option>listenAddress</option> if not defined.
+ '';
+ };
+ sessionTimeout = mkOption {
+ type = types.int;
+ default = 1800;
+ description = ''
+ How long in seconds the session can stay active after
+ the job completes (which will block the job from finishing).
+ '';
+ };
+ };
+ };
+ default = { };
+ example = literalExample ''
+ {
+ listenAddress = "0.0.0.0:8093";
+ }
+ '';
+ description = ''
+ The session server allows the user to interact with jobs
+ that the Runner is responsible for. A good example of this is the
+ <link xlink:href="https://docs.gitlab.com/ee/ci/interactive_web_terminal/index.html">interactive web terminal</link>.
+ '';
+ };
gracefulTermination = mkOption {
type = types.bool;
default = false;
@@ -306,6 +379,14 @@ in
in context of selected executor (Locally, Docker, SSH).
'';
};
+ cloneUrl = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "http://gitlab.example.local";
+ description = ''
+ Overwrite the URL for the GitLab instance. Used if the Runner can’t connect to GitLab on the URL GitLab exposes itself.
+ '';
+ };
dockerImage = mkOption {
type = types.nullOr types.str;
default = null;
diff --git a/nixpkgs/nixos/modules/services/databases/mysql.nix b/nixpkgs/nixos/modules/services/databases/mysql.nix
index 51885881cf7..2e8c5b7640b 100644
--- a/nixpkgs/nixos/modules/services/databases/mysql.nix
+++ b/nixpkgs/nixos/modules/services/databases/mysql.nix
@@ -334,7 +334,8 @@ in
environment.etc."my.cnf".source = cfg.configFile;
systemd.tmpfiles.rules = [
- "d '${cfg.dataDir}' 0700 ${cfg.user} mysql -"
+ "d '${cfg.dataDir}' 0700 ${cfg.user} mysql - -"
+ "z '${cfg.dataDir}' 0700 ${cfg.user} mysql - -"
];
systemd.services.mysql = let
@@ -357,21 +358,17 @@ in
preStart = if isMariaDB then ''
if ! test -e ${cfg.dataDir}/mysql; then
${mysql}/bin/mysql_install_db --defaults-file=/etc/my.cnf ${mysqldOptions}
- touch /tmp/mysql_init
+ touch ${cfg.dataDir}/mysql_init
fi
'' else ''
if ! test -e ${cfg.dataDir}/mysql; then
${mysql}/bin/mysqld --defaults-file=/etc/my.cnf ${mysqldOptions} --initialize-insecure
- touch /tmp/mysql_init
+ touch ${cfg.dataDir}/mysql_init
fi
'';
serviceConfig = {
- User = cfg.user;
- Group = "mysql";
Type = if hasNotify then "notify" else "simple";
- RuntimeDirectory = "mysqld";
- RuntimeDirectoryMode = "0755";
Restart = "on-abort";
RestartSec = "5s";
# The last two environment variables are used for starting Galera clusters
@@ -398,7 +395,7 @@ in
done
''}
- if [ -f /tmp/mysql_init ]
+ if [ -f ${cfg.dataDir}/mysql_init ]
then
${concatMapStrings (database: ''
# Create initial databases
@@ -452,7 +449,7 @@ in
cat ${toString cfg.initialScript} | ${mysql}/bin/mysql -u root -N
''}
- rm /tmp/mysql_init
+ rm ${cfg.dataDir}/mysql_init
fi
${optionalString (cfg.ensureDatabases != []) ''
@@ -476,6 +473,35 @@ in
# ensureDatbases & ensureUsers depends on this script being run as root
# when the user has secured their mysql install
"+${setupScript}";
+ # User and group
+ User = cfg.user;
+ Group = "mysql";
+ # Runtime directory and mode
+ RuntimeDirectory = "mysqld";
+ RuntimeDirectoryMode = "0755";
+ # Access write directories
+ ReadWritePaths = [ cfg.dataDir ];
+ # Capabilities
+ CapabilityBoundingSet = "";
+ # Security
+ NoNewPrivileges = true;
+ # Sandboxing
+ ProtectSystem = "strict";
+ ProtectHome = true;
+ PrivateTmp = true;
+ PrivateDevices = true;
+ ProtectHostname = true;
+ ProtectKernelTunables = true;
+ ProtectKernelModules = true;
+ ProtectControlGroups = true;
+ RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
+ LockPersonality = true;
+ MemoryDenyWriteExecute = true;
+ RestrictRealtime = true;
+ RestrictSUIDSGID = true;
+ PrivateMounts = true;
+ # System Call Filtering
+ SystemCallArchitectures = "native";
};
};
diff --git a/nixpkgs/nixos/modules/services/databases/openldap.nix b/nixpkgs/nixos/modules/services/databases/openldap.nix
index 8c2851c37ac..7472538b887 100644
--- a/nixpkgs/nixos/modules/services/databases/openldap.nix
+++ b/nixpkgs/nixos/modules/services/databases/openldap.nix
@@ -5,14 +5,14 @@ with lib;
let
cfg = config.services.openldap;
- openldap = pkgs.openldap;
+ openldap = cfg.package;
dataFile = pkgs.writeText "ldap-contents.ldif" cfg.declarativeContents;
configFile = pkgs.writeText "slapd.conf" ((optionalString cfg.defaultSchemas ''
- include ${pkgs.openldap.out}/etc/schema/core.schema
- include ${pkgs.openldap.out}/etc/schema/cosine.schema
- include ${pkgs.openldap.out}/etc/schema/inetorgperson.schema
- include ${pkgs.openldap.out}/etc/schema/nis.schema
+ include ${openldap.out}/etc/schema/core.schema
+ include ${openldap.out}/etc/schema/cosine.schema
+ include ${openldap.out}/etc/schema/inetorgperson.schema
+ include ${openldap.out}/etc/schema/nis.schema
'') + ''
${cfg.extraConfig}
database ${cfg.database}
@@ -46,6 +46,18 @@ in
";
};
+ package = mkOption {
+ type = types.package;
+ default = pkgs.openldap;
+ description = ''
+ OpenLDAP package to use.
+
+ This can be used to, for example, set an OpenLDAP package
+ with custom overrides to enable modules or other
+ functionality.
+ '';
+ };
+
user = mkOption {
type = types.str;
default = "openldap";
@@ -152,10 +164,10 @@ in
";
example = literalExample ''
'''
- include ${pkgs.openldap.out}/etc/schema/core.schema
- include ${pkgs.openldap.out}/etc/schema/cosine.schema
- include ${pkgs.openldap.out}/etc/schema/inetorgperson.schema
- include ${pkgs.openldap.out}/etc/schema/nis.schema
+ include ${openldap.out}/etc/schema/core.schema
+ include ${openldap.out}/etc/schema/cosine.schema
+ include ${openldap.out}/etc/schema/inetorgperson.schema
+ include ${openldap.out}/etc/schema/nis.schema
database bdb
suffix dc=example,dc=org
@@ -232,7 +244,7 @@ in
};
meta = {
- maintainers = lib.maintainers.mic92;
+ maintainers = [ lib.maintainers.mic92 ];
};
diff --git a/nixpkgs/nixos/modules/services/databases/redis.nix b/nixpkgs/nixos/modules/services/databases/redis.nix
index 799c3db6216..f1777854e14 100644
--- a/nixpkgs/nixos/modules/services/databases/redis.nix
+++ b/nixpkgs/nixos/modules/services/databases/redis.nix
@@ -218,6 +218,7 @@ in
description = "Redis database user";
isSystemUser = true;
};
+ users.groups.redis = {};
environment.systemPackages = [ cfg.package ];
@@ -240,6 +241,7 @@ in
StateDirectory = "redis";
Type = "notify";
User = "redis";
+ Group = "redis";
};
};
};
diff --git a/nixpkgs/nixos/modules/services/desktops/flatpak.nix b/nixpkgs/nixos/modules/services/desktops/flatpak.nix
index 7fb0024f37d..7da92cc9f26 100644
--- a/nixpkgs/nixos/modules/services/desktops/flatpak.nix
+++ b/nixpkgs/nixos/modules/services/desktops/flatpak.nix
@@ -42,6 +42,7 @@ in {
# It has been possible since https://github.com/flatpak/flatpak/releases/tag/1.3.2
# to build a SELinux policy module.
+ # TODO: use sysusers.d
users.users.flatpak = {
description = "Flatpak system helper";
group = "flatpak";
diff --git a/nixpkgs/nixos/modules/services/desktops/malcontent.nix b/nixpkgs/nixos/modules/services/desktops/malcontent.nix
index 5d6912595b5..1fbeb17e6ae 100644
--- a/nixpkgs/nixos/modules/services/desktops/malcontent.nix
+++ b/nixpkgs/nixos/modules/services/desktops/malcontent.nix
@@ -28,7 +28,10 @@ with lib;
malcontent-ui
];
- services.dbus.packages = [ pkgs.malcontent ];
+ services.dbus.packages = [
+ # D-Bus services are in `out`, not the default `bin` output that would be picked up by `makeDbusConf`.
+ pkgs.malcontent.out
+ ];
services.accounts-daemon.enable = true;
diff --git a/nixpkgs/nixos/modules/services/development/jupyter/default.nix b/nixpkgs/nixos/modules/services/development/jupyter/default.nix
index e598b018645..6a5fd6b2940 100644
--- a/nixpkgs/nixos/modules/services/development/jupyter/default.nix
+++ b/nixpkgs/nixos/modules/services/development/jupyter/default.nix
@@ -6,10 +6,7 @@ let
cfg = config.services.jupyter;
- # NOTE: We don't use top-level jupyter because we don't
- # want to pass in JUPYTER_PATH but use .environment instead,
- # saving a rebuild.
- package = pkgs.python3.pkgs.notebook;
+ package = cfg.package;
kernels = (pkgs.jupyter-kernel.create {
definitions = if cfg.kernels != null
@@ -37,6 +34,27 @@ in {
'';
};
+ package = mkOption {
+ type = types.package;
+ # NOTE: We don't use top-level jupyter because we don't
+ # want to pass in JUPYTER_PATH but use .environment instead,
+ # saving a rebuild.
+ default = pkgs.python3.pkgs.notebook;
+ description = ''
+ Jupyter package to use.
+ '';
+ };
+
+ command = mkOption {
+ type = types.str;
+ default = "jupyter-notebook";
+ example = "jupyter-lab";
+ description = ''
+ Which command the service runs. Note that not all jupyter packages
+ have all commands, e.g. jupyter-lab isn't present in the default package.
+ '';
+ };
+
port = mkOption {
type = types.int;
default = 8888;
@@ -157,7 +175,7 @@ in {
serviceConfig = {
Restart = "always";
- ExecStart = ''${package}/bin/jupyter-notebook \
+ ExecStart = ''${package}/bin/${cfg.command} \
--no-browser \
--ip=${cfg.ip} \
--port=${toString cfg.port} --port-retries 0 \
diff --git a/nixpkgs/nixos/modules/services/games/teeworlds.nix b/nixpkgs/nixos/modules/services/games/teeworlds.nix
new file mode 100644
index 00000000000..babf989c98c
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/games/teeworlds.nix
@@ -0,0 +1,119 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.teeworlds;
+ register = cfg.register;
+
+ teeworldsConf = pkgs.writeText "teeworlds.cfg" ''
+ sv_port ${toString cfg.port}
+ sv_register ${if cfg.register then "1" else "0"}
+ ${optionalString (cfg.name != null) "sv_name ${cfg.name}"}
+ ${optionalString (cfg.motd != null) "sv_motd ${cfg.motd}"}
+ ${optionalString (cfg.password != null) "password ${cfg.password}"}
+ ${optionalString (cfg.rconPassword != null) "sv_rcon_password ${cfg.rconPassword}"}
+ ${concatStringsSep "\n" cfg.extraOptions}
+ '';
+
+in
+{
+ options = {
+ services.teeworlds = {
+ enable = mkEnableOption "Teeworlds Server";
+
+ openPorts = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Whether to open firewall ports for Teeworlds";
+ };
+
+ name = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description = ''
+ Name of the server. Defaults to 'unnamed server'.
+ '';
+ };
+
+ register = mkOption {
+ type = types.bool;
+ example = true;
+ default = false;
+ description = ''
+ Whether the server registers as public server in the global server list. This is disabled by default because of privacy.
+ '';
+ };
+
+ motd = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description = ''
+ Set the server message of the day text.
+ '';
+ };
+
+ password = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description = ''
+ Password to connect to the server.
+ '';
+ };
+
+ rconPassword = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description = ''
+ Password to access the remote console. If not set, a randomly generated one is displayed in the server log.
+ '';
+ };
+
+ port = mkOption {
+ type = types.int;
+ default = 8303;
+ description = ''
+ Port the server will listen on.
+ '';
+ };
+
+ extraOptions = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ description = ''
+ Extra configuration lines for the <filename>teeworlds.cfg</filename>. See <link xlink:href="https://www.teeworlds.com/?page=docs&amp;wiki=server_settings">Teeworlds Documentation</link>.
+ '';
+ example = [ "sv_map dm1" "sv_gametype dm" ];
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ networking.firewall = mkIf cfg.openPorts {
+ allowedUDPPorts = [ cfg.port ];
+ };
+
+ systemd.services.teeworlds = {
+ description = "Teeworlds Server";
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network.target" ];
+
+ serviceConfig = {
+ DynamicUser = true;
+ ExecStart = "${pkgs.teeworlds}/bin/teeworlds_srv -f ${teeworldsConf}";
+
+ # Hardening
+ CapabilityBoundingSet = false;
+ PrivateDevices = true;
+ PrivateUsers = true;
+ ProtectHome = true;
+ ProtectKernelLogs = true;
+ ProtectKernelModules = true;
+ ProtectKernelTunables = true;
+ RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+ RestrictNamespaces = true;
+ SystemCallArchitectures = "native";
+ };
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/hardware/fwupd.nix b/nixpkgs/nixos/modules/services/hardware/fwupd.nix
index e586af25c2b..222ac8e487e 100644
--- a/nixpkgs/nixos/modules/services/hardware/fwupd.nix
+++ b/nixpkgs/nixos/modules/services/hardware/fwupd.nix
@@ -6,6 +6,23 @@ with lib;
let
cfg = config.services.fwupd;
+
+ customEtc = {
+ "fwupd/daemon.conf" = {
+ source = pkgs.writeText "daemon.conf" ''
+ [fwupd]
+ BlacklistDevices=${lib.concatStringsSep ";" cfg.blacklistDevices}
+ BlacklistPlugins=${lib.concatStringsSep ";" cfg.blacklistPlugins}
+ '';
+ };
+ "fwupd/uefi.conf" = {
+ source = pkgs.writeText "uefi.conf" ''
+ [uefi]
+ OverrideESPMountPoint=${config.boot.loader.efi.efiSysMountPoint}
+ '';
+ };
+ };
+
originalEtc =
let
mkEtcFile = n: nameValuePair n { source = "${cfg.package}/etc/${n}"; };
@@ -96,22 +113,8 @@ in {
environment.systemPackages = [ cfg.package ];
- environment.etc = {
- "fwupd/daemon.conf" = {
- source = pkgs.writeText "daemon.conf" ''
- [fwupd]
- BlacklistDevices=${lib.concatStringsSep ";" cfg.blacklistDevices}
- BlacklistPlugins=${lib.concatStringsSep ";" cfg.blacklistPlugins}
- '';
- };
- "fwupd/uefi.conf" = {
- source = pkgs.writeText "uefi.conf" ''
- [uefi]
- OverrideESPMountPoint=${config.boot.loader.efi.efiSysMountPoint}
- '';
- };
-
- } // originalEtc // extraTrustedKeys // testRemote;
+ # customEtc overrides some files from the package
+ environment.etc = originalEtc // customEtc // extraTrustedKeys // testRemote;
services.dbus.packages = [ cfg.package ];
diff --git a/nixpkgs/nixos/modules/services/hardware/tlp.nix b/nixpkgs/nixos/modules/services/hardware/tlp.nix
index 3962d7b1598..4230f2edd27 100644
--- a/nixpkgs/nixos/modules/services/hardware/tlp.nix
+++ b/nixpkgs/nixos/modules/services/hardware/tlp.nix
@@ -8,12 +8,8 @@ let
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);
+ if isList val then "\"" + (toString val) + "\""
+ else toString val;
} "=";
} tlpConfig;
in
@@ -27,10 +23,24 @@ in
description = "Whether to enable the TLP power management daemon.";
};
+ settings = mkOption {type = with types; attrsOf (oneOf [bool int float str (listOf str)]);
+ default = {};
+ example = {
+ SATA_LINKPWR_ON_BAT = "med_power_with_dipm";
+ USB_BLACKLIST_PHONE = 1;
+ };
+ description = ''
+ Options passed to TLP. See https://linrunner.de/tlp for all supported options..
+ '';
+ };
+
extraConfig = mkOption {
type = types.lines;
default = "";
- description = "Additional configuration variables for TLP";
+ description = ''
+ Verbatim additional configuration variables for TLP.
+ DEPRECATED: use services.tlp.config instead.
+ '';
};
};
};
@@ -39,8 +49,20 @@ in
config = mkIf cfg.enable {
boot.kernelModules = [ "msr" ];
+ warnings = optional (cfg.extraConfig != "") ''
+ Using config.services.tlp.extraConfig is deprecated and will become unsupported in a future release. Use config.services.tlp.settings instead.
+ '';
+
+ assertions = [{
+ assertion = cfg.enable -> config.powerManagement.scsiLinkPolicy == null;
+ message = ''
+ `services.tlp.enable` and `config.powerManagement.scsiLinkPolicy` cannot be set both.
+ Set `services.tlp.settings.SATA_LINKPWR_ON_AC` and `services.tlp.settings.SATA_LINKPWR_ON_BAT` instead.
+ '';
+ }];
+
environment.etc = {
- "tlp.conf".text = cfg.extraConfig;
+ "tlp.conf".text = (mkTlpConfig cfg.settings) + cfg.extraConfig;
} // optionalAttrs enableRDW {
"NetworkManager/dispatcher.d/99tlp-rdw-nm".source =
"${tlp}/etc/NetworkManager/dispatcher.d/99tlp-rdw-nm";
@@ -48,18 +70,25 @@ in
environment.systemPackages = [ tlp ];
- # 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;
+
+ services.tlp.settings = let
+ cfg = config.powerManagement;
+ maybeDefault = val: lib.mkIf (val != null) (lib.mkDefault val);
+ in {
+ CPU_SCALING_GOVERNOR_ON_AC = maybeDefault cfg.cpuFreqGovernor;
+ CPU_SCALING_GOVERNOR_ON_BAT = maybeDefault cfg.cpuFreqGovernor;
+ CPU_SCALING_MIN_FREQ_ON_AC = maybeDefault cfg.cpufreq.min;
+ CPU_SCALING_MAX_FREQ_ON_AC = maybeDefault cfg.cpufreq.max;
+ CPU_SCALING_MIN_FREQ_ON_BAT = maybeDefault cfg.cpufreq.min;
+ CPU_SCALING_MAX_FREQ_ON_BAT = maybeDefault cfg.cpufreq.max;
};
services.udev.packages = [ tlp ];
systemd = {
+ # use native tlp instead because it can also differentiate between AC/BAT
+ services.cpufreq.enable = false;
+
packages = [ tlp ];
# XXX: These must always be disabled/masked according to [1].
#
diff --git a/nixpkgs/nixos/modules/services/hardware/u2f.nix b/nixpkgs/nixos/modules/services/hardware/u2f.nix
deleted file mode 100644
index bb4b2f05f89..00000000000
--- a/nixpkgs/nixos/modules/services/hardware/u2f.nix
+++ /dev/null
@@ -1,23 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-let
- cfg = config.hardware.u2f;
-in {
- options = {
- hardware.u2f = {
- enable = mkOption {
- type = types.bool;
- default = false;
- description = ''
- Enable U2F hardware support.
- '';
- };
- };
- };
-
- config = mkIf cfg.enable {
- services.udev.packages = [ pkgs.libu2f-host ];
- };
-}
-
diff --git a/nixpkgs/nixos/modules/services/hardware/undervolt.nix b/nixpkgs/nixos/modules/services/hardware/undervolt.nix
index e5ef0601de3..828032dc573 100644
--- a/nixpkgs/nixos/modules/services/hardware/undervolt.nix
+++ b/nixpkgs/nixos/modules/services/hardware/undervolt.nix
@@ -1,18 +1,35 @@
{ config, pkgs, lib, ... }:
with lib;
-
let
cfg = config.services.undervolt;
-in {
+ cliArgs = lib.cli.toGNUCommandLineShell {} {
+ inherit (cfg)
+ verbose
+ temp
+ ;
+ # `core` and `cache` are both intentionally set to `cfg.coreOffset` as according to the undervolt docs:
+ #
+ # Core or Cache offsets have no effect. It is not possible to set different offsets for
+ # CPU Core and Cache. The CPU will take the smaller of the two offsets, and apply that to
+ # both CPU and Cache. A warning message will be displayed if you attempt to set different offsets.
+ core = cfg.coreOffset;
+ cache = cfg.coreOffset;
+ gpu = cfg.gpuOffset;
+ uncore = cfg.uncoreOffset;
+ analogio = cfg.analogioOffset;
+
+ temp-bat = cfg.tempBat;
+ temp-ac = cfg.tempAc;
+ };
+in
+{
options.services.undervolt = {
- enable = mkOption {
- type = types.bool;
- default = false;
- description = ''
- Whether to undervolt intel cpus.
- '';
- };
+ enable = mkEnableOption ''
+ Undervolting service for Intel CPUs.
+
+ Warning: This service is not endorsed by Intel and may permanently damage your hardware. Use at your own risk!
+ '';
verbose = mkOption {
type = types.bool;
@@ -32,58 +49,58 @@ in {
};
coreOffset = mkOption {
- type = types.nullOr types.str;
+ type = types.nullOr types.int;
default = null;
description = ''
- The amount of voltage to offset the CPU cores by. Accepts a floating point number.
+ The amount of voltage in mV to offset the CPU cores by.
'';
};
gpuOffset = mkOption {
- type = types.nullOr types.str;
+ type = types.nullOr types.int;
default = null;
description = ''
- The amount of voltage to offset the GPU by. Accepts a floating point number.
+ The amount of voltage in mV to offset the GPU by.
'';
};
uncoreOffset = mkOption {
- type = types.nullOr types.str;
+ type = types.nullOr types.int;
default = null;
description = ''
- The amount of voltage to offset uncore by. Accepts a floating point number.
+ The amount of voltage in mV to offset uncore by.
'';
};
analogioOffset = mkOption {
- type = types.nullOr types.str;
+ type = types.nullOr types.int;
default = null;
description = ''
- The amount of voltage to offset analogio by. Accepts a floating point number.
+ The amount of voltage in mV to offset analogio by.
'';
};
temp = mkOption {
- type = types.nullOr types.str;
+ type = types.nullOr types.int;
default = null;
description = ''
- The temperature target. Accepts a floating point number.
+ The temperature target in Celsius degrees.
'';
};
tempAc = mkOption {
- type = types.nullOr types.str;
+ type = types.nullOr types.int;
default = null;
description = ''
- The temperature target on AC power. Accepts a floating point number.
+ The temperature target on AC power in Celsius degrees.
'';
};
tempBat = mkOption {
- type = types.nullOr types.str;
+ type = types.nullOr types.int;
default = null;
description = ''
- The temperature target on battery power. Accepts a floating point number.
+ The temperature target on battery power in Celsius degrees.
'';
};
};
@@ -100,24 +117,7 @@ in {
serviceConfig = {
Type = "oneshot";
Restart = "no";
-
- # `core` and `cache` are both intentionally set to `cfg.coreOffset` as according to the undervolt docs:
- #
- # Core or Cache offsets have no effect. It is not possible to set different offsets for
- # CPU Core and Cache. The CPU will take the smaller of the two offsets, and apply that to
- # both CPU and Cache. A warning message will be displayed if you attempt to set different offsets.
- ExecStart = ''
- ${pkgs.undervolt}/bin/undervolt \
- ${optionalString cfg.verbose "--verbose"} \
- ${optionalString (cfg.coreOffset != null) "--core ${cfg.coreOffset}"} \
- ${optionalString (cfg.coreOffset != null) "--cache ${cfg.coreOffset}"} \
- ${optionalString (cfg.gpuOffset != null) "--gpu ${cfg.gpuOffset}"} \
- ${optionalString (cfg.uncoreOffset != null) "--uncore ${cfg.uncoreOffset}"} \
- ${optionalString (cfg.analogioOffset != null) "--analogio ${cfg.analogioOffset}"} \
- ${optionalString (cfg.temp != null) "--temp ${cfg.temp}"} \
- ${optionalString (cfg.tempAc != null) "--temp-ac ${cfg.tempAc}"} \
- ${optionalString (cfg.tempBat != null) "--temp-bat ${cfg.tempBat}"}
- '';
+ ExecStart = "${pkgs.undervolt}/bin/undervolt ${cliArgs}";
};
};
diff --git a/nixpkgs/nixos/modules/services/mail/dovecot.nix b/nixpkgs/nixos/modules/services/mail/dovecot.nix
index 9fbf0c19752..51cbcbf1cbc 100644
--- a/nixpkgs/nixos/modules/services/mail/dovecot.nix
+++ b/nixpkgs/nixos/modules/services/mail/dovecot.nix
@@ -125,6 +125,8 @@ let
mailboxConfig = mailbox: ''
mailbox "${mailbox.name}" {
auto = ${toString mailbox.auto}
+ '' + optionalString (mailbox.autoexpunge != null) ''
+ autoexpunge = ${mailbox.autoexpunge}
'' + optionalString (mailbox.specialUse != null) ''
special_use = \${toString mailbox.specialUse}
'' + "}";
@@ -132,8 +134,9 @@ let
mailboxes = { ... }: {
options = {
name = mkOption {
- type = types.strMatching ''[^"]+'';
+ type = types.nullOr (types.strMatching ''[^"]+'');
example = "Spam";
+ default = null;
description = "The name of the mailbox.";
};
auto = mkOption {
@@ -148,6 +151,15 @@ let
example = "Junk";
description = "Null if no special use flag is set. Other than that every use flag mentioned in the RFC is valid.";
};
+ autoexpunge = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "60d";
+ description = ''
+ To automatically remove all email from the mailbox which is older than the
+ specified time.
+ '';
+ };
};
};
in
@@ -323,9 +335,24 @@ in
};
mailboxes = mkOption {
- type = types.listOf (types.submodule mailboxes);
- default = [];
- example = [ { name = "Spam"; specialUse = "Junk"; auto = "create"; } ];
+ type = with types; let m = submodule mailboxes; in either (listOf m) (attrsOf m);
+ default = {};
+ apply = x:
+ if isList x then warn "Declaring `services.dovecot2.mailboxes' as a list is deprecated and will break eval in 21.03!" x
+ else mapAttrsToList (name: value:
+ if value.name != null
+ then throw ''
+ When specifying dovecot2 mailboxes as attributes, declaring
+ a `name'-attribute is prohibited! The name ${value.name} should
+ be the attribute key!
+ ''
+ else value // { inherit name; }
+ ) x;
+ example = literalExample ''
+ {
+ Spam = { specialUse = "Junk"; auto = "create"; };
+ }
+ '';
description = "Configure mailboxes and auto create or subscribe them.";
};
diff --git a/nixpkgs/nixos/modules/services/mail/mailman.nix b/nixpkgs/nixos/modules/services/mail/mailman.nix
index f5e78b18293..5c61cfbebf6 100644
--- a/nixpkgs/nixos/modules/services/mail/mailman.nix
+++ b/nixpkgs/nixos/modules/services/mail/mailman.nix
@@ -6,42 +6,46 @@ let
cfg = config.services.mailman;
+ pythonEnv = pkgs.python3.withPackages (ps:
+ [ps.mailman ps.mailman-web]
+ ++ lib.optional cfg.hyperkitty.enable ps.mailman-hyperkitty
+ ++ cfg.extraPythonPackages);
+
# This deliberately doesn't use recursiveUpdate so users can
# override the defaults.
- settings = {
+ webSettings = {
DEFAULT_FROM_EMAIL = cfg.siteOwner;
SERVER_EMAIL = cfg.siteOwner;
ALLOWED_HOSTS = [ "localhost" "127.0.0.1" ] ++ cfg.webHosts;
COMPRESS_OFFLINE = true;
- STATIC_ROOT = "/var/lib/mailman-web/static";
+ STATIC_ROOT = "/var/lib/mailman-web-static";
MEDIA_ROOT = "/var/lib/mailman-web/media";
+ LOGGING = {
+ version = 1;
+ disable_existing_loggers = true;
+ handlers.console.class = "logging.StreamHandler";
+ loggers.django = {
+ handlers = [ "console" ];
+ level = "INFO";
+ };
+ };
+ HAYSTACK_CONNECTIONS.default = {
+ ENGINE = "haystack.backends.whoosh_backend.WhooshEngine";
+ PATH = "/var/lib/mailman-web/fulltext-index";
+ };
} // cfg.webSettings;
- settingsJSON = pkgs.writeText "settings.json" (builtins.toJSON settings);
-
- mailmanCfg = ''
- [mailman]
- site_owner: ${cfg.siteOwner}
- layout: fhs
-
- [paths.fhs]
- bin_dir: ${pkgs.python3Packages.mailman}/bin
- var_dir: /var/lib/mailman
- queue_dir: $var_dir/queue
- template_dir: $var_dir/templates
- log_dir: $var_dir/log
- lock_dir: $var_dir/lock
- etc_dir: /etc
- ext_dir: $etc_dir/mailman.d
- pid_file: /run/mailman/master.pid
- '' + optionalString cfg.hyperkitty.enable ''
-
- [archiver.hyperkitty]
- class: mailman_hyperkitty.Archiver
- enable: yes
- configuration: /var/lib/mailman/mailman-hyperkitty.cfg
+ webSettingsJSON = pkgs.writeText "settings.json" (builtins.toJSON webSettings);
+
+ # TODO: Should this be RFC42-ised so that users can set additional options without modifying the module?
+ mtaConfig = pkgs.writeText "mailman-postfix.cfg" ''
+ [postfix]
+ postmap_command: ${pkgs.postfix}/bin/postmap
+ transport_file_type: hash
'';
+ mailmanCfg = lib.generators.toINI {} cfg.settings;
+
mailmanHyperkittyCfg = pkgs.writeText "mailman-hyperkitty.cfg" ''
[general]
# This is your HyperKitty installation, preferably on the localhost. This
@@ -84,7 +88,7 @@ in {
type = types.package;
default = pkgs.mailman;
defaultText = "pkgs.mailman";
- example = "pkgs.mailman.override { archivers = []; }";
+ example = literalExample "pkgs.mailman.override { archivers = []; }";
description = "Mailman package to use";
};
@@ -98,18 +102,6 @@ in {
'';
};
- webRoot = mkOption {
- type = types.path;
- default = "${pkgs.mailman-web}/${pkgs.python3.sitePackages}";
- defaultText = "\${pkgs.mailman-web}/\${pkgs.python3.sitePackages}";
- description = ''
- The web root for the Hyperkity + Postorius apps provided by Mailman.
- This variable can be set, of course, but it mainly exists so that site
- admins can refer to it in their own hand-written web server
- configuration files.
- '';
- };
-
webHosts = mkOption {
type = types.listOf types.str;
default = [];
@@ -124,7 +116,7 @@ in {
webUser = mkOption {
type = types.str;
- default = config.services.httpd.user;
+ default = "mailman-web";
description = ''
User to run mailman-web as
'';
@@ -138,6 +130,22 @@ in {
'';
};
+ serve = {
+ enable = mkEnableOption "Automatic nginx and uwsgi setup for mailman-web";
+ };
+
+ extraPythonPackages = mkOption {
+ description = "Packages to add to the python environment used by mailman and mailman-web";
+ type = types.listOf types.package;
+ default = [];
+ };
+
+ settings = mkOption {
+ description = "Settings for mailman.cfg";
+ type = types.attrsOf (types.attrsOf types.str);
+ default = {};
+ };
+
hyperkitty = {
enable = mkEnableOption "the Hyperkitty archiver for Mailman";
@@ -158,6 +166,35 @@ in {
config = mkIf cfg.enable {
+ services.mailman.settings = {
+ mailman.site_owner = lib.mkDefault cfg.siteOwner;
+ mailman.layout = "fhs";
+
+ "paths.fhs" = {
+ bin_dir = "${pkgs.python3Packages.mailman}/bin";
+ var_dir = "/var/lib/mailman";
+ queue_dir = "$var_dir/queue";
+ template_dir = "$var_dir/templates";
+ log_dir = "/var/log/mailman";
+ lock_dir = "$var_dir/lock";
+ etc_dir = "/etc";
+ ext_dir = "$etc_dir/mailman.d";
+ pid_file = "/run/mailman/master.pid";
+ };
+
+ mta.configuration = lib.mkDefault "${mtaConfig}";
+
+ "archiver.hyperkitty" = lib.mkIf cfg.hyperkitty.enable {
+ class = "mailman_hyperkitty.Archiver";
+ enable = "yes";
+ configuration = "/var/lib/mailman/mailman-hyperkitty.cfg";
+ };
+ } // (let
+ loggerNames = ["root" "archiver" "bounce" "config" "database" "debug" "error" "fromusenet" "http" "locks" "mischief" "plugins" "runner" "smtp"];
+ loggerSectionNames = map (n: "logging.${n}") loggerNames;
+ in lib.genAttrs loggerSectionNames(name: { handler = "stderr"; })
+ );
+
assertions = let
inherit (config.services) postfix;
@@ -183,7 +220,17 @@ in {
(requirePostfixHash [ "config" "local_recipient_maps" ] "postfix_lmtp")
];
- users.users.mailman = { description = "GNU Mailman"; isSystemUser = true; };
+ users.users.mailman = {
+ description = "GNU Mailman";
+ isSystemUser = true;
+ group = "mailman";
+ };
+ users.users.mailman-web = lib.mkIf (cfg.webUser == "mailman-web") {
+ description = "GNU Mailman web interface";
+ isSystemUser = true;
+ group = "mailman";
+ };
+ users.groups.mailman = {};
environment.etc."mailman.cfg".text = mailmanCfg;
@@ -198,197 +245,193 @@ in {
import json
- with open('${settingsJSON}') as f:
+ with open('${webSettingsJSON}') as f:
globals().update(json.load(f))
with open('/var/lib/mailman-web/settings_local.json') as f:
globals().update(json.load(f))
'';
- environment.systemPackages = [ cfg.package ] ++ (with pkgs; [ mailman-web ]);
-
- services.postfix = {
- recipientDelimiter = "+"; # bake recipient addresses in mail envelopes via VERP
- config = {
- owner_request_special = "no"; # Mailman handles -owner addresses on its own
- };
- };
-
- systemd.services.mailman = {
- description = "GNU Mailman Master Process";
- after = [ "network.target" ];
- restartTriggers = [ config.environment.etc."mailman.cfg".source ];
- wantedBy = [ "multi-user.target" ];
- serviceConfig = {
- ExecStart = "${cfg.package}/bin/mailman start";
- ExecStop = "${cfg.package}/bin/mailman stop";
- User = "mailman";
- Type = "forking";
- RuntimeDirectory = "mailman";
- PIDFile = "/run/mailman/master.pid";
- };
- };
-
- systemd.services.mailman-settings = {
- description = "Generate settings files (including secrets) for Mailman";
- before = [ "mailman.service" "mailman-web.service" "hyperkitty.service" "httpd.service" "uwsgi.service" ];
- requiredBy = [ "mailman.service" "mailman-web.service" "hyperkitty.service" "httpd.service" "uwsgi.service" ];
- path = with pkgs; [ jq ];
- script = ''
- mailmanDir=/var/lib/mailman
- mailmanWebDir=/var/lib/mailman-web
-
- mailmanCfg=$mailmanDir/mailman-hyperkitty.cfg
- mailmanWebCfg=$mailmanWebDir/settings_local.json
-
- install -m 0700 -o mailman -g nogroup -d $mailmanDir
- install -m 0700 -o ${cfg.webUser} -g nogroup -d $mailmanWebDir
-
- if [ ! -e $mailmanWebCfg ]; then
- hyperkittyApiKey=$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64)
- secretKey=$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64)
-
- mailmanWebCfgTmp=$(mktemp)
- jq -n '.MAILMAN_ARCHIVER_KEY=$archiver_key | .SECRET_KEY=$secret_key' \
- --arg archiver_key "$hyperkittyApiKey" \
- --arg secret_key "$secretKey" \
- >"$mailmanWebCfgTmp"
- chown ${cfg.webUser} "$mailmanWebCfgTmp"
- mv -n "$mailmanWebCfgTmp" $mailmanWebCfg
- fi
-
- hyperkittyApiKey="$(jq -r .MAILMAN_ARCHIVER_KEY $mailmanWebCfg)"
- mailmanCfgTmp=$(mktemp)
- sed "s/@API_KEY@/$hyperkittyApiKey/g" ${mailmanHyperkittyCfg} >"$mailmanCfgTmp"
- chown mailman "$mailmanCfgTmp"
- mv "$mailmanCfgTmp" $mailmanCfg
- '';
- 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";
+ services.nginx = mkIf cfg.serve.enable {
+ enable = mkDefault true;
+ virtualHosts."${lib.head cfg.webHosts}" = {
+ serverAliases = cfg.webHosts;
+ locations = {
+ "/".extraConfig = "uwsgi_pass unix:/run/mailman-web.socket;";
+ "/static/".alias = webSettings.STATIC_ROOT + "/";
+ };
};
};
- systemd.services.mailman-web = {
- description = "Init Postorius DB";
- before = [ "httpd.service" "uwsgi.service" ];
- requiredBy = [ "httpd.service" "uwsgi.service" ];
- restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
- script = ''
- ${pkgs.mailman-web}/bin/mailman-web migrate
- rm -rf static
- ${pkgs.mailman-web}/bin/mailman-web collectstatic
- ${pkgs.mailman-web}/bin/mailman-web compress
+ environment.systemPackages = [ (pkgs.buildEnv {
+ name = "mailman-tools";
+ # We don't want to pollute the system PATH with a python
+ # interpreter etc. so let's pick only the stuff we actually
+ # want from pythonEnv
+ pathsToLink = ["/bin"];
+ paths = [pythonEnv];
+ postBuild = ''
+ find $out/bin/ -mindepth 1 -not -name "mailman*" -delete
'';
- 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";
- };
- };
+ }) ];
- systemd.services.mailman-daily = {
- description = "Trigger daily Mailman events";
- startAt = "daily";
- restartTriggers = [ config.environment.etc."mailman.cfg".source ];
- serviceConfig = {
- ExecStart = "${cfg.package}/bin/mailman digests --send";
- User = "mailman";
- };
- };
-
- systemd.services.hyperkitty = {
- inherit (cfg.hyperkitty) enable;
- description = "GNU Hyperkitty QCluster Process";
- after = [ "network.target" ];
- restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
- wantedBy = [ "mailman.service" "multi-user.target" ];
- serviceConfig = {
- ExecStart = "${pkgs.mailman-web}/bin/mailman-web qcluster";
- User = cfg.webUser;
- WorkingDirectory = "/var/lib/mailman-web";
+ services.postfix = {
+ recipientDelimiter = "+"; # bake recipient addresses in mail envelopes via VERP
+ config = {
+ owner_request_special = "no"; # Mailman handles -owner addresses on its own
};
};
- systemd.services.hyperkitty-minutely = {
- inherit (cfg.hyperkitty) enable;
- description = "Trigger minutely Hyperkitty events";
- startAt = "minutely";
- restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
- serviceConfig = {
- ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs minutely";
- User = cfg.webUser;
- WorkingDirectory = "/var/lib/mailman-web";
- };
+ systemd.sockets.mailman-uwsgi = lib.mkIf cfg.serve.enable {
+ wantedBy = ["sockets.target"];
+ before = ["nginx.service"];
+ socketConfig.ListenStream = "/run/mailman-web.socket";
};
-
- systemd.services.hyperkitty-quarter-hourly = {
- inherit (cfg.hyperkitty) enable;
- description = "Trigger quarter-hourly Hyperkitty events";
- startAt = "*:00/15";
- restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
- serviceConfig = {
- ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs quarter_hourly";
- User = cfg.webUser;
- WorkingDirectory = "/var/lib/mailman-web";
+ systemd.services = {
+ mailman = {
+ description = "GNU Mailman Master Process";
+ after = [ "network.target" ];
+ restartTriggers = [ config.environment.etc."mailman.cfg".source ];
+ wantedBy = [ "multi-user.target" ];
+ serviceConfig = {
+ ExecStart = "${pythonEnv}/bin/mailman start";
+ ExecStop = "${pythonEnv}/bin/mailman stop";
+ User = "mailman";
+ Group = "mailman";
+ Type = "forking";
+ RuntimeDirectory = "mailman";
+ LogsDirectory = "mailman";
+ PIDFile = "/run/mailman/master.pid";
+ };
};
- };
- systemd.services.hyperkitty-hourly = {
- inherit (cfg.hyperkitty) enable;
- description = "Trigger hourly Hyperkitty events";
- startAt = "hourly";
- restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
- serviceConfig = {
- ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs hourly";
- User = cfg.webUser;
- WorkingDirectory = "/var/lib/mailman-web";
+ mailman-settings = {
+ description = "Generate settings files (including secrets) for Mailman";
+ before = [ "mailman.service" "mailman-web-setup.service" "mailman-uwsgi.service" "hyperkitty.service" ];
+ requiredBy = [ "mailman.service" "mailman-web-setup.service" "mailman-uwsgi.service" "hyperkitty.service" ];
+ path = with pkgs; [ jq ];
+ script = ''
+ mailmanDir=/var/lib/mailman
+ mailmanWebDir=/var/lib/mailman-web
+
+ mailmanCfg=$mailmanDir/mailman-hyperkitty.cfg
+ mailmanWebCfg=$mailmanWebDir/settings_local.json
+
+ install -m 0775 -o mailman -g mailman -d /var/lib/mailman-web-static
+ install -m 0770 -o mailman -g mailman -d $mailmanDir
+ install -m 0770 -o ${cfg.webUser} -g mailman -d $mailmanWebDir
+
+ if [ ! -e $mailmanWebCfg ]; then
+ hyperkittyApiKey=$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64)
+ secretKey=$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64)
+
+ mailmanWebCfgTmp=$(mktemp)
+ jq -n '.MAILMAN_ARCHIVER_KEY=$archiver_key | .SECRET_KEY=$secret_key' \
+ --arg archiver_key "$hyperkittyApiKey" \
+ --arg secret_key "$secretKey" \
+ >"$mailmanWebCfgTmp"
+ chown root:mailman "$mailmanWebCfgTmp"
+ chmod 440 "$mailmanWebCfgTmp"
+ mv -n "$mailmanWebCfgTmp" "$mailmanWebCfg"
+ fi
+
+ hyperkittyApiKey="$(jq -r .MAILMAN_ARCHIVER_KEY "$mailmanWebCfg")"
+ mailmanCfgTmp=$(mktemp)
+ sed "s/@API_KEY@/$hyperkittyApiKey/g" ${mailmanHyperkittyCfg} >"$mailmanCfgTmp"
+ chown mailman:mailman "$mailmanCfgTmp"
+ mv "$mailmanCfgTmp" "$mailmanCfg"
+ '';
};
- };
- systemd.services.hyperkitty-daily = {
- inherit (cfg.hyperkitty) enable;
- description = "Trigger daily Hyperkitty events";
- startAt = "daily";
- restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
- serviceConfig = {
- ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs daily";
- User = cfg.webUser;
- WorkingDirectory = "/var/lib/mailman-web";
+ mailman-web-setup = {
+ description = "Prepare mailman-web files and database";
+ before = [ "uwsgi.service" "mailman-uwsgi.service" ];
+ requiredBy = [ "mailman-uwsgi.service" ];
+ restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
+ script = ''
+ [[ -e "${webSettings.STATIC_ROOT}" ]] && find "${webSettings.STATIC_ROOT}/" -mindepth 1 -delete
+ ${pythonEnv}/bin/mailman-web migrate
+ ${pythonEnv}/bin/mailman-web collectstatic
+ ${pythonEnv}/bin/mailman-web compress
+ '';
+ serviceConfig = {
+ User = cfg.webUser;
+ Group = "mailman";
+ Type = "oneshot";
+ WorkingDirectory = "/var/lib/mailman-web";
+ };
};
- };
- systemd.services.hyperkitty-weekly = {
- inherit (cfg.hyperkitty) enable;
- description = "Trigger weekly Hyperkitty events";
- startAt = "weekly";
- restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
- serviceConfig = {
- ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs weekly";
- User = cfg.webUser;
- WorkingDirectory = "/var/lib/mailman-web";
+ mailman-uwsgi = mkIf cfg.serve.enable (let
+ uwsgiConfig.uwsgi = {
+ type = "normal";
+ plugins = ["python3"];
+ home = pythonEnv;
+ module = "mailman_web.wsgi";
+ };
+ uwsgiConfigFile = pkgs.writeText "uwsgi-mailman.json" (builtins.toJSON uwsgiConfig);
+ in {
+ wantedBy = ["multi-user.target"];
+ requires = ["mailman-uwsgi.socket" "mailman-web-setup.service"];
+ restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
+ serviceConfig = {
+ # Since the mailman-web settings.py obstinately creates a logs
+ # dir in the cwd, change to the (writable) runtime directory before
+ # starting uwsgi.
+ ExecStart = "${pkgs.coreutils}/bin/env -C $RUNTIME_DIRECTORY ${pkgs.uwsgi.override { plugins = ["python3"]; }}/bin/uwsgi --json ${uwsgiConfigFile}";
+ User = cfg.webUser;
+ Group = "mailman";
+ RuntimeDirectory = "mailman-uwsgi";
+ };
+ });
+
+ mailman-daily = {
+ description = "Trigger daily Mailman events";
+ startAt = "daily";
+ restartTriggers = [ config.environment.etc."mailman.cfg".source ];
+ serviceConfig = {
+ ExecStart = "${pythonEnv}/bin/mailman digests --send";
+ User = "mailman";
+ Group = "mailman";
+ };
};
- };
- systemd.services.hyperkitty-yearly = {
- inherit (cfg.hyperkitty) enable;
- description = "Trigger yearly Hyperkitty events";
- startAt = "yearly";
- restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
- serviceConfig = {
- ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs yearly";
- User = cfg.webUser;
- WorkingDirectory = "/var/lib/mailman-web";
+ hyperkitty = lib.mkIf cfg.hyperkitty.enable {
+ description = "GNU Hyperkitty QCluster Process";
+ after = [ "network.target" ];
+ restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
+ wantedBy = [ "mailman.service" "multi-user.target" ];
+ serviceConfig = {
+ ExecStart = "${pythonEnv}/bin/mailman-web qcluster";
+ User = cfg.webUser;
+ Group = "mailman";
+ WorkingDirectory = "/var/lib/mailman-web";
+ };
};
- };
+ } // flip lib.mapAttrs' {
+ "minutely" = "minutely";
+ "quarter_hourly" = "*:00/15";
+ "hourly" = "hourly";
+ "daily" = "daily";
+ "weekly" = "weekly";
+ "yearly" = "yearly";
+ } (name: startAt:
+ lib.nameValuePair "hyperkitty-${name}" (lib.mkIf cfg.hyperkitty.enable {
+ description = "Trigger ${name} Hyperkitty events";
+ inherit startAt;
+ restartTriggers = [ config.environment.etc."mailman3/settings.py".source ];
+ serviceConfig = {
+ ExecStart = "${pythonEnv}/bin/mailman-web runjobs minutely";
+ User = cfg.webUser;
+ Group = "mailman";
+ WorkingDirectory = "/var/lib/mailman-web";
+ };
+ }));
+ };
+ meta = {
+ maintainers = with lib.maintainers; [ lheckemann ];
+ doc = ./mailman.xml;
};
}
diff --git a/nixpkgs/nixos/modules/services/mail/mailman.xml b/nixpkgs/nixos/modules/services/mail/mailman.xml
new file mode 100644
index 00000000000..cbe50ed0b91
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/mail/mailman.xml
@@ -0,0 +1,59 @@
+<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-mailman">
+ <title>Mailman</title>
+ <para>
+ <link xlink:href="https://www.list.org">Mailman</link> is free
+ software for managing electronic mail discussion and e-newsletter
+ lists. Mailman and its web interface can be configured using the
+ corresponding NixOS module. Note that this service is best used with
+ an existing, securely configured Postfix setup, as it does not automatically configure this.
+ </para>
+
+ <section xml:id="module-services-mailman-basic-usage">
+ <title>Basic usage</title>
+ <para>
+ For a basic configuration, the following settings are suggested:
+ <programlisting>{ config, ... }: {
+ services.postfix = {
+ enable = true;
+ relayDomains = ["hash:/var/lib/mailman/data/postfix_domains"];
+ sslCert = config.security.acme.certs."lists.example.org".directory + "/full.pem";
+ sslKey = config.security.acme.certs."lists.example.org".directory + "/key.pem";
+ config = {
+ transport_maps = ["hash:/var/lib/mailman/data/postfix_lmtp"];
+ local_recipient_maps = ["hash:/var/lib/mailman/data/postfix_lmtp"];
+ };
+ };
+ services.mailman = {
+ <link linkend="opt-services.mailman.enable">enable</link> = true;
+ <link linkend="opt-services.mailman.serve.enable">serve.enable</link> = true;
+ <link linkend="opt-services.mailman.hyperkitty.enable">hyperkitty.enable</link> = true;
+ <link linkend="opt-services.mailman.hyperkitty.enable">webHosts</link> = ["lists.example.org"];
+ <link linkend="opt-services.mailman.hyperkitty.enable">siteOwner</link> = "mailman@example.org";
+ };
+ <link linkend="opt-services.nginx.virtualHosts._name_.enableACME">services.nginx.virtualHosts."lists.example.org".enableACME</link> = true;
+ <link linkend="opt-services.mailman.hyperkitty.enable">networking.firewall.allowedTCPPorts</link> = [ 25 80 443 ];
+}</programlisting>
+ </para>
+ <para>
+ DNS records will also be required:
+ <itemizedlist>
+ <listitem><para><literal>AAAA</literal> and <literal>A</literal> records pointing to the host in question, in order for browsers to be able to discover the address of the web server;</para></listitem>
+ <listitem><para>An <literal>MX</literal> record pointing to a domain name at which the host is reachable, in order for other mail servers to be able to deliver emails to the mailing lists it hosts.</para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ After this has been done and appropriate DNS records have been
+ set up, the Postorius mailing list manager and the Hyperkitty
+ archive browser will be available at
+ https://lists.example.org/. Note that this setup is not
+ sufficient to deliver emails to most email providers nor to
+ avoid spam -- a number of additional measures for authenticating
+ incoming and outgoing mails, such as SPF, DMARC and DKIM are
+ necessary, but outside the scope of the Mailman module.
+ </para>
+ </section>
+</chapter>
diff --git a/nixpkgs/nixos/modules/services/mail/opensmtpd.nix b/nixpkgs/nixos/modules/services/mail/opensmtpd.nix
index 1fabe2da45c..c838d3b949d 100644
--- a/nixpkgs/nixos/modules/services/mail/opensmtpd.nix
+++ b/nixpkgs/nixos/modules/services/mail/opensmtpd.nix
@@ -17,6 +17,10 @@ in {
###### interface
+ imports = [
+ (mkRenamedOptionModule [ "services" "opensmtpd" "addSendmailToSystemPath" ] [ "services" "opensmtpd" "setSendmail" ])
+ ];
+
options = {
services.opensmtpd = {
@@ -34,13 +38,10 @@ in {
description = "The OpenSMTPD package to use.";
};
- addSendmailToSystemPath = mkOption {
+ setSendmail = mkOption {
type = types.bool;
default = true;
- description = ''
- Whether to add OpenSMTPD's sendmail binary to the
- system path or not.
- '';
+ description = "Whether to set the system sendmail to OpenSMTPD's.";
};
extraServerArgs = mkOption {
@@ -82,7 +83,7 @@ in {
###### implementation
- config = mkIf cfg.enable {
+ config = mkIf cfg.enable rec {
users.groups = {
smtpd.gid = config.ids.gids.smtpd;
smtpq.gid = config.ids.gids.smtpq;
@@ -101,6 +102,14 @@ in {
};
};
+ security.wrappers.smtpctl = {
+ group = "smtpq";
+ setgid = true;
+ source = "${cfg.package}/bin/smtpctl";
+ };
+
+ services.mail.sendmailSetuidWrapper = mkIf cfg.setSendmail security.wrappers.smtpctl;
+
systemd.tmpfiles.rules = [
"d /var/spool/smtpd 711 root - - -"
"d /var/spool/smtpd/offline 770 root smtpq - -"
@@ -119,7 +128,5 @@ in {
serviceConfig.ExecStart = "${cfg.package}/sbin/smtpd -d -f ${conf} ${args}";
environment.OPENSMTPD_PROC_PATH = "${procEnv}/libexec/opensmtpd";
};
-
- environment.systemPackages = mkIf cfg.addSendmailToSystemPath [ sendmail ];
};
}
diff --git a/nixpkgs/nixos/modules/services/mail/postfix.nix b/nixpkgs/nixos/modules/services/mail/postfix.nix
index 608f64a68fb..ad10ba1d909 100644
--- a/nixpkgs/nixos/modules/services/mail/postfix.nix
+++ b/nixpkgs/nixos/modules/services/mail/postfix.nix
@@ -280,6 +280,17 @@ in
description = "Whether to enable smtp submission.";
};
+ enableSubmissions = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to enable smtp submission via smtps.
+
+ According to RFC 8314 this should be preferred
+ over STARTTLS for submission of messages by end user clients.
+ '';
+ };
+
submissionOptions = mkOption {
type = types.attrs;
default = {
@@ -298,6 +309,29 @@ in
description = "Options for the submission config in master.cf";
};
+ submissionsOptions = mkOption {
+ type = types.attrs;
+ default = {
+ smtpd_sasl_auth_enable = "yes";
+ smtpd_client_restrictions = "permit_sasl_authenticated,reject";
+ milter_macro_daemon_name = "ORIGINATING";
+ };
+ example = {
+ smtpd_sasl_auth_enable = "yes";
+ smtpd_sasl_type = "dovecot";
+ smtpd_client_restrictions = "permit_sasl_authenticated,reject";
+ milter_macro_daemon_name = "ORIGINATING";
+ };
+ description = ''
+ Options for the submission config via smtps in master.cf.
+
+ smtpd_tls_security_level will be set to encrypt, if it is missing
+ or has one of the values "may" or "none".
+
+ smtpd_tls_wrappermode with value "yes" will be added automatically.
+ '';
+ };
+
setSendmail = mkOption {
type = types.bool;
default = true;
@@ -454,7 +488,7 @@ in
'';
example = {
mail_owner = "postfix";
- smtp_use_tls = true;
+ smtp_tls_security_level = "may";
};
};
@@ -466,16 +500,18 @@ in
";
};
- sslCert = mkOption {
+ tlsTrustedAuthorities = mkOption {
type = types.str;
- default = "";
- description = "SSL certificate to use.";
+ default = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
+ description = ''
+ File containing trusted certification authorities (CA) to verify certificates of mailservers contacted for mail delivery. This basically sets smtp_tls_CAfile and enables opportunistic tls. Defaults to NixOS trusted certification authorities.
+ '';
};
- sslCACert = mkOption {
+ sslCert = mkOption {
type = types.str;
default = "";
- description = "SSL certificate of CA.";
+ description = "SSL certificate to use.";
};
sslKey = mkOption {
@@ -771,18 +807,20 @@ in
recipient_canonical_classes = [ "envelope_recipient" ];
}
// optionalAttrs cfg.enableHeaderChecks { header_checks = [ "regexp:/etc/postfix/header_checks" ]; }
+ // optionalAttrs (cfg.tlsTrustedAuthorities != "") {
+ smtp_tls_CAfile = cfg.tlsTrustedAuthorities;
+ smtp_tls_security_level = "may";
+ }
// optionalAttrs (cfg.sslCert != "") {
- smtp_tls_CAfile = cfg.sslCACert;
smtp_tls_cert_file = cfg.sslCert;
smtp_tls_key_file = cfg.sslKey;
- smtp_use_tls = true;
+ smtp_tls_security_level = "may";
- smtpd_tls_CAfile = cfg.sslCACert;
smtpd_tls_cert_file = cfg.sslCert;
smtpd_tls_key_file = cfg.sslKey;
- smtpd_use_tls = true;
+ smtpd_tls_security_level = "may";
};
services.postfix.masterConfig = {
@@ -878,6 +916,23 @@ in
command = "smtp";
args = [ "-o" "smtp_fallback_relay=" ];
};
+ } // optionalAttrs cfg.enableSubmissions {
+ submissions = {
+ type = "inet";
+ private = false;
+ command = "smtpd";
+ args = let
+ mkKeyVal = opt: val: [ "-o" (opt + "=" + val) ];
+ adjustSmtpTlsSecurityLevel = !(cfg.submissionsOptions ? smtpd_tls_security_level) ||
+ cfg.submissionsOptions.smtpd_tls_security_level == "none" ||
+ cfg.submissionsOptions.smtpd_tls_security_level == "may";
+ submissionsOptions = cfg.submissionsOptions // {
+ smtpd_tls_wrappermode = "yes";
+ } // optionalAttrs adjustSmtpTlsSecurityLevel {
+ smtpd_tls_security_level = "encrypt";
+ };
+ in concatLists (mapAttrsToList mkKeyVal submissionsOptions);
+ };
};
}
@@ -900,4 +955,9 @@ in
services.postfix.mapFiles.client_access = checkClientAccessFile;
})
]);
+
+ imports = [
+ (mkRemovedOptionModule [ "services" "postfix" "sslCACert" ]
+ "services.postfix.sslCACert was replaced by services.postfix.tlsTrustedAuthorities. In case you intend that your server should validate requested client certificates use services.postfix.extraConfig.")
+ ];
}
diff --git a/nixpkgs/nixos/modules/services/mail/roundcube.nix b/nixpkgs/nixos/modules/services/mail/roundcube.nix
index ed1439745ac..a0bbab64985 100644
--- a/nixpkgs/nixos/modules/services/mail/roundcube.nix
+++ b/nixpkgs/nixos/modules/services/mail/roundcube.nix
@@ -95,6 +95,18 @@ in
'';
};
+ maxAttachmentSize = mkOption {
+ type = types.int;
+ default = 18;
+ description = ''
+ The maximum attachment size in MB.
+
+ Note: Since roundcube only uses 70% of max upload values configured in php
+ 30% is added automatically to <xref linkend="opt-services.roundcube.maxAttachmentSize"/>.
+ '';
+ apply = configuredMaxAttachmentSize: "${toString (configuredMaxAttachmentSize * 1.3)}M";
+ };
+
extraConfig = mkOption {
type = types.lines;
default = "";
@@ -115,7 +127,7 @@ in
$config = array();
$config['db_dsnw'] = 'pgsql://${cfg.database.username}${lib.optionalString (!localDB) ":' . $password . '"}@${if localDB then "unix(/run/postgresql)" else cfg.database.host}/${cfg.database.dbname}';
$config['log_driver'] = 'syslog';
- $config['max_message_size'] = '25M';
+ $config['max_message_size'] = '${cfg.maxAttachmentSize}';
$config['plugins'] = [${concatMapStringsSep "," (p: "'${p}'") cfg.plugins}];
$config['des_key'] = file_get_contents('/var/lib/roundcube/des_key');
$config['mime_types'] = '${pkgs.nginx}/conf/mime.types';
@@ -172,8 +184,8 @@ in
phpOptions = ''
error_log = 'stderr'
log_errors = on
- post_max_size = 25M
- upload_max_filesize = 25M
+ post_max_size = ${cfg.maxAttachmentSize}
+ upload_max_filesize = ${cfg.maxAttachmentSize}
'';
settings = mapAttrs (name: mkDefault) {
"listen.owner" = "nginx";
diff --git a/nixpkgs/nixos/modules/services/misc/gitlab.nix b/nixpkgs/nixos/modules/services/misc/gitlab.nix
index 1ada131bd7b..be59b53e5ce 100644
--- a/nixpkgs/nixos/modules/services/misc/gitlab.nix
+++ b/nixpkgs/nixos/modules/services/misc/gitlab.nix
@@ -71,7 +71,7 @@ let
};
};
- redisConfig.production.url = "redis://localhost:6379/";
+ redisConfig.production.url = cfg.redisUrl;
gitlabConfig = {
# These are the default settings from config/gitlab.example.yml
@@ -311,6 +311,12 @@ in {
description = "Extra configuration in config/database.yml.";
};
+ redisUrl = mkOption {
+ type = types.str;
+ default = "redis://localhost:6379/";
+ description = "Redis URL for all GitLab services except gitlab-shell";
+ };
+
extraGitlabRb = mkOption {
type = types.str;
default = "";
@@ -704,7 +710,7 @@ in {
TimeoutSec = "infinity";
Restart = "on-failure";
WorkingDirectory = "${cfg.packages.gitlab}/share/gitlab";
- ExecStart="${cfg.packages.gitlab.rubyEnv}/bin/sidekiq -C \"${cfg.packages.gitlab}/share/gitlab/config/sidekiq_queues.yml\" -e production -P ${cfg.statePath}/tmp/sidekiq.pid";
+ ExecStart="${cfg.packages.gitlab.rubyEnv}/bin/sidekiq -C \"${cfg.packages.gitlab}/share/gitlab/config/sidekiq_queues.yml\" -e production";
};
};
diff --git a/nixpkgs/nixos/modules/services/misc/gitolite.nix b/nixpkgs/nixos/modules/services/misc/gitolite.nix
index cc69f81bbcc..59cbdac319c 100644
--- a/nixpkgs/nixos/modules/services/misc/gitolite.nix
+++ b/nixpkgs/nixos/modules/services/misc/gitolite.nix
@@ -27,7 +27,10 @@ in
type = types.str;
default = "/var/lib/gitolite";
description = ''
- Gitolite home directory (used to store all the repositories).
+ The gitolite home directory used to store all repositories. If left as the default value
+ this directory will automatically be created before the gitolite server starts, otherwise
+ the sysadmin is responsible for ensuring the directory exists with appropriate ownership
+ and permissions.
'';
};
@@ -149,14 +152,6 @@ in
};
users.groups.${cfg.group}.gid = config.ids.gids.gitolite;
- systemd.tmpfiles.rules = [
- "d '${cfg.dataDir}' 0750 ${cfg.user} ${cfg.group} - -"
- "d '${cfg.dataDir}'/.gitolite - ${cfg.user} ${cfg.group} - -"
- "d '${cfg.dataDir}'/.gitolite/logs - ${cfg.user} ${cfg.group} - -"
-
- "Z ${cfg.dataDir} 0750 ${cfg.user} ${cfg.group} - -"
- ];
-
systemd.services.gitolite-init = {
description = "Gitolite initialization";
wantedBy = [ "multi-user.target" ];
@@ -167,13 +162,19 @@ in
GITOLITE_RC_DEFAULT = "${rcDir}/gitolite.rc.default";
};
- serviceConfig = {
- Type = "oneshot";
- User = cfg.user;
- Group = cfg.group;
- WorkingDirectory = "~";
- RemainAfterExit = true;
- };
+ serviceConfig = mkMerge [
+ (mkIf (cfg.dataDir == "/var/lib/gitolite") {
+ StateDirectory = "gitolite gitolite/.gitolite gitolite/.gitolite/logs";
+ StateDirectoryMode = "0750";
+ })
+ {
+ Type = "oneshot";
+ User = cfg.user;
+ Group = cfg.group;
+ WorkingDirectory = "~";
+ RemainAfterExit = true;
+ }
+ ];
path = [ pkgs.gitolite pkgs.git pkgs.perl pkgs.bash pkgs.diffutils config.programs.ssh.package ];
script =
diff --git a/nixpkgs/nixos/modules/services/misc/home-assistant.nix b/nixpkgs/nixos/modules/services/misc/home-assistant.nix
index 8ce2437841b..0477254e7c1 100644
--- a/nixpkgs/nixos/modules/services/misc/home-assistant.nix
+++ b/nixpkgs/nixos/modules/services/misc/home-assistant.nix
@@ -240,6 +240,7 @@ in {
'');
serviceConfig = {
ExecStart = "${package}/bin/hass --config '${cfg.configDir}'";
+ ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
User = "hass";
Group = "hass";
Restart = "on-failure";
diff --git a/nixpkgs/nixos/modules/services/misc/matrix-synapse.nix b/nixpkgs/nixos/modules/services/misc/matrix-synapse.nix
index 703bc9416f8..e982eb16fa7 100644
--- a/nixpkgs/nixos/modules/services/misc/matrix-synapse.nix
+++ b/nixpkgs/nixos/modules/services/misc/matrix-synapse.nix
@@ -9,6 +9,9 @@ let
logConfigFile = pkgs.writeText "log_config.yaml" cfg.logConfig;
mkResource = r: ''{names: ${builtins.toJSON r.names}, compress: ${boolToString r.compress}}'';
mkListener = l: ''{port: ${toString l.port}, bind_address: "${l.bind_address}", type: ${l.type}, tls: ${boolToString l.tls}, x_forwarded: ${boolToString l.x_forwarded}, resources: [${concatStringsSep "," (map mkResource l.resources)}]}'';
+ pluginsEnv = cfg.package.python.buildEnv.override {
+ extraLibs = cfg.plugins;
+ };
configFile = pkgs.writeText "homeserver.yaml" ''
${optionalString (cfg.tls_certificate_path != null) ''
tls_certificate_path: "${cfg.tls_certificate_path}"
@@ -125,6 +128,14 @@ in {
Overridable attribute of the matrix synapse server package to use.
'';
};
+ plugins = mkOption {
+ type = types.listOf types.package;
+ default = [ ];
+ defaultText = "with config.services.matrix-synapse.package.plugins [ matrix-synapse-ldap3 matrix-synapse-pam ]";
+ description = ''
+ List of additional Matrix plugins to make available.
+ '';
+ };
no_tls = mkOption {
type = types.bool;
default = false;
@@ -686,6 +697,7 @@ in {
--keys-directory ${cfg.dataDir} \
--generate-keys
'';
+ environment.PYTHONPATH = makeSearchPathOutput "lib" cfg.package.python.sitePackages [ pluginsEnv ];
serviceConfig = {
Type = "notify";
User = "matrix-synapse";
@@ -715,5 +727,6 @@ in {
];
meta.doc = ./matrix-synapse.xml;
+ meta.maintainers = teams.matrix.members;
}
diff --git a/nixpkgs/nixos/modules/services/misc/matrix-synapse.xml b/nixpkgs/nixos/modules/services/misc/matrix-synapse.xml
index 2f2ac27eeb9..fbfa838b168 100644
--- a/nixpkgs/nixos/modules/services/misc/matrix-synapse.xml
+++ b/nixpkgs/nixos/modules/services/misc/matrix-synapse.xml
@@ -14,9 +14,9 @@
<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
+ copy of the Element 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,
+ Matrix Now!</link> overview page for links to Element Apps for Android and iOS,
desktop clients, as well as bridges to other networks and other projects
around Matrix.
</para>
@@ -84,7 +84,7 @@ in {
"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
+ # ACAO required to allow element-web on any URL to request this json file
in ''
add_header Content-Type application/json;
add_header Access-Control-Allow-Origin *;
@@ -98,7 +98,7 @@ in {
<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.
+ # But do not put a Matrix Web client here! See the Element web section below.
<link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.extraConfig">locations."/".extraConfig</link> = ''
return 404;
'';
@@ -171,17 +171,19 @@ Success!
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>
+ <section xml:id="module-services-matrix-element-web">
+ <title>Element (formerly known as Riot) Web Client</title>
<para>
- <link xlink:href="https://github.com/vector-im/riot-web/">Riot Web</link> is
+ <link xlink:href="https://github.com/vector-im/riot-web/">Element 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
+ matrix.org. Element was formerly known as Riot.im, see the
+ <link xlink:href="https://element.io/blog/welcome-to-element/">Element introductory blog post</link>
+ for more information. 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>,
+ <code>https://element.myhostname.example.org</code> and
+ <code>https://element.example.org</code>. Alternatively, you can use the hosted
+ copy at <link xlink:href="https://app.element.io/">https://app.element.io/</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
@@ -191,14 +193,14 @@ Success!
featureset.
<programlisting>
{
- services.nginx.virtualHosts."riot.${fqdn}" = {
+ services.nginx.virtualHosts."element.${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}"
+ "element.${config.networking.domain}"
];
- <link linkend="opt-services.nginx.virtualHosts._name_.root">root</link> = pkgs.riot-web.override {
+ <link linkend="opt-services.nginx.virtualHosts._name_.root">root</link> = pkgs.element-web.override {
conf = {
default_server_config."m.homeserver" = {
"base_url" = "${config.networking.domain}";
@@ -212,13 +214,13 @@ Success!
</para>
<para>
- Note that the Riot developers do not recommend running Riot and your Matrix
+ Note that the Element developers do not recommend running Element 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,
+ <literal>myhostname.example.org</literal> virtualHost to also serve Element,
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
+ <literal>element.example.org</literal> in the example. See the
+ <link xlink:href="https://github.com/vector-im/riot-web#important-security-note">Element
Important Security Notes</link> for more information on this subject.
</para>
</section>
diff --git a/nixpkgs/nixos/modules/services/misc/mautrix-telegram.nix b/nixpkgs/nixos/modules/services/misc/mautrix-telegram.nix
index 78a42fbb574..c5e8a5b85ec 100644
--- a/nixpkgs/nixos/modules/services/misc/mautrix-telegram.nix
+++ b/nixpkgs/nixos/modules/services/misc/mautrix-telegram.nix
@@ -125,7 +125,7 @@ in {
if [ ! -f '${registrationFile}' ]; then
${pkgs.mautrix-telegram}/bin/mautrix-telegram \
--generate-registration \
- --base-config='${pkgs.mautrix-telegram}/example-config.yaml' \
+ --base-config='${pkgs.mautrix-telegram}/${pkgs.mautrix-telegram.pythonModule.sitePackages}/mautrix_telegram/example-config.yaml' \
--config='${settingsFile}' \
--registration='${registrationFile}'
fi
diff --git a/nixpkgs/nixos/modules/services/misc/nix-daemon.nix b/nixpkgs/nixos/modules/services/misc/nix-daemon.nix
index 0b3d7f3f03c..924a007efc6 100644
--- a/nixpkgs/nixos/modules/services/misc/nix-daemon.nix
+++ b/nixpkgs/nixos/modules/services/misc/nix-daemon.nix
@@ -193,50 +193,111 @@ in
};
buildMachines = mkOption {
- type = types.listOf types.attrs;
+ type = types.listOf (types.submodule ({
+ options = {
+ hostName = mkOption {
+ type = types.str;
+ example = "nixbuilder.example.org";
+ description = ''
+ The hostname of the build machine.
+ '';
+ };
+ system = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "x86_64-linux";
+ description = ''
+ The system type the build machine can execute derivations on.
+ Either this attribute or <varname>systems</varname> must be
+ present, where <varname>system</varname> takes precedence if
+ both are set.
+ '';
+ };
+ systems = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ example = [ "x86_64-linux" "aarch64-linux" ];
+ description = ''
+ The system types the build machine can execute derivations on.
+ Either this attribute or <varname>system</varname> must be
+ present, where <varname>system</varname> takes precedence if
+ both are set.
+ '';
+ };
+ sshUser = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "builder";
+ description = ''
+ The username to log in as on the remote host. This user must be
+ able to log in and run nix commands non-interactively. It must
+ also be privileged to build derivations, so must be included in
+ <option>nix.trustedUsers</option>.
+ '';
+ };
+ sshKey = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "/root/.ssh/id_buildhost_builduser";
+ description = ''
+ The path to the SSH private key with which to authenticate on
+ the build machine. The private key must not have a passphrase.
+ If null, the building user (root on NixOS machines) must have an
+ appropriate ssh configuration to log in non-interactively.
+
+ Note that for security reasons, this path must point to a file
+ in the local filesystem, *not* to the nix store.
+ '';
+ };
+ maxJobs = mkOption {
+ type = types.int;
+ default = 1;
+ description = ''
+ The number of concurrent jobs the build machine supports. The
+ build machine will enforce its own limits, but this allows hydra
+ to schedule better since there is no work-stealing between build
+ machines.
+ '';
+ };
+ speedFactor = mkOption {
+ type = types.int;
+ default = 1;
+ description = ''
+ The relative speed of this builder. This is an arbitrary integer
+ that indicates the speed of this builder, relative to other
+ builders. Higher is faster.
+ '';
+ };
+ mandatoryFeatures = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ example = [ "big-parallel" ];
+ description = ''
+ A list of features mandatory for this builder. The builder will
+ be ignored for derivations that don't require all features in
+ this list. All mandatory features are automatically included in
+ <varname>supportedFeatures</varname>.
+ '';
+ };
+ supportedFeatures = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ example = [ "kvm" "big-parallel" ];
+ description = ''
+ A list of features supported by this builder. The builder will
+ be ignored for derivations that require features not in this
+ list.
+ '';
+ };
+ };
+ }));
default = [];
- example = literalExample ''
- [ { hostName = "voila.labs.cs.uu.nl";
- sshUser = "nix";
- sshKey = "/root/.ssh/id_buildfarm";
- system = "powerpc-darwin";
- maxJobs = 1;
- }
- { hostName = "linux64.example.org";
- sshUser = "buildfarm";
- sshKey = "/root/.ssh/id_buildfarm";
- system = "x86_64-linux";
- maxJobs = 2;
- speedFactor = 2;
- supportedFeatures = [ "kvm" ];
- mandatoryFeatures = [ "perf" ];
- }
- ]
- '';
description = ''
- This option lists the machines to be used if distributed
- builds are enabled (see
- <option>nix.distributedBuilds</option>). Nix will perform
- derivations on those machines via SSH by copying the inputs
- to the Nix store on the remote machine, starting the build,
- then copying the output back to the local Nix store. Each
- element of the list should be an attribute set containing
- the machine's host name (<varname>hostname</varname>), the
- user name to be used for the SSH connection
- (<varname>sshUser</varname>), the Nix system type
- (<varname>system</varname>, e.g.,
- <literal>"i686-linux"</literal>), the maximum number of
- jobs to be run in parallel on that machine
- (<varname>maxJobs</varname>), the path to the SSH private
- key to be used to connect (<varname>sshKey</varname>), a
- list of supported features of the machine
- (<varname>supportedFeatures</varname>) and a list of
- mandatory features of the machine
- (<varname>mandatoryFeatures</varname>). The SSH private key
- should not have a passphrase, and the corresponding public
- key should be added to
- <filename>~<replaceable>sshUser</replaceable>/authorized_keys</filename>
- on the remote machine.
+ This option lists the machines to be used if distributed builds are
+ enabled (see <option>nix.distributedBuilds</option>).
+ Nix will perform derivations on those machines via SSH by copying the
+ inputs to the Nix store on the remote machine, starting the build,
+ then copying the output back to the local Nix store.
'';
};
@@ -439,6 +500,13 @@ in
config = {
+ assertions = [
+ {
+ assertion = config.nix.distributedBuilds || config.nix.buildMachines == [];
+ message = "You must set `nix.distributedBuilds = true` to use nix.buildMachines";
+ }
+ ];
+
nix.binaryCachePublicKeys = [ "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" ];
nix.binaryCaches = [ "https://cache.nixos.org/" ];
@@ -461,14 +529,14 @@ in
{ enable = cfg.buildMachines != [];
text =
concatMapStrings (machine:
- "${if machine ? sshUser then "${machine.sshUser}@" else ""}${machine.hostName} "
- + machine.system or (concatStringsSep "," machine.systems)
- + " ${machine.sshKey or "-"} ${toString machine.maxJobs or 1} "
- + toString (machine.speedFactor or 1)
+ "${if machine.sshUser != null then "${machine.sshUser}@" else ""}${machine.hostName} "
+ + (if machine.system != null then machine.system else concatStringsSep "," machine.systems)
+ + " ${if machine.sshKey != null then machine.sshKey else "-"} ${toString machine.maxJobs} "
+ + toString (machine.speedFactor)
+ " "
- + concatStringsSep "," (machine.mandatoryFeatures or [] ++ machine.supportedFeatures or [])
+ + concatStringsSep "," (machine.mandatoryFeatures ++ machine.supportedFeatures)
+ " "
- + concatStringsSep "," machine.mandatoryFeatures or []
+ + concatStringsSep "," machine.mandatoryFeatures
+ "\n"
) cfg.buildMachines;
};
diff --git a/nixpkgs/nixos/modules/services/misc/zigbee2mqtt.nix b/nixpkgs/nixos/modules/services/misc/zigbee2mqtt.nix
new file mode 100644
index 00000000000..0957920f1a0
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/misc/zigbee2mqtt.nix
@@ -0,0 +1,98 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.zigbee2mqtt;
+
+ configJSON = pkgs.writeText "configuration.json"
+ (builtins.toJSON (recursiveUpdate defaultConfig cfg.config));
+ configFile = pkgs.runCommand "configuration.yaml" { preferLocalBuild = true; } ''
+ ${pkgs.remarshal}/bin/json2yaml -i ${configJSON} -o $out
+ '';
+
+ # the default config contains all required settings,
+ # so the service starts up without crashing.
+ defaultConfig = {
+ homeassistant = false;
+ permit_join = false;
+ mqtt = {
+ base_topic = "zigbee2mqtt";
+ server = "mqtt://localhost:1883";
+ };
+ serial.port = "/dev/ttyACM0";
+ # put device configuration into separate file because configuration.yaml
+ # is copied from the store on startup
+ devices = "devices.yaml";
+ };
+in
+{
+ meta.maintainers = with maintainers; [ sweber ];
+
+ options.services.zigbee2mqtt = {
+ enable = mkEnableOption "enable zigbee2mqtt service";
+
+ package = mkOption {
+ description = "Zigbee2mqtt package to use";
+ default = pkgs.zigbee2mqtt.override {
+ dataDir = cfg.dataDir;
+ };
+ defaultText = "pkgs.zigbee2mqtt";
+ type = types.package;
+ };
+
+ dataDir = mkOption {
+ description = "Zigbee2mqtt data directory";
+ default = "/var/lib/zigbee2mqtt";
+ type = types.path;
+ };
+
+ config = mkOption {
+ default = {};
+ type = with types; nullOr attrs;
+ example = literalExample ''
+ {
+ homeassistant = config.services.home-assistant.enable;
+ permit_join = true;
+ serial = {
+ port = "/dev/ttyACM1";
+ };
+ }
+ '';
+ description = ''
+ Your <filename>configuration.yaml</filename> as a Nix attribute set.
+ '';
+ };
+ };
+
+ config = mkIf (cfg.enable) {
+ systemd.services.zigbee2mqtt = {
+ description = "Zigbee2mqtt Service";
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network.target" ];
+ serviceConfig = {
+ ExecStart = "${cfg.package}/bin/zigbee2mqtt";
+ User = "zigbee2mqtt";
+ WorkingDirectory = cfg.dataDir;
+ Restart = "on-failure";
+ ProtectSystem = "strict";
+ ReadWritePaths = cfg.dataDir;
+ PrivateTmp = true;
+ RemoveIPC = true;
+ };
+ preStart = ''
+ cp --no-preserve=mode ${configFile} "${cfg.dataDir}/configuration.yaml"
+ '';
+ };
+
+ users.users.zigbee2mqtt = {
+ home = cfg.dataDir;
+ createHome = true;
+ group = "zigbee2mqtt";
+ extraGroups = [ "dialout" ];
+ uid = config.ids.uids.zigbee2mqtt;
+ };
+
+ users.groups.zigbee2mqtt.gid = config.ids.gids.zigbee2mqtt;
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/monitoring/do-agent.nix b/nixpkgs/nixos/modules/services/monitoring/do-agent.nix
index 2d3fe2f7976..4dfb6236727 100644
--- a/nixpkgs/nixos/modules/services/monitoring/do-agent.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/do-agent.nix
@@ -4,6 +4,7 @@ with lib;
let
cfg = config.services.do-agent;
+
in
{
options.services.do-agent = {
@@ -11,23 +12,13 @@ in
};
config = mkIf cfg.enable {
- environment.systemPackages = [ pkgs.do-agent ];
+ systemd.packages = [ pkgs.do-agent ];
systemd.services.do-agent = {
- description = "DigitalOcean Droplet Metrics Agent";
wantedBy = [ "multi-user.target" ];
- after = [ "network-online.target" ];
- wants = [ "network-online.target" ];
serviceConfig = {
- ExecStart = "${pkgs.do-agent}/bin/do-agent --syslog";
- Restart = "always";
- OOMScoreAdjust = -900;
- SyslogIdentifier = "DigitalOceanAgent";
- PrivateTmp = "yes";
- ProtectSystem = "full";
- ProtectHome = "yes";
- NoNewPrivileges = "yes";
- DynamicUser = "yes";
+ ExecStart = [ "" "${pkgs.do-agent}/bin/do-agent --syslog" ];
+ DynamicUser = true;
};
};
};
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix
index f9ad1457fc8..59748efe0de 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix
@@ -21,6 +21,7 @@ let
# `serviceOpts.script` or `serviceOpts.serviceConfig.ExecStart`
exporterOpts = genAttrs [
+ "apcupsd"
"bind"
"blackbox"
"collectd"
@@ -28,14 +29,18 @@ let
"dovecot"
"fritzbox"
"json"
+ "keylight"
+ "lnd"
"mail"
"mikrotik"
"minio"
+ "modemmanager"
"nextcloud"
"nginx"
"node"
"postfix"
"postgres"
+ "redis"
"rspamd"
"snmp"
"surfboard"
@@ -168,15 +173,6 @@ in
(opt: lib.mkRemovedOptionModule [ "services" "prometheus" "${opt}" ] ''
The prometheus exporters are now configured using `services.prometheus.exporters'.
See the 18.03 release notes for more information.
- '' ))
-
- ++ (lib.forEach [ "enable" "substitutions" "preset" ]
- (opt: lib.mkRemovedOptionModule [ "fonts" "fontconfig" "ultimate" "${opt}" ] ''
- The fonts.fontconfig.ultimate module and configuration is obsolete.
- The repository has since been archived and activity has ceased.
- https://github.com/bohoomil/fontconfig-ultimate/issues/171.
- No action should be needed for font configuration, as the fonts.fontconfig
- module is already used by default.
'' ));
options.services.prometheus.exporters = mkOption {
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/apcupsd.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/apcupsd.nix
new file mode 100644
index 00000000000..57c35a742c5
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/apcupsd.nix
@@ -0,0 +1,38 @@
+{ config, lib, pkgs, options }:
+
+with lib;
+
+let
+ cfg = config.services.prometheus.exporters.apcupsd;
+in
+{
+ port = 9162;
+ extraOpts = {
+ apcupsdAddress = mkOption {
+ type = types.str;
+ default = ":3551";
+ description = ''
+ Address of the apcupsd Network Information Server (NIS).
+ '';
+ };
+
+ apcupsdNetwork = mkOption {
+ type = types.enum ["tcp" "tcp4" "tcp6"];
+ default = "tcp";
+ description = ''
+ Network of the apcupsd Network Information Server (NIS): one of "tcp", "tcp4", or "tcp6".
+ '';
+ };
+ };
+ serviceOpts = {
+ serviceConfig = {
+ ExecStart = ''
+ ${pkgs.prometheus-apcupsd-exporter}/bin/apcupsd_exporter \
+ -telemetry.addr ${cfg.listenAddress}:${toString cfg.port} \
+ -apcupsd.addr ${cfg.apcupsdAddress} \
+ -apcupsd.network ${cfg.apcupsdNetwork} \
+ ${concatStringsSep " \\\n " cfg.extraFlags}
+ '';
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/keylight.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/keylight.nix
new file mode 100644
index 00000000000..dfa56343b87
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/keylight.nix
@@ -0,0 +1,19 @@
+{ config, lib, pkgs, options }:
+
+with lib;
+
+let
+ cfg = config.services.prometheus.exporters.keylight;
+in
+{
+ port = 9288;
+ serviceOpts = {
+ serviceConfig = {
+ ExecStart = ''
+ ${pkgs.prometheus-keylight-exporter}/bin/keylight_exporter \
+ -metrics.addr ${cfg.listenAddress}:${toString cfg.port} \
+ ${concatStringsSep " \\\n " cfg.extraFlags}
+ '';
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/lnd.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/lnd.nix
new file mode 100644
index 00000000000..35f97202057
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/lnd.nix
@@ -0,0 +1,46 @@
+{ config, lib, pkgs, options }:
+
+with lib;
+
+let
+ cfg = config.services.prometheus.exporters.lnd;
+in
+{
+ port = 9092;
+ extraOpts = {
+ lndHost = mkOption {
+ type = types.str;
+ default = "localhost:10009";
+ description = ''
+ lnd instance gRPC address:port.
+ '';
+ };
+
+ lndTlsPath = mkOption {
+ type = types.path;
+ description = ''
+ Path to lnd TLS certificate.
+ '';
+ };
+
+ lndMacaroonDir = mkOption {
+ type = types.path;
+ description = ''
+ Path to lnd macaroons.
+ '';
+ };
+ };
+ serviceOpts.serviceConfig = {
+ ExecStart = ''
+ ${pkgs.prometheus-lnd-exporter}/bin/lndmon \
+ --prometheus.listenaddr=${cfg.listenAddress}:${toString cfg.port} \
+ --prometheus.logdir=/var/log/prometheus-lnd-exporter \
+ --lnd.host=${cfg.lndHost} \
+ --lnd.tlspath=${cfg.lndTlsPath} \
+ --lnd.macaroondir=${cfg.lndMacaroonDir} \
+ ${concatStringsSep " \\\n " cfg.extraFlags}
+ '';
+ LogsDirectory = "prometheus-lnd-exporter";
+ ReadOnlyPaths = [ cfg.lndTlsPath cfg.lndMacaroonDir ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/modemmanager.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/modemmanager.nix
new file mode 100644
index 00000000000..86ea98b94e4
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/modemmanager.nix
@@ -0,0 +1,33 @@
+{ config, lib, pkgs, options }:
+
+with lib;
+
+let
+ cfg = config.services.prometheus.exporters.modemmanager;
+in
+{
+ port = 9539;
+ extraOpts = {
+ refreshRate = mkOption {
+ type = types.str;
+ default = "5s";
+ description = ''
+ How frequently ModemManager will refresh the extended signal quality
+ information for each modem. The duration should be specified in seconds
+ ("5s"), minutes ("1m"), or hours ("1h").
+ '';
+ };
+ };
+ serviceOpts = {
+ serviceConfig = {
+ # Required in order to authenticate with ModemManager via D-Bus.
+ SupplementaryGroups = "networkmanager";
+ ExecStart = ''
+ ${pkgs.prometheus-modemmanager-exporter}/bin/modemmanager_exporter \
+ -addr ${cfg.listenAddress}:${toString cfg.port} \
+ -rate ${cfg.refreshRate} \
+ ${concatStringsSep " \\\n " cfg.extraFlags}
+ '';
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/redis.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/redis.nix
new file mode 100644
index 00000000000..befbcb21f76
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/redis.nix
@@ -0,0 +1,19 @@
+{ config, lib, pkgs, options }:
+
+with lib;
+
+let
+ cfg = config.services.prometheus.exporters.redis;
+in
+{
+ port = 9121;
+ serviceOpts = {
+ serviceConfig = {
+ ExecStart = ''
+ ${pkgs.prometheus-redis-exporter}/bin/redis_exporter \
+ -web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
+ ${concatStringsSep " \\\n " cfg.extraFlags}
+ '';
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/monitoring/tuptime.nix b/nixpkgs/nixos/modules/services/monitoring/tuptime.nix
index 731260a5c20..8f79d916599 100644
--- a/nixpkgs/nixos/modules/services/monitoring/tuptime.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/tuptime.nix
@@ -32,7 +32,10 @@ in {
environment.systemPackages = [ pkgs.tuptime ];
- users.users.tuptime.description = "tuptime database owner";
+ users = {
+ groups._tuptime.members = [ "_tuptime" ];
+ users._tuptime.description = "tuptime database owner";
+ };
systemd = {
services = {
@@ -45,7 +48,7 @@ in {
serviceConfig = {
StateDirectory = "tuptime";
Type = "oneshot";
- User = "tuptime";
+ User = "_tuptime";
RemainAfterExit = true;
ExecStart = "${pkgs.tuptime}/bin/tuptime -x";
ExecStop = "${pkgs.tuptime}/bin/tuptime -xg";
@@ -57,7 +60,7 @@ in {
serviceConfig = {
StateDirectory = "tuptime";
Type = "oneshot";
- User = "tuptime";
+ User = "_tuptime";
ExecStart = "${pkgs.tuptime}/bin/tuptime -x";
};
};
diff --git a/nixpkgs/nixos/modules/services/monitoring/zabbix-agent.nix b/nixpkgs/nixos/modules/services/monitoring/zabbix-agent.nix
index b3383ed628b..73eed7aa66a 100644
--- a/nixpkgs/nixos/modules/services/monitoring/zabbix-agent.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/zabbix-agent.nix
@@ -3,8 +3,9 @@
let
cfg = config.services.zabbixAgent;
- inherit (lib) mkDefault mkEnableOption mkIf mkOption;
+ inherit (lib) mkDefault mkEnableOption mkIf mkMerge mkOption;
inherit (lib) attrValues concatMapStringsSep literalExample optionalString types;
+ inherit (lib.generators) toKeyValue;
user = "zabbix-agent";
group = "zabbix-agent";
@@ -14,19 +15,15 @@ let
paths = attrValues cfg.modules;
};
- configFile = pkgs.writeText "zabbix_agent.conf" ''
- LogType = console
- Server = ${cfg.server}
- ListenIP = ${cfg.listen.ip}
- ListenPort = ${toString cfg.listen.port}
- ${optionalString (cfg.modules != {}) "LoadModulePath = ${moduleEnv}/lib"}
- ${concatMapStringsSep "\n" (name: "LoadModule = ${name}") (builtins.attrNames cfg.modules)}
- ${cfg.extraConfig}
- '';
+ configFile = pkgs.writeText "zabbix_agent.conf" (toKeyValue { listsAsDuplicateKeys = true; } cfg.settings);
in
{
+ imports = [
+ (lib.mkRemovedOptionModule [ "services" "zabbixAgent" "extraConfig" ] "Use services.zabbixAgent.settings instead.")
+ ];
+
# interface
options = {
@@ -105,15 +102,18 @@ in
'';
};
- # TODO: for bonus points migrate this to https://github.com/NixOS/rfcs/pull/42
- extraConfig = mkOption {
- default = "";
- type = types.lines;
+ settings = mkOption {
+ type = with types; attrsOf (oneOf [ int str (listOf str) ]);
+ default = {};
description = ''
- Configuration that is injected verbatim into the configuration file. Refer to
+ Zabbix Agent configuration. Refer to
<link xlink:href="https://www.zabbix.com/documentation/current/manual/appendix/config/zabbix_agentd"/>
for details on supported values.
'';
+ example = {
+ Hostname = "example.org";
+ DebugLevel = 4;
+ };
};
};
@@ -124,6 +124,17 @@ in
config = mkIf cfg.enable {
+ services.zabbixAgent.settings = mkMerge [
+ {
+ LogType = "console";
+ Server = cfg.server;
+ ListenIP = cfg.listen.ip;
+ ListenPort = cfg.listen.port;
+ LoadModule = builtins.attrNames cfg.modules;
+ }
+ (mkIf (cfg.modules != {}) { LoadModulePath = "${moduleEnv}/lib"; })
+ ];
+
networking.firewall = mkIf cfg.openFirewall {
allowedTCPPorts = [ cfg.listen.port ];
};
diff --git a/nixpkgs/nixos/modules/services/monitoring/zabbix-proxy.nix b/nixpkgs/nixos/modules/services/monitoring/zabbix-proxy.nix
index 9d214469c3b..d51507c91a1 100644
--- a/nixpkgs/nixos/modules/services/monitoring/zabbix-proxy.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/zabbix-proxy.nix
@@ -5,8 +5,9 @@ let
pgsql = config.services.postgresql;
mysql = config.services.mysql;
- inherit (lib) mkDefault mkEnableOption mkIf mkOption;
+ inherit (lib) mkDefault mkEnableOption mkIf mkMerge mkOption;
inherit (lib) attrValues concatMapStringsSep literalExample optional optionalAttrs optionalString types;
+ inherit (lib.generators) toKeyValue;
user = "zabbix";
group = "zabbix";
@@ -19,24 +20,7 @@ let
paths = attrValues cfg.modules;
};
- configFile = pkgs.writeText "zabbix_proxy.conf" ''
- LogType = console
- ListenIP = ${cfg.listen.ip}
- ListenPort = ${toString cfg.listen.port}
- Server = ${cfg.server}
- # TODO: set to cfg.database.socket if database type is pgsql?
- DBHost = ${optionalString (cfg.database.createLocally != true) cfg.database.host}
- ${optionalString (cfg.database.createLocally != true) "DBPort = ${cfg.database.port}"}
- DBName = ${cfg.database.name}
- DBUser = ${cfg.database.user}
- ${optionalString (cfg.database.passwordFile != null) "Include ${passwordFile}"}
- ${optionalString (mysqlLocal && cfg.database.socket != null) "DBSocket = ${cfg.database.socket}"}
- SocketDir = ${runtimeDir}
- FpingLocation = /run/wrappers/bin/fping
- ${optionalString (cfg.modules != {}) "LoadModulePath = ${moduleEnv}/lib"}
- ${concatMapStringsSep "\n" (name: "LoadModule = ${name}") (builtins.attrNames cfg.modules)}
- ${cfg.extraConfig}
- '';
+ configFile = pkgs.writeText "zabbix_proxy.conf" (toKeyValue { listsAsDuplicateKeys = true; } cfg.settings);
mysqlLocal = cfg.database.createLocally && cfg.database.type == "mysql";
pgsqlLocal = cfg.database.createLocally && cfg.database.type == "pgsql";
@@ -44,6 +28,10 @@ let
in
{
+ imports = [
+ (lib.mkRemovedOptionModule [ "services" "zabbixProxy" "extraConfig" ] "Use services.zabbixProxy.settings instead.")
+ ];
+
# interface
options = {
@@ -182,15 +170,19 @@ in
'';
};
- # TODO: for bonus points migrate this to https://github.com/NixOS/rfcs/pull/42
- extraConfig = mkOption {
- default = "";
- type = types.lines;
+ settings = mkOption {
+ type = with types; attrsOf (oneOf [ int str (listOf str) ]);
+ default = {};
description = ''
- Configuration that is injected verbatim into the configuration file. Refer to
+ Zabbix Proxy configuration. Refer to
<link xlink:href="https://www.zabbix.com/documentation/current/manual/appendix/config/zabbix_proxy"/>
for details on supported values.
'';
+ example = {
+ CacheSize = "1G";
+ SSHKeyLocation = "/var/lib/zabbix/.ssh";
+ StartPingers = 32;
+ };
};
};
@@ -213,6 +205,26 @@ in
}
];
+ services.zabbixProxy.settings = mkMerge [
+ {
+ LogType = "console";
+ ListenIP = cfg.listen.ip;
+ ListenPort = cfg.listen.port;
+ Server = cfg.server;
+ # TODO: set to cfg.database.socket if database type is pgsql?
+ DBHost = optionalString (cfg.database.createLocally != true) cfg.database.host;
+ DBName = cfg.database.name;
+ DBUser = cfg.database.user;
+ SocketDir = runtimeDir;
+ FpingLocation = "/run/wrappers/bin/fping";
+ LoadModule = builtins.attrNames cfg.modules;
+ }
+ (mkIf (cfg.database.createLocally != true) { DBPort = cfg.database.port; })
+ (mkIf (cfg.database.passwordFile != null) { Include = [ "${passwordFile}" ]; })
+ (mkIf (mysqlLocal && cfg.database.socket != null) { DBSocket = cfg.database.socket; })
+ (mkIf (cfg.modules != {}) { LoadModulePath = "${moduleEnv}/lib"; })
+ ];
+
networking.firewall = mkIf cfg.openFirewall {
allowedTCPPorts = [ cfg.listen.port ];
};
diff --git a/nixpkgs/nixos/modules/services/monitoring/zabbix-server.nix b/nixpkgs/nixos/modules/services/monitoring/zabbix-server.nix
index b4e4378ce1e..df09488a8cc 100644
--- a/nixpkgs/nixos/modules/services/monitoring/zabbix-server.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/zabbix-server.nix
@@ -5,8 +5,9 @@ let
pgsql = config.services.postgresql;
mysql = config.services.mysql;
- inherit (lib) mkDefault mkEnableOption mkIf mkOption;
+ inherit (lib) mkDefault mkEnableOption mkIf mkMerge mkOption;
inherit (lib) attrValues concatMapStringsSep literalExample optional optionalAttrs optionalString types;
+ inherit (lib.generators) toKeyValue;
user = "zabbix";
group = "zabbix";
@@ -19,24 +20,7 @@ let
paths = attrValues cfg.modules;
};
- configFile = pkgs.writeText "zabbix_server.conf" ''
- LogType = console
- ListenIP = ${cfg.listen.ip}
- ListenPort = ${toString cfg.listen.port}
- # TODO: set to cfg.database.socket if database type is pgsql?
- DBHost = ${optionalString (cfg.database.createLocally != true) cfg.database.host}
- ${optionalString (cfg.database.createLocally != true) "DBPort = ${cfg.database.port}"}
- DBName = ${cfg.database.name}
- DBUser = ${cfg.database.user}
- ${optionalString (cfg.database.passwordFile != null) "Include ${passwordFile}"}
- ${optionalString (mysqlLocal && cfg.database.socket != null) "DBSocket = ${cfg.database.socket}"}
- PidFile = ${runtimeDir}/zabbix_server.pid
- SocketDir = ${runtimeDir}
- FpingLocation = /run/wrappers/bin/fping
- ${optionalString (cfg.modules != {}) "LoadModulePath = ${moduleEnv}/lib"}
- ${concatMapStringsSep "\n" (name: "LoadModule = ${name}") (builtins.attrNames cfg.modules)}
- ${cfg.extraConfig}
- '';
+ configFile = pkgs.writeText "zabbix_server.conf" (toKeyValue { listsAsDuplicateKeys = true; } cfg.settings);
mysqlLocal = cfg.database.createLocally && cfg.database.type == "mysql";
pgsqlLocal = cfg.database.createLocally && cfg.database.type == "pgsql";
@@ -47,6 +31,7 @@ in
imports = [
(lib.mkRenamedOptionModule [ "services" "zabbixServer" "dbServer" ] [ "services" "zabbixServer" "database" "host" ])
(lib.mkRemovedOptionModule [ "services" "zabbixServer" "dbPassword" ] "Use services.zabbixServer.database.passwordFile instead.")
+ (lib.mkRemovedOptionModule [ "services" "zabbixServer" "extraConfig" ] "Use services.zabbixServer.settings instead.")
];
# interface
@@ -176,15 +161,19 @@ in
'';
};
- # TODO: for bonus points migrate this to https://github.com/NixOS/rfcs/pull/42
- extraConfig = mkOption {
- default = "";
- type = types.lines;
+ settings = mkOption {
+ type = with types; attrsOf (oneOf [ int str (listOf str) ]);
+ default = {};
description = ''
- Configuration that is injected verbatim into the configuration file. Refer to
+ Zabbix Server configuration. Refer to
<link xlink:href="https://www.zabbix.com/documentation/current/manual/appendix/config/zabbix_server"/>
for details on supported values.
'';
+ example = {
+ CacheSize = "1G";
+ SSHKeyLocation = "/var/lib/zabbix/.ssh";
+ StartPingers = 32;
+ };
};
};
@@ -204,6 +193,26 @@ in
}
];
+ services.zabbixServer.settings = mkMerge [
+ {
+ LogType = "console";
+ ListenIP = cfg.listen.ip;
+ ListenPort = cfg.listen.port;
+ # TODO: set to cfg.database.socket if database type is pgsql?
+ DBHost = optionalString (cfg.database.createLocally != true) cfg.database.host;
+ DBName = cfg.database.name;
+ DBUser = cfg.database.user;
+ PidFile = "${runtimeDir}/zabbix_server.pid";
+ SocketDir = runtimeDir;
+ FpingLocation = "/run/wrappers/bin/fping";
+ LoadModule = builtins.attrNames cfg.modules;
+ }
+ (mkIf (cfg.database.createLocally != true) { DBPort = cfg.database.port; })
+ (mkIf (cfg.database.passwordFile != null) { Include = [ "${passwordFile}" ]; })
+ (mkIf (mysqlLocal && cfg.database.socket != null) { DBSocket = cfg.database.socket; })
+ (mkIf (cfg.modules != {}) { LoadModulePath = "${moduleEnv}/lib"; })
+ ];
+
networking.firewall = mkIf cfg.openFirewall {
allowedTCPPorts = [ cfg.listen.port ];
};
diff --git a/nixpkgs/nixos/modules/services/network-filesystems/ipfs.nix b/nixpkgs/nixos/modules/services/network-filesystems/ipfs.nix
index 1f5c14d777d..7d18410ff0a 100644
--- a/nixpkgs/nixos/modules/services/network-filesystems/ipfs.nix
+++ b/nixpkgs/nixos/modules/services/network-filesystems/ipfs.nix
@@ -1,69 +1,30 @@
-{ config, lib, pkgs, ... }:
+{ config, lib, pkgs, options, ... }:
with lib;
let
- inherit (pkgs) ipfs runCommand makeWrapper;
-
cfg = config.services.ipfs;
+ opt = options.services.ipfs;
ipfsFlags = toString ([
(optionalString cfg.autoMount "--mount")
- #(optionalString cfg.autoMigrate "--migrate")
(optionalString cfg.enableGC "--enable-gc")
(optionalString (cfg.serviceFdlimit != null) "--manage-fdlimit=false")
(optionalString (cfg.defaultMode == "offline") "--offline")
(optionalString (cfg.defaultMode == "norouting") "--routing=none")
] ++ cfg.extraFlags);
- defaultDataDir = if versionAtLeast config.system.stateVersion "17.09" then
- "/var/lib/ipfs" else
- "/var/lib/ipfs/.ipfs";
-
- # Wrapping the ipfs binary with the environment variable IPFS_PATH set to dataDir because we can't set it in the user environment
- wrapped = runCommand "ipfs" { buildInputs = [ makeWrapper ]; preferLocalBuild = true; } ''
- mkdir -p "$out/bin"
- makeWrapper "${ipfs}/bin/ipfs" "$out/bin/ipfs" \
- --set IPFS_PATH ${cfg.dataDir} \
- --prefix PATH : /run/wrappers/bin
- '';
+ splitMulitaddr = addrRaw: lib.tail (lib.splitString "/" addrRaw);
+ multiaddrToListenStream = addrRaw: let
+ addr = splitMulitaddr addrRaw;
+ s = builtins.elemAt addr;
+ in if s 0 == "ip4" && s 2 == "tcp"
+ then "${s 1}:${s 3}"
+ else if s 0 == "ip6" && s 2 == "tcp"
+ then "[${s 1}]:${s 3}"
+ else if s 0 == "unix"
+ then "/${lib.concatStringsSep "/" (lib.tail addr)}"
+ else null; # not valid for listen stream, skip
- commonEnv = {
- environment.IPFS_PATH = cfg.dataDir;
- path = [ wrapped ];
- serviceConfig.User = cfg.user;
- serviceConfig.Group = cfg.group;
- };
-
- baseService = recursiveUpdate commonEnv {
- wants = [ "ipfs-init.service" ];
- # NB: migration must be performed prior to pre-start, else we get the failure message!
- preStart = optionalString cfg.autoMount ''
- ipfs --local config Mounts.FuseAllowOther --json true
- ipfs --local config Mounts.IPFS ${cfg.ipfsMountDir}
- ipfs --local config Mounts.IPNS ${cfg.ipnsMountDir}
- '' + concatStringsSep "\n" (collect
- isString
- (mapAttrsRecursive
- (path: value:
- # Using heredoc below so that the value is never improperly quoted
- ''
- read value <<EOF
- ${builtins.toJSON value}
- EOF
- ipfs --local config --json "${concatStringsSep "." path}" "$value"
- '')
- ({ Addresses.API = cfg.apiAddress;
- Addresses.Gateway = cfg.gatewayAddress;
- Addresses.Swarm = cfg.swarmAddress;
- } //
- cfg.extraConfig))
- );
- serviceConfig = {
- ExecStart = "${wrapped}/bin/ipfs daemon ${ipfsFlags}";
- Restart = "on-failure";
- RestartSec = 1;
- } // optionalAttrs (cfg.serviceFdlimit != null) { LimitNOFILE = cfg.serviceFdlimit; };
- };
in {
###### interface
@@ -88,7 +49,9 @@ in {
dataDir = mkOption {
type = types.str;
- default = defaultDataDir;
+ default = if versionAtLeast config.system.stateVersion "17.09"
+ then "/var/lib/ipfs"
+ else "/var/lib/ipfs/.ipfs";
description = "The data dir for IPFS";
};
@@ -98,18 +61,6 @@ in {
description = "systemd service that is enabled by default";
};
- /*
- autoMigrate = mkOption {
- type = types.bool;
- default = false;
- description = ''
- Whether IPFS should try to migrate the file system automatically.
-
- The daemon will need to be able to download a binary from https://ipfs.io to perform the migration.
- '';
- };
- */
-
autoMount = mkOption {
type = types.bool;
default = false;
@@ -142,7 +93,10 @@ in {
swarmAddress = mkOption {
type = types.listOf types.str;
- default = [ "/ip4/0.0.0.0/tcp/4001" "/ip6/::/tcp/4001" ];
+ default = [
+ "/ip4/0.0.0.0/tcp/4001"
+ "/ip6/::/tcp/4001"
+ ];
description = "Where IPFS listens for incoming p2p connections";
};
@@ -199,13 +153,21 @@ in {
example = 64*1024;
};
+ startWhenNeeded = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Whether to use socket activation to start IPFS when needed.";
+ };
+
};
};
###### implementation
config = mkIf cfg.enable {
- environment.systemPackages = [ wrapped ];
+ environment.systemPackages = [ pkgs.ipfs ];
+ environment.variables.IPFS_PATH = cfg.dataDir;
+
programs.fuse = mkIf cfg.autoMount {
userAllowOther = true;
};
@@ -234,10 +196,14 @@ in {
"d '${cfg.ipnsMountDir}' - ${cfg.user} ${cfg.group} - -"
];
- systemd.services.ipfs-init = recursiveUpdate commonEnv {
+ systemd.packages = [ pkgs.ipfs ];
+
+ systemd.services.ipfs-init = {
description = "IPFS Initializer";
- before = [ "ipfs.service" "ipfs-offline.service" "ipfs-norouting.service" ];
+ environment.IPFS_PATH = cfg.dataDir;
+
+ path = [ pkgs.ipfs ];
script = ''
if [[ ! -f ${cfg.dataDir}/config ]]; then
@@ -251,34 +217,67 @@ in {
fi
'';
+ wantedBy = [ "default.target" ];
+
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
+ User = cfg.user;
+ Group = cfg.group;
};
};
- # TODO These 3 definitions possibly be further abstracted through use of a function
- # like: mutexServices "ipfs" [ "", "offline", "norouting" ] { ... shared conf here ... }
+ systemd.services.ipfs = {
+ path = [ "/run/wrappers" pkgs.ipfs ];
+ environment.IPFS_PATH = cfg.dataDir;
+
+ wants = [ "ipfs-init.service" ];
+ after = [ "ipfs-init.service" ];
- systemd.services.ipfs = recursiveUpdate baseService {
- description = "IPFS Daemon";
- wantedBy = mkIf (cfg.defaultMode == "online") [ "multi-user.target" ];
- after = [ "network.target" "ipfs-init.service" ];
- conflicts = [ "ipfs-offline.service" "ipfs-norouting.service"];
+ preStart = optionalString cfg.autoMount ''
+ ipfs --local config Mounts.FuseAllowOther --json true
+ ipfs --local config Mounts.IPFS ${cfg.ipfsMountDir}
+ ipfs --local config Mounts.IPNS ${cfg.ipnsMountDir}
+ '' + concatStringsSep "\n" (collect
+ isString
+ (mapAttrsRecursive
+ (path: value:
+ # Using heredoc below so that the value is never improperly quoted
+ ''
+ read value <<EOF
+ ${builtins.toJSON value}
+ EOF
+ ipfs --local config --json "${concatStringsSep "." path}" "$value"
+ '')
+ ({ Addresses.API = cfg.apiAddress;
+ Addresses.Gateway = cfg.gatewayAddress;
+ Addresses.Swarm = cfg.swarmAddress;
+ } //
+ cfg.extraConfig))
+ );
+ serviceConfig = {
+ ExecStart = ["" "${pkgs.ipfs}/bin/ipfs daemon ${ipfsFlags}"];
+ User = cfg.user;
+ Group = cfg.group;
+ } // optionalAttrs (cfg.serviceFdlimit != null) { LimitNOFILE = cfg.serviceFdlimit; };
+ } // optionalAttrs (!cfg.startWhenNeeded) {
+ wantedBy = [ "default.target" ];
};
- systemd.services.ipfs-offline = recursiveUpdate baseService {
- description = "IPFS Daemon (offline mode)";
- wantedBy = mkIf (cfg.defaultMode == "offline") [ "multi-user.target" ];
- after = [ "ipfs-init.service" ];
- conflicts = [ "ipfs.service" "ipfs-norouting.service"];
+ systemd.sockets.ipfs-gateway = {
+ wantedBy = [ "sockets.target" ];
+ socketConfig.ListenStream = let
+ fromCfg = multiaddrToListenStream cfg.gatewayAddress;
+ in [ "" ] ++ lib.optional (fromCfg != null) fromCfg;
};
- systemd.services.ipfs-norouting = recursiveUpdate baseService {
- description = "IPFS Daemon (no routing mode)";
- wantedBy = mkIf (cfg.defaultMode == "norouting") [ "multi-user.target" ];
- after = [ "ipfs-init.service" ];
- conflicts = [ "ipfs.service" "ipfs-offline.service"];
+ systemd.sockets.ipfs-api = {
+ wantedBy = [ "sockets.target" ];
+ # We also include "%t/ipfs.sock" because tere is no way to put the "%t"
+ # in the multiaddr.
+ socketConfig.ListenStream = let
+ fromCfg = multiaddrToListenStream cfg.apiAddress;
+ in [ "" "%t/ipfs.sock" ] ++ lib.optional (fromCfg != null) fromCfg;
};
};
diff --git a/nixpkgs/nixos/modules/services/networking/3proxy.nix b/nixpkgs/nixos/modules/services/networking/3proxy.nix
index ae8a4958ca9..37a48657c1c 100644
--- a/nixpkgs/nixos/modules/services/networking/3proxy.nix
+++ b/nixpkgs/nixos/modules/services/networking/3proxy.nix
@@ -124,7 +124,7 @@ in {
<literal>"iponly"</literal>: specifies no authentication. ACLs authorization is used.
</para></listitem>
<listitem><para>
- <literal>"strong"</literal>: authentication by username/password. If user is not registered his access is denied regardless of ACLs.
+ <literal>"strong"</literal>: authentication by username/password. If user is not registered their access is denied regardless of ACLs.
</para></listitem>
</itemizedlist>
diff --git a/nixpkgs/nixos/modules/services/networking/bitcoind.nix b/nixpkgs/nixos/modules/services/networking/bitcoind.nix
index 4e00a886547..38537ad2de7 100644
--- a/nixpkgs/nixos/modules/services/networking/bitcoind.nix
+++ b/nixpkgs/nixos/modules/services/networking/bitcoind.nix
@@ -3,31 +3,8 @@
with lib;
let
- cfg = config.services.bitcoind;
- pidFile = "${cfg.dataDir}/bitcoind.pid";
- configFile = pkgs.writeText "bitcoin.conf" ''
- ${optionalString cfg.testnet "testnet=1"}
- ${optionalString (cfg.dbCache != null) "dbcache=${toString cfg.dbCache}"}
- ${optionalString (cfg.prune != null) "prune=${toString cfg.prune}"}
-
- # Connection options
- ${optionalString (cfg.port != null) "port=${toString cfg.port}"}
-
- # RPC server options
- ${optionalString (cfg.rpc.port != null) "rpcport=${toString cfg.rpc.port}"}
- ${concatMapStringsSep "\n"
- (rpcUser: "rpcauth=${rpcUser.name}:${rpcUser.passwordHMAC}")
- (attrValues cfg.rpc.users)
- }
- # Extra config options (from bitcoind nixos service)
- ${cfg.extraConfig}
- '';
- cmdlineOptions = escapeShellArgs [
- "-conf=${cfg.configFile}"
- "-datadir=${cfg.dataDir}"
- "-pid=${pidFile}"
- ];
+ eachBitcoind = config.services.bitcoind;
rpcUserOpts = { name, ... }: {
options = {
@@ -39,11 +16,14 @@ let
'';
};
passwordHMAC = mkOption {
- type = with types; uniq (strMatching "[0-9a-f]+\\$[0-9a-f]{64}");
+ type = types.uniq (types.strMatching "[0-9a-f]+\\$[0-9a-f]{64}");
example = "f7efda5c189b999524f151318c0c86$d5b51b3beffbc02b724e5d095828e0bc8b2456e9ac8757ae3211a5d9b16a22ae";
description = ''
Password HMAC-SHA-256 for JSON-RPC connections. Must be a string of the
format &lt;SALT-HEX&gt;$&lt;HMAC-HEX&gt;.
+
+ Tool (Python script) for HMAC generation is available here:
+ <link xlink:href="https://github.com/bitcoin/bitcoin/blob/master/share/rpcauth/rpcauth.py"/>
'';
};
};
@@ -51,10 +31,10 @@ let
name = mkDefault name;
};
};
-in {
- options = {
- services.bitcoind = {
+ bitcoindOpts = { config, lib, name, ...}: {
+ options = {
+
enable = mkEnableOption "Bitcoin daemon";
package = mkOption {
@@ -63,12 +43,14 @@ in {
defaultText = "pkgs.bitcoind";
description = "The package providing bitcoin binaries.";
};
+
configFile = mkOption {
- type = types.path;
- default = configFile;
- example = "/etc/bitcoind.conf";
+ type = types.nullOr types.path;
+ default = null;
+ example = "/var/lib/${name}/bitcoin.conf";
description = "The configuration file path to supply bitcoind.";
};
+
extraConfig = mkOption {
type = types.lines;
default = "";
@@ -79,20 +61,22 @@ in {
'';
description = "Additional configurations to be appended to <filename>bitcoin.conf</filename>.";
};
+
dataDir = mkOption {
type = types.path;
- default = "/var/lib/bitcoind";
+ default = "/var/lib/bitcoind-${name}";
description = "The data directory for bitcoind.";
};
user = mkOption {
type = types.str;
- default = "bitcoin";
+ default = "bitcoind-${name}";
description = "The user as which to run bitcoind.";
};
+
group = mkOption {
type = types.str;
- default = cfg.user;
+ default = config.user;
description = "The group as which to run bitcoind.";
};
@@ -110,29 +94,36 @@ in {
bob.passwordHMAC = "b2dd077cb54591a2f3139e69a897ac$4e71f08d48b4347cf8eff3815c0e25ae2e9a4340474079f55705f40574f4ec99";
}
'';
- type = with types; loaOf (submodule rpcUserOpts);
- description = ''
- RPC user information for JSON-RPC connnections.
- '';
+ type = types.attrsOf (types.submodule rpcUserOpts);
+ description = "RPC user information for JSON-RPC connnections.";
};
};
+ pidFile = mkOption {
+ type = types.path;
+ default = "${config.dataDir}/bitcoind.pid";
+ description = "Location of bitcoind pid file.";
+ };
+
testnet = mkOption {
type = types.bool;
default = false;
- description = "Whether to use the test chain.";
+ description = "Whether to use the testnet instead of mainnet.";
};
+
port = mkOption {
type = types.nullOr types.port;
default = null;
description = "Override the default port on which to listen for connections.";
};
+
dbCache = mkOption {
type = types.nullOr (types.ints.between 4 16384);
default = null;
example = 4000;
- description = "Override the default database cache size in megabytes.";
+ description = "Override the default database cache size in MiB.";
};
+
prune = mkOption {
type = types.nullOr (types.coercedTo
(types.enum [ "disable" "manual" ])
@@ -149,45 +140,122 @@ in {
and -rescan. Warning: Reverting this setting requires re-downloading
the entire blockchain. ("disable" = disable pruning blocks, "manual"
= allow manual pruning via RPC, >=550 = automatically prune block files
- to stay under the specified target size in MiB)
+ to stay under the specified target size in MiB).
+ '';
+ };
+
+ extraCmdlineOptions = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ description = ''
+ Extra command line options to pass to bitcoind.
+ Run bitcoind --help to list all available options.
'';
};
};
};
+in
+{
- config = mkIf cfg.enable {
- environment.systemPackages = [ cfg.package ];
- systemd.tmpfiles.rules = [
- "d '${cfg.dataDir}' 0770 '${cfg.user}' '${cfg.group}' - -"
- "L '${cfg.dataDir}/bitcoin.conf' - - - - '${cfg.configFile}'"
- ];
- systemd.services.bitcoind = {
- description = "Bitcoin daemon";
- after = [ "network.target" ];
- wantedBy = [ "multi-user.target" ];
- serviceConfig = {
- User = cfg.user;
- Group = cfg.group;
- ExecStart = "${cfg.package}/bin/bitcoind ${cmdlineOptions}";
- Restart = "on-failure";
-
- # Hardening measures
- PrivateTmp = "true";
- ProtectSystem = "full";
- NoNewPrivileges = "true";
- PrivateDevices = "true";
- MemoryDenyWriteExecute = "true";
- };
+ options = {
+ services.bitcoind = mkOption {
+ type = types.attrsOf (types.submodule bitcoindOpts);
+ default = {};
+ description = "Specification of one or more bitcoind instances.";
};
- users.users.${cfg.user} = {
+ };
+
+ config = mkIf (eachBitcoind != {}) {
+
+ assertions = flatten (mapAttrsToList (bitcoindName: cfg: [
+ {
+ assertion = (cfg.prune != null) -> (builtins.elem cfg.prune [ "disable" "manual" 0 1 ] || (builtins.isInt cfg.prune && cfg.prune >= 550));
+ message = ''
+ If set, services.bitcoind.${bitcoindName}.prune has to be "disable", "manual", 0 , 1 or >= 550.
+ '';
+ }
+ {
+ assertion = (cfg.rpc.users != {}) -> (cfg.configFile == null);
+ message = ''
+ You cannot set both services.bitcoind.${bitcoindName}.rpc.users and services.bitcoind.${bitcoindName}.configFile
+ as they are exclusive. RPC user setting would have no effect if custom configFile would be used.
+ '';
+ }
+ ]) eachBitcoind);
+
+ environment.systemPackages = flatten (mapAttrsToList (bitcoindName: cfg: [
+ cfg.package
+ ]) eachBitcoind);
+
+ systemd.services = mapAttrs' (bitcoindName: cfg: (
+ nameValuePair "bitcoind-${bitcoindName}" (
+ let
+ configFile = pkgs.writeText "bitcoin.conf" ''
+ # If Testnet is enabled, we need to add [test] section
+ # otherwise, some options (e.g.: custom RPC port) will not work
+ ${optionalString cfg.testnet "[test]"}
+ # RPC users
+ ${concatMapStringsSep "\n"
+ (rpcUser: "rpcauth=${rpcUser.name}:${rpcUser.passwordHMAC}")
+ (attrValues cfg.rpc.users)
+ }
+ # Extra config options (from bitcoind nixos service)
+ ${cfg.extraConfig}
+ '';
+ in {
+ description = "Bitcoin daemon";
+ after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ serviceConfig = {
+ User = cfg.user;
+ Group = cfg.group;
+ ExecStart = ''
+ ${cfg.package}/bin/bitcoind \
+ ${if (cfg.configFile != null) then
+ "-conf=${cfg.configFile}"
+ else
+ "-conf=${configFile}"
+ } \
+ -datadir=${cfg.dataDir} \
+ -pid=${cfg.pidFile} \
+ ${optionalString cfg.testnet "-testnet"}\
+ ${optionalString (cfg.port != null) "-port=${toString cfg.port}"}\
+ ${optionalString (cfg.prune != null) "-prune=${toString cfg.prune}"}\
+ ${optionalString (cfg.dbCache != null) "-dbcache=${toString cfg.dbCache}"}\
+ ${optionalString (cfg.rpc.port != null) "-rpcport=${toString cfg.rpc.port}"}\
+ ${toString cfg.extraCmdlineOptions}
+ '';
+ Restart = "on-failure";
+
+ # Hardening measures
+ PrivateTmp = "true";
+ ProtectSystem = "full";
+ NoNewPrivileges = "true";
+ PrivateDevices = "true";
+ MemoryDenyWriteExecute = "true";
+ };
+ }
+ ))) eachBitcoind;
+
+ systemd.tmpfiles.rules = flatten (mapAttrsToList (bitcoindName: cfg: [
+ "d '${cfg.dataDir}' 0770 '${cfg.user}' '${cfg.group}' - -"
+ ]) eachBitcoind);
+
+ users.users = mapAttrs' (bitcoindName: cfg: (
+ nameValuePair "bitcoind-${bitcoindName}" {
name = cfg.user;
group = cfg.group;
description = "Bitcoin daemon user";
home = cfg.dataDir;
isSystemUser = true;
- };
- users.groups.${cfg.group} = {
- name = cfg.group;
- };
+ })) eachBitcoind;
+
+ users.groups = mapAttrs' (bitcoindName: cfg: (
+ nameValuePair "${cfg.group}" { }
+ )) eachBitcoind;
+
};
+
+ meta.maintainers = with maintainers; [ maintainers."1000101" ];
+
}
diff --git a/nixpkgs/nixos/modules/services/networking/blockbook-frontend.nix b/nixpkgs/nixos/modules/services/networking/blockbook-frontend.nix
new file mode 100644
index 00000000000..61938e51e06
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/blockbook-frontend.nix
@@ -0,0 +1,272 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ eachBlockbook = config.services.blockbook-frontend;
+
+ blockbookOpts = { config, lib, name, ...}: {
+
+ options = {
+
+ enable = mkEnableOption "blockbook-frontend application.";
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.blockbook;
+ description = "Which blockbook package to use.";
+ };
+
+ user = mkOption {
+ type = types.str;
+ default = "blockbook-frontend-${name}";
+ description = "The user as which to run blockbook-frontend-${name}.";
+ };
+
+ group = mkOption {
+ type = types.str;
+ default = "${config.user}";
+ description = "The group as which to run blockbook-frontend-${name}.";
+ };
+
+ certFile = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ example = "/etc/secrets/blockbook-frontend-${name}/certFile";
+ description = ''
+ To enable SSL, specify path to the name of certificate files without extension.
+ Expecting <filename>certFile.crt</filename> and <filename>certFile.key</filename>.
+ '';
+ };
+
+ configFile = mkOption {
+ type = with types; nullOr path;
+ default = null;
+ example = "${config.dataDir}/config.json";
+ description = "Location of the blockbook configuration file.";
+ };
+
+ coinName = mkOption {
+ type = types.str;
+ default = "Bitcoin";
+ example = "Bitcoin";
+ description = ''
+ See <link xlink:href="https://github.com/trezor/blockbook/blob/master/bchain/coins/blockchain.go#L61"/>
+ for current of coins supported in master (Note: may differ from release).
+ '';
+ };
+
+ cssDir = mkOption {
+ type = types.path;
+ default = "${config.package}/share/css/";
+ example = "${config.dataDir}/static/css/";
+ description = ''
+ Location of the dir with <filename>main.css</filename> CSS file.
+ By default, the one shipped with the package is used.
+ '';
+ };
+
+ dataDir = mkOption {
+ type = types.path;
+ default = "/var/lib/blockbook-frontend-${name}";
+ description = "Location of blockbook-frontend-${name} data directory.";
+ };
+
+ debug = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Debug mode, return more verbose errors, reload templates on each request.";
+ };
+
+ internal = mkOption {
+ type = types.nullOr types.str;
+ default = ":9030";
+ example = ":9030";
+ description = "Internal http server binding <literal>[address]:port</literal>.";
+ };
+
+ messageQueueBinding = mkOption {
+ type = types.str;
+ default = "tcp://127.0.0.1:38330";
+ example = "tcp://127.0.0.1:38330";
+ description = "Message Queue Binding <literal>address:port</literal>.";
+ };
+
+ public = mkOption {
+ type = types.nullOr types.str;
+ default = ":9130";
+ example = ":9130";
+ description = "Public http server binding <literal>[address]:port</literal>.";
+ };
+
+ rpc = {
+ url = mkOption {
+ type = types.str;
+ default = "http://127.0.0.1";
+ description = "URL for JSON-RPC connections.";
+ };
+
+ port = mkOption {
+ type = types.port;
+ default = 8030;
+ description = "Port for JSON-RPC connections.";
+ };
+
+ user = mkOption {
+ type = types.str;
+ default = "rpc";
+ example = "rpc";
+ description = "Username for JSON-RPC connections.";
+ };
+
+ password = mkOption {
+ type = types.str;
+ default = "rpc";
+ example = "rpc";
+ description = ''
+ RPC password for JSON-RPC connections.
+ Warning: this is stored in cleartext in the Nix store!!!
+ Use <literal>configFile</literal> or <literal>passwordFile</literal> if needed.
+ '';
+ };
+
+ passwordFile = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ description = ''
+ File containing password of the RPC user.
+ Note: This options is ignored when <literal>configFile</literal> is used.
+ '';
+ };
+ };
+
+ sync = mkOption {
+ type = types.bool;
+ default = true;
+ description = "Synchronizes until tip, if together with zeromq, keeps index synchronized.";
+ };
+
+ templateDir = mkOption {
+ type = types.path;
+ default = "${config.package}/share/templates/";
+ example = "${config.dataDir}/templates/static/";
+ description = "Location of the HTML templates. By default, ones shipped with the package are used.";
+ };
+
+ extraConfig = mkOption {
+ type = types.attrs;
+ default = {};
+ example = literalExample '' {
+ alternative_estimate_fee = "whatthefee-disabled";
+ alternative_estimate_fee_params = "{\"url\": \"https://whatthefee.io/data.json\", \"periodSeconds\": 60}";
+ fiat_rates = "coingecko";
+ fiat_rates_params = "{\"url\": \"https://api.coingecko.com/api/v3\", \"coin\": \"bitcoin\", \"periodSeconds\": 60}";
+ coin_shortcut = "BTC";
+ coin_label = "Bitcoin";
+ xpub_magic = 76067358;
+ xpub_magic_segwit_p2sh = 77429938;
+ xpub_magic_segwit_native = 78792518;
+ }'';
+ description = ''
+ Additional configurations to be appended to <filename>coin.conf</filename>.
+ Overrides any already defined configuration options.
+ See <link xlink:href="https://github.com/trezor/blockbook/tree/master/configs/coins"/>
+ for current configuration options supported in master (Note: may differ from release).
+ '';
+ };
+
+ extraCmdLineOptions = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ example = [ "-workers=1" "-dbcache=0" "-logtosderr" ];
+ description = ''
+ Extra command line options to pass to Blockbook.
+ Run blockbook --help to list all available options.
+ '';
+ };
+ };
+ };
+in
+{
+ # interface
+
+ options = {
+ services.blockbook-frontend = mkOption {
+ type = types.attrsOf (types.submodule blockbookOpts);
+ default = {};
+ description = "Specification of one or more blockbook-frontend instances.";
+ };
+ };
+
+ # implementation
+
+ config = mkIf (eachBlockbook != {}) {
+
+ systemd.services = mapAttrs' (blockbookName: cfg: (
+ nameValuePair "blockbook-frontend-${blockbookName}" (
+ let
+ configFile = if cfg.configFile != null then cfg.configFile else
+ pkgs.writeText "config.conf" (builtins.toJSON ( {
+ coin_name = "${cfg.coinName}";
+ rpc_user = "${cfg.rpc.user}";
+ rpc_pass = "${cfg.rpc.password}";
+ rpc_url = "${cfg.rpc.url}:${toString cfg.rpc.port}";
+ message_queue_binding = "${cfg.messageQueueBinding}";
+ } // cfg.extraConfig)
+ );
+ in {
+ description = "blockbook-frontend-${blockbookName} daemon";
+ after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ preStart = ''
+ ln -sf ${cfg.templateDir} ${cfg.dataDir}/static/
+ ln -sf ${cfg.cssDir} ${cfg.dataDir}/static/
+ ${optionalString (cfg.rpc.passwordFile != null && cfg.configFile == null) ''
+ CONFIGTMP=$(mktemp)
+ ${pkgs.jq}/bin/jq ".rpc_pass = \"$(cat ${cfg.rpc.passwordFile})\"" ${configFile} > $CONFIGTMP
+ mv $CONFIGTMP ${cfg.dataDir}/${blockbookName}-config.json
+ ''}
+ '';
+ serviceConfig = {
+ User = cfg.user;
+ Group = cfg.group;
+ ExecStart = ''
+ ${cfg.package}/bin/blockbook \
+ ${if (cfg.rpc.passwordFile != null && cfg.configFile == null) then
+ "-blockchaincfg=${cfg.dataDir}/${blockbookName}-config.json"
+ else
+ "-blockchaincfg=${configFile}"
+ } \
+ -datadir=${cfg.dataDir} \
+ ${optionalString (cfg.sync != false) "-sync"} \
+ ${optionalString (cfg.certFile != null) "-certfile=${toString cfg.certFile}"} \
+ ${optionalString (cfg.debug != false) "-debug"} \
+ ${optionalString (cfg.internal != null) "-internal=${toString cfg.internal}"} \
+ ${optionalString (cfg.public != null) "-public=${toString cfg.public}"} \
+ ${toString cfg.extraCmdLineOptions}
+ '';
+ Restart = "on-failure";
+ WorkingDirectory = cfg.dataDir;
+ LimitNOFILE = 65536;
+ };
+ }
+ ) )) eachBlockbook;
+
+ systemd.tmpfiles.rules = flatten (mapAttrsToList (blockbookName: cfg: [
+ "d ${cfg.dataDir} 0750 ${cfg.user} ${cfg.group} - -"
+ "d ${cfg.dataDir}/static 0750 ${cfg.user} ${cfg.group} - -"
+ ]) eachBlockbook);
+
+ users.users = mapAttrs' (blockbookName: cfg: (
+ nameValuePair "blockbook-frontend-${blockbookName}" {
+ name = cfg.user;
+ group = cfg.group;
+ home = cfg.dataDir;
+ isSystemUser = true;
+ })) eachBlockbook;
+
+ users.groups = mapAttrs' (instanceName: cfg: (
+ nameValuePair "${cfg.group}" { })) eachBlockbook;
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/networking/corerad.nix b/nixpkgs/nixos/modules/services/networking/corerad.nix
index 1a2c4aec665..1c414c53a98 100644
--- a/nixpkgs/nixos/modules/services/networking/corerad.nix
+++ b/nixpkgs/nixos/modules/services/networking/corerad.nix
@@ -4,14 +4,50 @@ with lib;
let
cfg = config.services.corerad;
+
+ writeTOML = name: x:
+ pkgs.runCommandNoCCLocal name {
+ passAsFile = ["config"];
+ config = builtins.toJSON x;
+ buildInputs = [ pkgs.go-toml ];
+ } "jsontoml < $configPath > $out";
+
in {
- meta = {
- maintainers = with maintainers; [ mdlayher ];
- };
+ meta.maintainers = with maintainers; [ mdlayher ];
options.services.corerad = {
enable = mkEnableOption "CoreRAD IPv6 NDP RA daemon";
+ settings = mkOption {
+ type = types.uniq types.attrs;
+ example = literalExample ''
+ {
+ interfaces = [
+ # eth0 is an upstream interface monitoring for IPv6 router advertisements.
+ {
+ name = "eth0";
+ monitor = true;
+ }
+ # eth1 is a downstream interface advertising IPv6 prefixes for SLAAC.
+ {
+ name = "eth1";
+ advertise = true;
+ prefix = [{ prefix = "::/64"; }];
+ }
+ ];
+ # Optionally enable Prometheus metrics.
+ debug = {
+ address = "localhost:9430";
+ prometheus = true;
+ };
+ }
+ '';
+ description = ''
+ Configuration for CoreRAD, see <link xlink:href="https://github.com/mdlayher/corerad/blob/master/internal/config/default.toml"/>
+ for supported values. Ignored if configFile is set.
+ '';
+ };
+
configFile = mkOption {
type = types.path;
example = literalExample "\"\${pkgs.corerad}/etc/corerad/corerad.toml\"";
@@ -27,6 +63,9 @@ in {
};
config = mkIf cfg.enable {
+ # Prefer the config file over settings if both are set.
+ services.corerad.configFile = mkDefault (writeTOML "corerad.toml" cfg.settings);
+
systemd.services.corerad = {
description = "CoreRAD IPv6 NDP RA daemon";
after = [ "network.target" ];
@@ -38,6 +77,8 @@ in {
AmbientCapabilities = "CAP_NET_ADMIN CAP_NET_RAW";
NoNewPrivileges = true;
DynamicUser = true;
+ Type = "notify";
+ NotifyAccess = "main";
ExecStart = "${getBin cfg.package}/bin/corerad -c=${cfg.configFile}";
Restart = "on-failure";
};
diff --git a/nixpkgs/nixos/modules/services/networking/dhcpd.nix b/nixpkgs/nixos/modules/services/networking/dhcpd.nix
index 67f7d811887..8966deac76c 100644
--- a/nixpkgs/nixos/modules/services/networking/dhcpd.nix
+++ b/nixpkgs/nixos/modules/services/networking/dhcpd.nix
@@ -11,7 +11,7 @@ let
''
default-lease-time 600;
max-lease-time 7200;
- authoritative;
+ ${optionalString (!cfg.authoritative) "not "}authoritative;
ddns-update-style interim;
log-facility local1; # see dhcpd.nix
@@ -176,6 +176,16 @@ let
'';
};
+ authoritative = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether the DHCP server shall send DHCPNAK messages to misconfigured
+ clients. If this is not done, clients may be unable to get a correct
+ IP address after changing subnets until their old lease has expired.
+ '';
+ };
+
};
in
diff --git a/nixpkgs/nixos/modules/services/networking/dnschain.nix b/nixpkgs/nixos/modules/services/networking/dnschain.nix
deleted file mode 100644
index 003609ea705..00000000000
--- a/nixpkgs/nixos/modules/services/networking/dnschain.nix
+++ /dev/null
@@ -1,184 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-
-let
- cfgs = config.services;
- cfg = cfgs.dnschain;
-
- dataDir = "/var/lib/dnschain";
- username = "dnschain";
-
- configFile = pkgs.writeText "dnschain.conf" ''
- [log]
- level = info
-
- [dns]
- host = ${cfg.dns.address}
- port = ${toString cfg.dns.port}
- oldDNSMethod = NO_OLD_DNS
- externalIP = ${cfg.dns.externalAddress}
-
- [http]
- host = ${cfg.api.hostname}
- port = ${toString cfg.api.port}
- tlsPort = ${toString cfg.api.tlsPort}
-
- ${cfg.extraConfig}
- '';
-
-in
-
-{
-
- ###### interface
-
- options = {
-
- services.dnschain = {
-
- enable = mkEnableOption ''
- DNSChain, a blockchain based DNS + HTTP server.
- To resolve .bit domains set <literal>services.namecoind.enable = true;</literal>
- and an RPC username/password.
- '';
-
- dns.address = mkOption {
- type = types.str;
- default = "127.0.0.1";
- description = ''
- The IP address the DNSChain resolver will bind to.
- Leave this unchanged if you do not wish to directly expose the resolver.
- '';
- };
-
- dns.externalAddress = mkOption {
- type = types.str;
- default = cfg.dns.address;
- description = ''
- The IP address used by clients to reach the resolver and the value of
- the <literal>namecoin.dns</literal> record. Set this in case the bind address
- is not the actual IP address (e.g. the machine is behind a NAT).
- '';
- };
-
- dns.port = mkOption {
- type = types.int;
- default = 5333;
- description = ''
- The port the DNSChain resolver will bind to.
- '';
- };
-
- api.hostname = mkOption {
- type = types.str;
- default = "0.0.0.0";
- description = ''
- The hostname (or IP address) the DNSChain API server will bind to.
- '';
- };
-
- api.port = mkOption {
- type = types.int;
- default = 8080;
- description = ''
- The port the DNSChain API server (HTTP) will bind to.
- '';
- };
-
- api.tlsPort = mkOption {
- type = types.int;
- default = 4433;
- description = ''
- The port the DNSChain API server (HTTPS) will bind to.
- '';
- };
-
- extraConfig = mkOption {
- type = types.lines;
- default = "";
- example = ''
- [log]
- level = debug
- '';
- description = ''
- Additional options that will be appended to the configuration file.
- '';
- };
-
- };
-
- services.dnsmasq.resolveDNSChainQueries = mkOption {
- type = types.bool;
- default = false;
- description = ''
- Resolve <literal>.bit</literal> top-level domains using DNSChain and namecoin.
- '';
- };
-
- services.pdns-recursor.resolveDNSChainQueries = mkOption {
- type = types.bool;
- default = false;
- description = ''
- Resolve <literal>.bit</literal> top-level domains using DNSChain and namecoin.
- '';
- };
-
- };
-
-
- ###### implementation
-
- config = mkIf cfg.enable {
-
- services.dnsmasq.servers = optionals cfgs.dnsmasq.resolveDNSChainQueries
- [ "/.bit/127.0.0.1#${toString cfg.dns.port}"
- "/.dns/127.0.0.1#${toString cfg.dns.port}"
- ];
-
- services.pdns-recursor = mkIf cfgs.pdns-recursor.resolveDNSChainQueries {
- forwardZonesRecurse =
- { bit = "127.0.0.1:${toString cfg.dns.port}";
- dns = "127.0.0.1:${toString cfg.dns.port}";
- };
- luaConfig =''
- addNTA("bit", "namecoin doesn't support DNSSEC")
- addNTA("dns", "namecoin doesn't support DNSSEC")
- '';
- };
-
- users.users.${username} = {
- description = "DNSChain daemon user";
- home = dataDir;
- createHome = true;
- uid = config.ids.uids.dnschain;
- extraGroups = optional cfgs.namecoind.enable "namecoin";
- };
-
- systemd.services.dnschain = {
- description = "DNSChain daemon";
- after = optional cfgs.namecoind.enable "namecoind.target";
- wantedBy = [ "multi-user.target" ];
-
- serviceConfig = {
- User = "dnschain";
- Restart = "on-failure";
- ExecStart = "${pkgs.nodePackages.dnschain}/bin/dnschain";
- };
-
- preStart = ''
- # Link configuration file into dnschain home directory
- configPath=${dataDir}/.dnschain/dnschain.conf
- mkdir -p ${dataDir}/.dnschain
- if [ "$(realpath $configPath)" != "${configFile}" ]; then
- rm -f $configPath
- ln -s ${configFile} $configPath
- fi
- '';
- };
-
- };
-
- meta.maintainers = with lib.maintainers; [ rnhmjoj ];
-
-}
diff --git a/nixpkgs/nixos/modules/services/networking/go-neb.nix b/nixpkgs/nixos/modules/services/networking/go-neb.nix
new file mode 100644
index 00000000000..991ae38f30a
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/go-neb.nix
@@ -0,0 +1,53 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.go-neb;
+
+ configFile = pkgs.writeText "config.yml" (builtins.toJSON cfg.config);
+in {
+ options.services.go-neb = {
+ enable = mkEnableOption "Extensible matrix bot written in Go";
+
+ bindAddress = mkOption {
+ type = types.str;
+ description = "Port (and optionally address) to listen on.";
+ default = ":4050";
+ };
+
+ baseUrl = mkOption {
+ type = types.str;
+ description = "Public-facing endpoint that can receive webhooks.";
+ };
+
+ config = mkOption {
+ type = types.uniq types.attrs;
+ description = ''
+ Your <filename>config.yaml</filename> as a Nix attribute set.
+ See <link xlink:href="https://github.com/matrix-org/go-neb/blob/master/config.sample.yaml">config.sample.yaml</link>
+ for possible options.
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ systemd.services.go-neb = {
+ description = "Extensible matrix bot written in Go";
+ after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ environment = {
+ BASE_URL = cfg.baseUrl;
+ BIND_ADDRESS = cfg.bindAddress;
+ CONFIG_FILE = configFile;
+ };
+
+ serviceConfig = {
+ ExecStart = "${pkgs.go-neb}/bin/go-neb";
+ DynamicUser = true;
+ };
+ };
+ };
+
+ meta.maintainers = with maintainers; [ hexa maralorn ];
+}
diff --git a/nixpkgs/nixos/modules/services/networking/jicofo.nix b/nixpkgs/nixos/modules/services/networking/jicofo.nix
new file mode 100644
index 00000000000..160a5fea91a
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/jicofo.nix
@@ -0,0 +1,152 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.jicofo;
+in
+{
+ options.services.jicofo = with types; {
+ enable = mkEnableOption "Jitsi Conference Focus - component of Jitsi Meet";
+
+ xmppHost = mkOption {
+ type = str;
+ example = "localhost";
+ description = ''
+ Hostname of the XMPP server to connect to.
+ '';
+ };
+
+ xmppDomain = mkOption {
+ type = nullOr str;
+ example = "meet.example.org";
+ description = ''
+ Domain name of the XMMP server to which to connect as a component.
+
+ If null, <option>xmppHost</option> is used.
+ '';
+ };
+
+ componentPasswordFile = mkOption {
+ type = str;
+ example = "/run/keys/jicofo-component";
+ description = ''
+ Path to file containing component secret.
+ '';
+ };
+
+ userName = mkOption {
+ type = str;
+ default = "focus";
+ description = ''
+ User part of the JID for XMPP user connection.
+ '';
+ };
+
+ userDomain = mkOption {
+ type = str;
+ example = "auth.meet.example.org";
+ description = ''
+ Domain part of the JID for XMPP user connection.
+ '';
+ };
+
+ userPasswordFile = mkOption {
+ type = str;
+ example = "/run/keys/jicofo-user";
+ description = ''
+ Path to file containing password for XMPP user connection.
+ '';
+ };
+
+ bridgeMuc = mkOption {
+ type = str;
+ example = "jvbbrewery@internal.meet.example.org";
+ description = ''
+ JID of the internal MUC used to communicate with Videobridges.
+ '';
+ };
+
+ config = mkOption {
+ type = attrsOf str;
+ default = { };
+ example = literalExample ''
+ {
+ "org.jitsi.jicofo.auth.URL" = "XMPP:jitsi-meet.example.com";
+ }
+ '';
+ description = ''
+ Contents of the <filename>sip-communicator.properties</filename> configuration file for jicofo.
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ services.jicofo.config = mapAttrs (_: v: mkDefault v) {
+ "org.jitsi.jicofo.BRIDGE_MUC" = cfg.bridgeMuc;
+ };
+
+ users.groups.jitsi-meet = {};
+
+ systemd.services.jicofo = let
+ jicofoProps = {
+ "-Dnet.java.sip.communicator.SC_HOME_DIR_LOCATION" = "/etc/jitsi";
+ "-Dnet.java.sip.communicator.SC_HOME_DIR_NAME" = "jicofo";
+ "-Djava.util.logging.config.file" = "/etc/jitsi/jicofo/logging.properties";
+ };
+ in
+ {
+ description = "JItsi COnference FOcus";
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network.target" ];
+
+ restartTriggers = [
+ config.environment.etc."jitsi/jicofo/sip-communicator.properties".source
+ ];
+ environment.JAVA_SYS_PROPS = concatStringsSep " " (mapAttrsToList (k: v: "${k}=${toString v}") jicofoProps);
+
+ script = ''
+ ${pkgs.jicofo}/bin/jicofo \
+ --host=${cfg.xmppHost} \
+ --domain=${if cfg.xmppDomain == null then cfg.xmppHost else cfg.xmppDomain} \
+ --secret=$(cat ${cfg.componentPasswordFile}) \
+ --user_name=${cfg.userName} \
+ --user_domain=${cfg.userDomain} \
+ --user_password=$(cat ${cfg.userPasswordFile})
+ '';
+
+ serviceConfig = {
+ Type = "exec";
+
+ DynamicUser = true;
+ User = "jicofo";
+ Group = "jitsi-meet";
+
+ CapabilityBoundingSet = "";
+ NoNewPrivileges = true;
+ ProtectSystem = "strict";
+ ProtectHome = true;
+ PrivateTmp = true;
+ PrivateDevices = true;
+ ProtectHostname = true;
+ ProtectKernelTunables = true;
+ ProtectKernelModules = true;
+ ProtectControlGroups = true;
+ RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
+ RestrictNamespaces = true;
+ LockPersonality = true;
+ RestrictRealtime = true;
+ RestrictSUIDSGID = true;
+ };
+ };
+
+ environment.etc."jitsi/jicofo/sip-communicator.properties".source =
+ pkgs.writeText "sip-communicator.properties" (
+ generators.toKeyValue {} cfg.config
+ );
+ environment.etc."jitsi/jicofo/logging.properties".source =
+ mkDefault "${pkgs.jicofo}/etc/jitsi/jicofo/logging.properties-journal";
+ };
+
+ meta.maintainers = lib.teams.jitsi.members;
+}
diff --git a/nixpkgs/nixos/modules/services/networking/jitsi-videobridge.nix b/nixpkgs/nixos/modules/services/networking/jitsi-videobridge.nix
new file mode 100644
index 00000000000..5482e997a40
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/jitsi-videobridge.nix
@@ -0,0 +1,276 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.jitsi-videobridge;
+ attrsToArgs = a: concatStringsSep " " (mapAttrsToList (k: v: "${k}=${toString v}") a);
+
+ # HOCON is a JSON superset that videobridge2 uses for configuration.
+ # It can substitute environment variables which we use for passwords here.
+ # https://github.com/lightbend/config/blob/master/README.md
+ #
+ # Substitution for environment variable FOO is represented as attribute set
+ # { __hocon_envvar = "FOO"; }
+ toHOCON = x: if isAttrs x && x ? __hocon_envvar then ("\${" + x.__hocon_envvar + "}")
+ else if isAttrs x then "{${ concatStringsSep "," (mapAttrsToList (k: v: ''"${k}":${toHOCON v}'') x) }}"
+ else if isList x then "[${ concatMapStringsSep "," toHOCON x }]"
+ else builtins.toJSON x;
+
+ # We're passing passwords in environment variables that have names generated
+ # from an attribute name, which may not be a valid bash identifier.
+ toVarName = s: "XMPP_PASSWORD_" + stringAsChars (c: if builtins.match "[A-Za-z0-9]" c != null then c else "_") s;
+
+ defaultJvbConfig = {
+ videobridge = {
+ ice = {
+ tcp = {
+ enabled = true;
+ port = 4443;
+ };
+ udp.port = 10000;
+ };
+ stats = {
+ enabled = true;
+ transports = [ { type = "muc"; } ];
+ };
+ apis.xmpp-client.configs = flip mapAttrs cfg.xmppConfigs (name: xmppConfig: {
+ hostname = xmppConfig.hostName;
+ domain = xmppConfig.domain;
+ username = xmppConfig.userName;
+ password = { __hocon_envvar = toVarName name; };
+ muc_jids = xmppConfig.mucJids;
+ muc_nickname = xmppConfig.mucNickname;
+ disable_certificate_verification = xmppConfig.disableCertificateVerification;
+ });
+ };
+ };
+
+ # Allow overriding leaves of the default config despite types.attrs not doing any merging.
+ jvbConfig = recursiveUpdate defaultJvbConfig cfg.config;
+in
+{
+ options.services.jitsi-videobridge = with types; {
+ enable = mkEnableOption "Jitsi Videobridge, a WebRTC compatible video router";
+
+ config = mkOption {
+ type = attrs;
+ default = { };
+ example = literalExample ''
+ {
+ videobridge = {
+ ice.udp.port = 5000;
+ websockets = {
+ enabled = true;
+ server-id = "jvb1";
+ };
+ };
+ }
+ '';
+ description = ''
+ Videobridge configuration.
+
+ See <link xlink:href="https://github.com/jitsi/jitsi-videobridge/blob/master/src/main/resources/reference.conf" />
+ for default configuration with comments.
+ '';
+ };
+
+ xmppConfigs = mkOption {
+ description = ''
+ XMPP servers to connect to.
+
+ See <link xlink:href="https://github.com/jitsi/jitsi-videobridge/blob/master/doc/muc.md" /> for more information.
+ '';
+ default = { };
+ example = literalExample ''
+ {
+ "localhost" = {
+ hostName = "localhost";
+ userName = "jvb";
+ domain = "auth.xmpp.example.org";
+ passwordFile = "/var/lib/jitsi-meet/videobridge-secret";
+ mucJids = "jvbbrewery@internal.xmpp.example.org";
+ };
+ }
+ '';
+ type = attrsOf (submodule ({ name, ... }: {
+ options = {
+ hostName = mkOption {
+ type = str;
+ example = "xmpp.example.org";
+ description = ''
+ Hostname of the XMPP server to connect to. Name of the attribute set is used by default.
+ '';
+ };
+ domain = mkOption {
+ type = nullOr str;
+ default = null;
+ example = "auth.xmpp.example.org";
+ description = ''
+ Domain part of JID of the XMPP user, if it is different from hostName.
+ '';
+ };
+ userName = mkOption {
+ type = str;
+ default = "jvb";
+ description = ''
+ User part of the JID.
+ '';
+ };
+ passwordFile = mkOption {
+ type = str;
+ example = "/run/keys/jitsi-videobridge-xmpp1";
+ description = ''
+ File containing the password for the user.
+ '';
+ };
+ mucJids = mkOption {
+ type = str;
+ example = "jvbbrewery@internal.xmpp.example.org";
+ description = ''
+ JID of the MUC to join. JiCoFo needs to be configured to join the same MUC.
+ '';
+ };
+ mucNickname = mkOption {
+ # Upstream DEBs use UUID, let's use hostname instead.
+ type = str;
+ description = ''
+ Videobridges use the same XMPP account and need to be distinguished by the
+ nickname (aka resource part of the JID). By default, system hostname is used.
+ '';
+ };
+ disableCertificateVerification = mkOption {
+ type = bool;
+ default = false;
+ description = ''
+ Whether to skip validation of the server's certificate.
+ '';
+ };
+ };
+ config = {
+ hostName = mkDefault name;
+ mucNickname = mkDefault (builtins.replaceStrings [ "." ] [ "-" ] (
+ config.networking.hostName + optionalString (config.networking.domain != null) ".${config.networking.domain}"
+ ));
+ };
+ }));
+ };
+
+ nat = {
+ localAddress = mkOption {
+ type = nullOr str;
+ default = null;
+ example = "192.168.1.42";
+ description = ''
+ Local address when running behind NAT.
+ '';
+ };
+
+ publicAddress = mkOption {
+ type = nullOr str;
+ default = null;
+ example = "1.2.3.4";
+ description = ''
+ Public address when running behind NAT.
+ '';
+ };
+ };
+
+ extraProperties = mkOption {
+ type = attrsOf str;
+ default = { };
+ description = ''
+ Additional Java properties passed to jitsi-videobridge.
+ '';
+ };
+
+ openFirewall = mkOption {
+ type = bool;
+ default = false;
+ description = ''
+ Whether to open ports in the firewall for the videobridge.
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ users.groups.jitsi-meet = {};
+
+ services.jitsi-videobridge.extraProperties = optionalAttrs (cfg.nat.localAddress != null) {
+ "org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS" = cfg.nat.localAddress;
+ "org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS" = cfg.nat.publicAddress;
+ };
+
+ systemd.services.jitsi-videobridge2 = let
+ jvbProps = {
+ "-Dnet.java.sip.communicator.SC_HOME_DIR_LOCATION" = "/etc/jitsi";
+ "-Dnet.java.sip.communicator.SC_HOME_DIR_NAME" = "videobridge";
+ "-Djava.util.logging.config.file" = "/etc/jitsi/videobridge/logging.properties";
+ "-Dconfig.file" = pkgs.writeText "jvb.conf" (toHOCON jvbConfig);
+ } // (mapAttrs' (k: v: nameValuePair "-D${k}" v) cfg.extraProperties);
+ in
+ {
+ aliases = [ "jitsi-videobridge.service" ];
+ description = "Jitsi Videobridge";
+ after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+
+ environment.JAVA_SYS_PROPS = attrsToArgs jvbProps;
+
+ script = (concatStrings (mapAttrsToList (name: xmppConfig:
+ "export ${toVarName name}=$(cat ${xmppConfig.passwordFile})\n"
+ ) cfg.xmppConfigs))
+ + ''
+ ${pkgs.jitsi-videobridge}/bin/jitsi-videobridge --apis=none
+ '';
+
+ serviceConfig = {
+ Type = "exec";
+
+ DynamicUser = true;
+ User = "jitsi-videobridge";
+ Group = "jitsi-meet";
+
+ CapabilityBoundingSet = "";
+ NoNewPrivileges = true;
+ ProtectSystem = "strict";
+ ProtectHome = true;
+ PrivateTmp = true;
+ PrivateDevices = true;
+ ProtectHostname = true;
+ ProtectKernelTunables = true;
+ ProtectKernelModules = true;
+ ProtectControlGroups = true;
+ RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
+ RestrictNamespaces = true;
+ LockPersonality = true;
+ RestrictRealtime = true;
+ RestrictSUIDSGID = true;
+
+ TasksMax = 65000;
+ LimitNPROC = 65000;
+ LimitNOFILE = 65000;
+ };
+ };
+
+ environment.etc."jitsi/videobridge/logging.properties".source =
+ mkDefault "${pkgs.jitsi-videobridge}/etc/jitsi/videobridge/logging.properties-journal";
+
+ # (from videobridge2 .deb)
+ # this sets the max, so that we can bump the JVB UDP single port buffer size.
+ boot.kernel.sysctl."net.core.rmem_max" = mkDefault 10485760;
+ boot.kernel.sysctl."net.core.netdev_max_backlog" = mkDefault 100000;
+
+ networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall
+ [ jvbConfig.videobridge.ice.tcp.port ];
+ networking.firewall.allowedUDPPorts = mkIf cfg.openFirewall
+ [ jvbConfig.videobridge.ice.udp.port ];
+
+ assertions = [{
+ message = "publicAddress must be set if and only if localAddress is set";
+ assertion = (cfg.nat.publicAddress == null) == (cfg.nat.localAddress == null);
+ }];
+ };
+
+ meta.maintainers = lib.teams.jitsi.members;
+}
diff --git a/nixpkgs/nixos/modules/services/networking/kresd.nix b/nixpkgs/nixos/modules/services/networking/kresd.nix
index c5a84eebd46..26ddd4e811e 100644
--- a/nixpkgs/nixos/modules/services/networking/kresd.nix
+++ b/nixpkgs/nixos/modules/services/networking/kresd.nix
@@ -134,8 +134,7 @@ in {
CacheDirectoryMode = "0750";
};
- environment.etc."tmpfiles.d/knot-resolver.conf".source =
- "${package}/lib/tmpfiles.d/knot-resolver.conf";
+ systemd.tmpfiles.packages = [ package ];
# Try cleaning up the previously default location of cache file.
# Note that /var/cache/* should always be safe to remove.
diff --git a/nixpkgs/nixos/modules/services/networking/namecoind.nix b/nixpkgs/nixos/modules/services/networking/namecoind.nix
index ead7f085943..6ca99e1321b 100644
--- a/nixpkgs/nixos/modules/services/networking/namecoind.nix
+++ b/nixpkgs/nixos/modules/services/networking/namecoind.nix
@@ -149,11 +149,6 @@ in
config = mkIf cfg.enable {
- services.dnschain.extraConfig = ''
- [namecoin]
- config = ${configFile}
- '';
-
users.users.namecoin = {
uid = config.ids.uids.namecoin;
description = "Namecoin daemon user";
diff --git a/nixpkgs/nixos/modules/services/networking/ncdns.nix b/nixpkgs/nixos/modules/services/networking/ncdns.nix
new file mode 100644
index 00000000000..c1832ad1752
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/ncdns.nix
@@ -0,0 +1,278 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfgs = config.services;
+ cfg = cfgs.ncdns;
+
+ dataDir = "/var/lib/ncdns";
+ username = "ncdns";
+
+ valueType = with types; oneOf [ int str bool path ]
+ // { description = "setting type (integer, string, bool or path)"; };
+
+ configType = with types; attrsOf (nullOr (either valueType configType))
+ // { description = ''
+ ncdns.conf configuration type. The format consists of an
+ attribute set of settings. Each setting can be either `null`,
+ a value or an attribute set. The allowed values are integers,
+ strings, booleans or paths.
+ '';
+ };
+
+ configFile = pkgs.runCommand "ncdns.conf"
+ { json = builtins.toJSON cfg.settings;
+ passAsFile = [ "json" ];
+ }
+ "${pkgs.remarshal}/bin/json2toml < $jsonPath > $out";
+
+ defaultFiles = {
+ public = "${dataDir}/bit.key";
+ private = "${dataDir}/bit.private";
+ zonePublic = "${dataDir}/bit-zone.key";
+ zonePrivate = "${dataDir}/bit-zone.private";
+ };
+
+ # if all keys are the default value
+ needsKeygen = all id (flip mapAttrsToList cfg.dnssec.keys
+ (n: v: v == getAttr n defaultFiles));
+
+ mkDefaultAttrs = mapAttrs (n: v: mkDefault v);
+
+in
+
+{
+
+ ###### interface
+
+ options = {
+
+ services.ncdns = {
+
+ enable = mkEnableOption ''
+ ncdns, a Go daemon to bridge Namecoin to DNS.
+ To resolve .bit domains set <literal>services.namecoind.enable = true;</literal>
+ and an RPC username/password
+ '';
+
+ address = mkOption {
+ type = types.str;
+ default = "127.0.0.1";
+ description = ''
+ The IP address the ncdns resolver will bind to. Leave this unchanged
+ if you do not wish to directly expose the resolver.
+ '';
+ };
+
+ port = mkOption {
+ type = types.port;
+ default = 5333;
+ description = ''
+ The port the ncdns resolver will bind to.
+ '';
+ };
+
+ identity.hostname = mkOption {
+ type = types.str;
+ default = config.networking.hostName;
+ example = "example.com";
+ description = ''
+ The hostname of this ncdns instance, which defaults to the machine
+ hostname. If specified, ncdns lists the hostname as an NS record at
+ the zone apex:
+ <programlisting>
+ bit. IN NS ns1.example.com.
+ </programlisting>
+ If unset ncdns will generate an internal psuedo-hostname under the
+ zone, which will resolve to the value of
+ <option>services.ncdns.identity.address</option>.
+ If you are only using ncdns locally you can ignore this.
+ '';
+ };
+
+ identity.hostmaster = mkOption {
+ type = types.str;
+ default = "";
+ example = "root@example.com";
+ description = ''
+ An email address for the SOA record at the bit zone.
+ If you are only using ncdns locally you can ignore this.
+ '';
+ };
+
+ identity.address = mkOption {
+ type = types.str;
+ default = "127.127.127.127";
+ description = ''
+ The IP address the hostname specified in
+ <option>services.ncdns.identity.hostname</option> should resolve to.
+ If you are only using ncdns locally you can ignore this.
+ '';
+ };
+
+ dnssec.enable = mkEnableOption ''
+ DNSSEC support in ncdns. This will generate KSK and ZSK keypairs
+ (unless provided via the options
+ <option>services.ncdns.dnssec.publicKey</option>,
+ <option>services.ncdns.dnssec.privateKey</option> etc.) and add a trust
+ anchor to recursive resolvers
+ '';
+
+ dnssec.keys.public = mkOption {
+ type = types.path;
+ default = defaultFiles.public;
+ description = ''
+ Path to the file containing the KSK public key.
+ The key can be generated using the <literal>dnssec-keygen</literal>
+ command, provided by the package <package>bind</package> as follows:
+ <programlisting>
+ $ dnssec-keygen -a RSASHA256 -3 -b 2048 -f KSK bit
+ </programlisting>
+ '';
+ };
+
+ dnssec.keys.private = mkOption {
+ type = types.path;
+ default = defaultFiles.private;
+ description = ''
+ Path to the file containing the KSK private key.
+ '';
+ };
+
+ dnssec.keys.zonePublic = mkOption {
+ type = types.path;
+ default = defaultFiles.zonePublic;
+ description = ''
+ Path to the file containing the ZSK public key.
+ The key can be generated using the <literal>dnssec-keygen</literal>
+ command, provided by the package <package>bind</package> as follows:
+ <programlisting>
+ $ dnssec-keygen -a RSASHA256 -3 -b 2048 bit
+ </programlisting>
+ '';
+ };
+
+ dnssec.keys.zonePrivate = mkOption {
+ type = types.path;
+ default = defaultFiles.zonePrivate;
+ description = ''
+ Path to the file containing the ZSK private key.
+ '';
+ };
+
+ settings = mkOption {
+ type = configType;
+ default = { };
+ example = literalExample ''
+ { # enable webserver
+ ncdns.httplistenaddr = ":8202";
+
+ # synchronize TLS certs
+ certstore.nss = true;
+ # note: all paths are relative to the config file
+ certstore.nsscertdir = "../../var/lib/ncdns";
+ certstore.nssdbdir = "../../home/alice/.pki/nssdb";
+ }
+ '';
+ description = ''
+ ncdns settings. Use this option to configure ncds
+ settings not exposed in a NixOS option or to bypass one.
+ See the example ncdns.conf file at <link xlink:href="
+ https://git.io/JfX7g"/> for the available options.
+ '';
+ };
+
+ };
+
+ services.pdns-recursor.resolveNamecoin = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Resolve <literal>.bit</literal> top-level domains using ncdns and namecoin.
+ '';
+ };
+
+ };
+
+
+ ###### implementation
+
+ config = mkIf cfg.enable {
+
+ services.pdns-recursor = mkIf cfgs.pdns-recursor.resolveNamecoin {
+ forwardZonesRecurse.bit = "127.0.0.1:${toString cfg.port}";
+ luaConfig =
+ if cfg.dnssec.enable
+ then ''readTrustAnchorsFromFile("${cfg.dnssec.keys.public}")''
+ else ''addNTA("bit", "namecoin DNSSEC disabled")'';
+ };
+
+ # Avoid pdns-recursor not finding the DNSSEC keys
+ systemd.services.pdns-recursor = mkIf cfgs.pdns-recursor.resolveNamecoin {
+ after = [ "ncdns.service" ];
+ wants = [ "ncdns.service" ];
+ };
+
+ services.ncdns.settings = mkDefaultAttrs {
+ ncdns =
+ { # Namecoin RPC
+ namecoinrpcaddress =
+ "${cfgs.namecoind.rpc.address}:${toString cfgs.namecoind.rpc.port}";
+ namecoinrpcusername = cfgs.namecoind.rpc.user;
+ namecoinrpcpassword = cfgs.namecoind.rpc.password;
+
+ # Identity
+ selfname = cfg.identity.hostname;
+ hostmaster = cfg.identity.hostmaster;
+ selfip = cfg.identity.address;
+
+ # Other
+ bind = "${cfg.address}:${toString cfg.port}";
+ }
+ // optionalAttrs cfg.dnssec.enable
+ { # DNSSEC
+ publickey = "../.." + cfg.dnssec.keys.public;
+ privatekey = "../.." + cfg.dnssec.keys.private;
+ zonepublickey = "../.." + cfg.dnssec.keys.zonePublic;
+ zoneprivatekey = "../.." + cfg.dnssec.keys.zonePrivate;
+ };
+
+ # Daemon
+ service.daemon = true;
+ xlog.journal = true;
+ };
+
+ users.users.ncdns =
+ { description = "ncdns daemon user"; };
+
+ systemd.services.ncdns = {
+ description = "ncdns daemon";
+ after = [ "namecoind.service" ];
+ wantedBy = [ "multi-user.target" ];
+
+ serviceConfig = {
+ User = "ncdns";
+ StateDirectory = "ncdns";
+ Restart = "on-failure";
+ ExecStart = "${pkgs.ncdns}/bin/ncdns -conf=${configFile}";
+ };
+
+ preStart = optionalString (cfg.dnssec.enable && needsKeygen) ''
+ cd ${dataDir}
+ if [ ! -e bit.key ]; then
+ ${pkgs.bind}/bin/dnssec-keygen -a RSASHA256 -3 -b 2048 bit
+ mv Kbit.*.key bit-zone.key
+ mv Kbit.*.private bit-zone.private
+ ${pkgs.bind}/bin/dnssec-keygen -a RSASHA256 -3 -b 2048 -f KSK bit
+ mv Kbit.*.key bit.key
+ mv Kbit.*.private bit.private
+ fi
+ '';
+ };
+
+ };
+
+ meta.maintainers = with lib.maintainers; [ rnhmjoj ];
+
+}
diff --git a/nixpkgs/nixos/modules/services/networking/nsd.nix b/nixpkgs/nixos/modules/services/networking/nsd.nix
index 6e3eed0c557..3ecbd06ee41 100644
--- a/nixpkgs/nixos/modules/services/networking/nsd.nix
+++ b/nixpkgs/nixos/modules/services/networking/nsd.nix
@@ -11,8 +11,6 @@ let
# build nsd with the options needed for the given config
nsdPkg = pkgs.nsd.override {
- configFile = "${configFile}/nsd.conf";
-
bind8Stats = cfg.bind8Stats;
ipv6 = cfg.ipv6;
ratelimit = cfg.ratelimit.enable;
@@ -897,7 +895,10 @@ in
+ "want, please enable 'services.nsd.rootServer'.";
};
- environment.systemPackages = [ nsdPkg ];
+ environment = {
+ systemPackages = [ nsdPkg ];
+ etc."nsd/nsd.conf".source = "${configFile}/nsd.conf";
+ };
users.groups.${username}.gid = config.ids.gids.nsd;
diff --git a/nixpkgs/nixos/modules/services/networking/onedrive.nix b/nixpkgs/nixos/modules/services/networking/onedrive.nix
new file mode 100644
index 00000000000..a945250fa9e
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/onedrive.nix
@@ -0,0 +1,72 @@
+{ config, lib, pkgs, ... }:
+let
+ cfg = config.services.onedrive;
+
+ onedriveLauncher = pkgs.writeShellScriptBin
+ "onedrive-launcher"
+ ''
+ # XDG_CONFIG_HOME is not recognized in the environment here.
+ if [ -f $HOME/.config/onedrive-launcher ]
+ then
+ # Hopefully using underscore boundary helps locate variables
+ for _onedrive_config_dirname_ in $(cat $HOME/.config/onedrive-launcher | grep -v '[ \t]*#' )
+ do
+ systemctl --user start onedrive@$_onedrive_config_dirname_
+ done
+ else
+ systemctl --user start onedrive@onedrive
+ fi
+ ''
+ ;
+
+in {
+ ### Documentation
+ # meta.doc = ./onedrive.xml;
+
+ ### Interface
+
+ options.services.onedrive = {
+ enable = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ description = "Enable OneDrive service";
+ };
+
+ package = lib.mkOption {
+ type = lib.types.package;
+ default = pkgs.onedrive;
+ defaultText = "pkgs.onedrive";
+ example = lib.literalExample "pkgs.onedrive";
+ description = ''
+ OneDrive package to use.
+ '';
+ };
+ };
+### Implementation
+
+ config = lib.mkIf cfg.enable {
+ environment.systemPackages = [ cfg.package ];
+
+ systemd.user.services."onedrive@" = {
+ description = "Onedrive sync service";
+
+ serviceConfig = {
+ Type = "simple";
+ ExecStart = ''
+ ${cfg.package}/bin/onedrive --monitor --verbose --confdir=%h/.config/%i
+ '';
+ Restart="on-failure";
+ RestartSec=3;
+ RestartPreventExitStatus=3;
+ };
+ };
+
+ systemd.user.services.onedrive-launcher = {
+ wantedBy = [ "default.target" ];
+ serviceConfig = {
+ Type = "oneshot";
+ ExecStart = "${onedriveLauncher}/bin/onedrive-launcher";
+ };
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/networking/onedrive.xml b/nixpkgs/nixos/modules/services/networking/onedrive.xml
new file mode 100644
index 00000000000..5a9dcf01aee
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/onedrive.xml
@@ -0,0 +1,34 @@
+<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="onedrive">
+ <title>Microsoft OneDrive</title>
+ <para>
+ Microsoft Onedrive is a popular cloud file-hosting service, used by 85% of Fortune 500 companies. NixOS uses a popular OneDrive client for Linux maintained by github user abraunegg. The Linux client is excellent and allows customization of which files or paths to download, not much unlike the default Windows OneDrive client by Microsoft itself. The client allows syncing with multiple onedrive accounts at the same time, of any type- OneDrive personal, OneDrive business, Office365 and Sharepoint libraries, without any additional charge.
+ </para>
+ <para>
+ For more information, guides and documentation, see <link xlink:href="https://abraunegg.github.io/"/>.
+ </para>
+ <para>
+ To enable OneDrive support, add the following to your <filename>configuration.nix</filename>:
+<programlisting>
+<xref linkend="opt-services.onedrive.enable"/> = true;
+</programlisting>
+ This installs the <literal>onedrive</literal> package and a service <literal>onedriveLauncher</literal> which will instantiate a <literal>onedrive</literal> service for all your OneDrive accounts. Follow the steps in documentation of the onedrive client to setup your accounts. To use the service with multiple accounts, create a file named <filename>onedrive-launcher</filename> in <filename>~/.config</filename> and add the filename of the config directory, relative to <filename>~/.config</filename>. For example, if you have two OneDrive accounts with configs in <filename>~/.config/onedrive_bob_work</filename> and <filename>~/.config/onedrive_bob_personal</filename>, add the following lines:
+<programlisting>
+onedrive_bob_work
+# Not in use:
+# onedrive_bob_office365
+onedrive_bob_personal
+</programlisting>
+ No such file needs to be created if you are using only a single OneDrive account with config in the default location <filename>~/.config/onedrive</filename>, in the absence of <filename>~/.config/onedrive-launcher</filename>, only a single service is instantiated, with default config path.
+</para>
+
+ <para>
+ If you wish to use a custom OneDrive package, say from another channel, add the following line:
+<programlisting>
+<xref linkend="opt-services.onedrive.package"/> = pkgs.unstable.onedrive;
+</programlisting>
+ </para>
+</chapter>
diff --git a/nixpkgs/nixos/modules/services/networking/radicale.nix b/nixpkgs/nixos/modules/services/networking/radicale.nix
index 30bf22586f8..5af035fd59e 100644
--- a/nixpkgs/nixos/modules/services/networking/radicale.nix
+++ b/nixpkgs/nixos/modules/services/networking/radicale.nix
@@ -8,8 +8,10 @@ let
confFile = pkgs.writeText "radicale.conf" cfg.config;
- # This enables us to default to version 2 while still not breaking configurations of people with version 1
- defaultPackage = if versionAtLeast config.system.stateVersion "17.09" then {
+ defaultPackage = if versionAtLeast config.system.stateVersion "20.09" then {
+ pkg = pkgs.radicale3;
+ text = "pkgs.radicale3";
+ } else if versionAtLeast config.system.stateVersion "17.09" then {
pkg = pkgs.radicale2;
text = "pkgs.radicale2";
} else {
@@ -35,8 +37,9 @@ in
defaultText = defaultPackage.text;
description = ''
Radicale package to use. This defaults to version 1.x if
- <literal>system.stateVersion &lt; 17.09</literal> and version 2.x
- otherwise.
+ <literal>system.stateVersion &lt; 17.09</literal>, version 2.x if
+ <literal>17.09 ≤ system.stateVersion &lt; 20.09</literal>, and
+ version 3.x otherwise.
'';
};
diff --git a/nixpkgs/nixos/modules/services/networking/resilio.nix b/nixpkgs/nixos/modules/services/networking/resilio.nix
index e74e03fc0b0..6193d7340fc 100644
--- a/nixpkgs/nixos/modules/services/networking/resilio.nix
+++ b/nixpkgs/nixos/modules/services/networking/resilio.nix
@@ -30,12 +30,12 @@ let
download_limit = cfg.downloadLimit;
upload_limit = cfg.uploadLimit;
lan_encrypt_data = cfg.encryptLAN;
- } // optionalAttrs cfg.enableWebUI {
+ } // optionalAttrs (cfg.directoryRoot != "") { directory_root = cfg.directoryRoot; }
+ // optionalAttrs cfg.enableWebUI {
webui = { listen = "${cfg.httpListenAddr}:${toString cfg.httpListenPort}"; } //
(optionalAttrs (cfg.httpLogin != "") { login = cfg.httpLogin; }) //
(optionalAttrs (cfg.httpPass != "") { password = cfg.httpPass; }) //
- (optionalAttrs (cfg.apiKey != "") { api_key = cfg.apiKey; }) //
- (optionalAttrs (cfg.directoryRoot != "") { directory_root = cfg.directoryRoot; });
+ (optionalAttrs (cfg.apiKey != "") { api_key = cfg.apiKey; });
} // optionalAttrs (sharedFoldersRecord != []) {
shared_folders = sharedFoldersRecord;
}));
@@ -109,8 +109,8 @@ in
httpListenAddr = mkOption {
type = types.str;
- default = "0.0.0.0";
- example = "1.2.3.4";
+ default = "[::1]";
+ example = "0.0.0.0";
description = ''
HTTP address to bind to.
'';
@@ -206,16 +206,16 @@ in
If you would like to be able to modify the contents of this
directories, it is recommended that you make your user a
- member of the <literal>resilio</literal> group.
+ member of the <literal>rslsync</literal> group.
Directories in this list should be in the
- <literal>resilio</literal> group, and that group must have
+ <literal>rslsync</literal> group, and that group must have
write access to the directory. It is also recommended that
<literal>chmod g+s</literal> is applied to the directory
so that any sub directories created will also belong to
- the <literal>resilio</literal> group. Also,
- <literal>setfacl -d -m group:resilio:rwx</literal> and
- <literal>setfacl -m group:resilio:rwx</literal> should also
+ the <literal>rslsync</literal> group. Also,
+ <literal>setfacl -d -m group:rslsync:rwx</literal> and
+ <literal>setfacl -m group:rslsync:rwx</literal> should also
be applied so that the sub directories are writable by
the group.
'';
diff --git a/nixpkgs/nixos/modules/services/networking/skydns.nix b/nixpkgs/nixos/modules/services/networking/skydns.nix
index e79d6de9264..ea466de9327 100644
--- a/nixpkgs/nixos/modules/services/networking/skydns.nix
+++ b/nixpkgs/nixos/modules/services/networking/skydns.nix
@@ -64,7 +64,7 @@ in {
extraConfig = mkOption {
default = {};
type = types.attrsOf types.str;
- description = "Skydns attribute set of extra config options passed as environemnt variables.";
+ description = "Skydns attribute set of extra config options passed as environment variables.";
};
};
diff --git a/nixpkgs/nixos/modules/services/networking/sslh.nix b/nixpkgs/nixos/modules/services/networking/sslh.nix
index c4fa370a5fe..0921febba66 100644
--- a/nixpkgs/nixos/modules/services/networking/sslh.nix
+++ b/nixpkgs/nixos/modules/services/networking/sslh.nix
@@ -15,7 +15,11 @@ let
listen:
(
- { host: "${cfg.listenAddress}"; port: "${toString cfg.port}"; }
+ ${
+ concatMapStringsSep ",\n"
+ (addr: ''{ host: "${addr}"; port: "${toString cfg.port}"; }'')
+ cfg.listenAddresses
+ }
);
${cfg.appendConfig}
@@ -33,6 +37,10 @@ let
'';
in
{
+ imports = [
+ (mkRenamedOptionModule [ "services" "sslh" "listenAddress" ] [ "services" "sslh" "listenAddresses" ])
+ ];
+
options = {
services.sslh = {
enable = mkEnableOption "sslh";
@@ -55,10 +63,10 @@ in
description = "Will the services behind sslh (Apache, sshd and so on) see the external IP and ports as if the external world connected directly to them";
};
- listenAddress = mkOption {
- type = types.str;
- default = "0.0.0.0";
- description = "Listening address or hostname.";
+ listenAddresses = mkOption {
+ type = types.coercedTo types.str singleton (types.listOf types.str);
+ default = [ "0.0.0.0" "[::]" ];
+ description = "Listening addresses or hostnames.";
};
port = mkOption {
diff --git a/nixpkgs/nixos/modules/services/networking/tinc.nix b/nixpkgs/nixos/modules/services/networking/tinc.nix
index e98aafc2093..725bd9bf940 100644
--- a/nixpkgs/nixos/modules/services/networking/tinc.nix
+++ b/nixpkgs/nixos/modules/services/networking/tinc.nix
@@ -48,6 +48,14 @@ in
'';
};
+ rsaPrivateKeyFile = mkOption {
+ default = null;
+ type = types.nullOr types.path;
+ description = ''
+ Path of the private RSA keyfile.
+ '';
+ };
+
debugLevel = mkOption {
default = 0;
type = types.addCheck types.int (l: l >= 0 && l <= 5);
@@ -139,6 +147,7 @@ in
Name = ${if data.name == null then "$HOST" else data.name}
DeviceType = ${data.interfaceType}
${optionalString (data.ed25519PrivateKeyFile != null) "Ed25519PrivateKeyFile = ${data.ed25519PrivateKeyFile}"}
+ ${optionalString (data.rsaPrivateKeyFile != null) "PrivateKeyFile = ${data.rsaPrivateKeyFile}"}
${optionalString (data.listenAddress != null) "ListenAddress = ${data.listenAddress}"}
${optionalString (data.bindToAddress != null) "BindToAddress = ${data.bindToAddress}"}
Interface = tinc.${network}
@@ -170,12 +179,15 @@ in
# Determine how we should generate our keys
if type tinc >/dev/null 2>&1; then
# Tinc 1.1+ uses the tinc helper application for key generation
- ${if data.ed25519PrivateKeyFile != null then " # Keyfile managed by nix" else ''
+ ${if data.ed25519PrivateKeyFile != null then " # ed25519 Keyfile managed by nix" else ''
# Prefer ED25519 keys (only in 1.1+)
[ -f "/etc/tinc/${network}/ed25519_key.priv" ] || tinc -n ${network} generate-ed25519-keys
''}
- # Otherwise use RSA keys
+ ${if data.rsaPrivateKeyFile != null then " # RSA Keyfile managed by nix" else ''
[ -f "/etc/tinc/${network}/rsa_key.priv" ] || tinc -n ${network} generate-rsa-keys 4096
+ ''}
+ # In case there isn't anything to do
+ true
else
# Tinc 1.0 uses the tincd application
[ -f "/etc/tinc/${network}/rsa_key.priv" ] || tincd -n ${network} -K 4096
diff --git a/nixpkgs/nixos/modules/services/networking/unifi.nix b/nixpkgs/nixos/modules/services/networking/unifi.nix
index 4bdfa8143dc..62bcf7a1497 100644
--- a/nixpkgs/nixos/modules/services/networking/unifi.nix
+++ b/nixpkgs/nixos/modules/services/networking/unifi.nix
@@ -162,6 +162,8 @@ in
unitConfig.RequiresMountsFor = stateDir;
# This a HACK to fix missing dependencies of dynamic libs extracted from jars
environment.LD_LIBRARY_PATH = with pkgs.stdenv; "${cc.cc.lib}/lib";
+ # Make sure package upgrades trigger a service restart
+ restartTriggers = [ cfg.unifiPackage cfg.mongodbPackage ];
serviceConfig = {
Type = "simple";
diff --git a/nixpkgs/nixos/modules/services/networking/wasabibackend.nix b/nixpkgs/nixos/modules/services/networking/wasabibackend.nix
new file mode 100644
index 00000000000..6eacffe709b
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/wasabibackend.nix
@@ -0,0 +1,158 @@
+{ config, lib, pkgs, ... }:
+
+let
+ cfg = config.services.wasabibackend;
+
+ inherit (lib) mkEnableOption mkIf mkOption optionalAttrs optionalString types;
+
+ confOptions = {
+ BitcoinRpcConnectionString = "${cfg.rpc.user}:${cfg.rpc.password}";
+ } // optionalAttrs (cfg.network == "mainnet") {
+ Network = "Main";
+ MainNetBitcoinP2pEndPoint = "${cfg.endpoint.ip}:${toString cfg.endpoint.port}";
+ MainNetBitcoinCoreRpcEndPoint = "${cfg.rpc.ip}:${toString cfg.rpc.port}";
+ } // optionalAttrs (cfg.network == "testnet") {
+ Network = "TestNet";
+ TestNetBitcoinP2pEndPoint = "${cfg.endpoint.ip}:${toString cfg.endpoint.port}";
+ TestNetBitcoinCoreRpcEndPoint = "${cfg.rpc.ip}:${toString cfg.rpc.port}";
+ } // optionalAttrs (cfg.network == "regtest") {
+ Network = "RegTest";
+ RegTestBitcoinP2pEndPoint = "${cfg.endpoint.ip}:${toString cfg.endpoint.port}";
+ RegTestBitcoinCoreRpcEndPoint = "${cfg.rpc.ip}:${toString cfg.rpc.port}";
+ };
+
+ configFile = pkgs.writeText "wasabibackend.conf" (builtins.toJSON confOptions);
+
+in {
+
+ options = {
+
+ services.wasabibackend = {
+ enable = mkEnableOption "Wasabi backend service";
+
+ dataDir = mkOption {
+ type = types.path;
+ default = "/var/lib/wasabibackend";
+ description = "The data directory for the Wasabi backend node.";
+ };
+
+ customConfigFile = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ description = "Defines the path to a custom configuration file that is copied to the user's directory. Overrides any config options.";
+ };
+
+ network = mkOption {
+ type = types.enum [ "mainnet" "testnet" "regtest" ];
+ default = "mainnet";
+ description = "The network to use for the Wasabi backend service.";
+ };
+
+ endpoint = {
+ ip = mkOption {
+ type = types.str;
+ default = "127.0.0.1";
+ description = "IP address for P2P connection to bitcoind.";
+ };
+
+ port = mkOption {
+ type = types.port;
+ default = 8333;
+ description = "Port for P2P connection to bitcoind.";
+ };
+ };
+
+ rpc = {
+ ip = mkOption {
+ type = types.str;
+ default = "127.0.0.1";
+ description = "IP address for RPC connection to bitcoind.";
+ };
+
+ port = mkOption {
+ type = types.port;
+ default = 8332;
+ description = "Port for RPC connection to bitcoind.";
+ };
+
+ user = mkOption {
+ type = types.str;
+ default = "bitcoin";
+ description = "RPC user for the bitcoin endpoint.";
+ };
+
+ password = mkOption {
+ type = types.str;
+ default = "password";
+ description = "RPC password for the bitcoin endpoint. Warning: this is stored in cleartext in the Nix store! Use <literal>configFile</literal> or <literal>passwordFile</literal> if needed.";
+ };
+
+ passwordFile = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ description = "File that contains the password of the RPC user.";
+ };
+ };
+
+ user = mkOption {
+ type = types.str;
+ default = "wasabibackend";
+ description = "The user as which to run the wasabibackend node.";
+ };
+
+ group = mkOption {
+ type = types.str;
+ default = cfg.user;
+ description = "The group as which to run the wasabibackend node.";
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+
+ systemd.tmpfiles.rules = [
+ "d '${cfg.dataDir}' 0770 '${cfg.user}' '${cfg.group}' - -"
+ ];
+
+ systemd.services.wasabibackend = {
+ description = "wasabibackend server";
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network-online.target" ];
+ environment = {
+ DOTNET_PRINT_TELEMETRY_MESSAGE = "false";
+ DOTNET_CLI_TELEMETRY_OPTOUT = "true";
+ };
+ preStart = ''
+ mkdir -p ${cfg.dataDir}/.walletwasabi/backend
+ ${if cfg.customConfigFile != null then ''
+ cp -v ${cfg.customConfigFile} ${cfg.dataDir}/.walletwasabi/backend/Config.json
+ '' else ''
+ cp -v ${configFile} ${cfg.dataDir}/.walletwasabi/backend/Config.json
+ ${optionalString (cfg.rpc.passwordFile != null) ''
+ CONFIGTMP=$(mktemp)
+ cat ${cfg.dataDir}/.walletwasabi/backend/Config.json | ${pkgs.jq}/bin/jq --arg rpconnection "${cfg.rpc.user}:$(cat "${cfg.rpc.passwordFile}")" '. + { BitcoinRpcConnectionString: $rpconnection }' > $CONFIGTMP
+ mv $CONFIGTMP ${cfg.dataDir}/.walletwasabi/backend/Config.json
+ ''}
+ ''}
+ chmod ug+w ${cfg.dataDir}/.walletwasabi/backend/Config.json
+ '';
+ serviceConfig = {
+ User = cfg.user;
+ Group = cfg.group;
+ ExecStart = "${pkgs.wasabibackend}/bin/WasabiBackend";
+ ProtectSystem = "full";
+ };
+ };
+
+ users.users.${cfg.user} = {
+ name = cfg.user;
+ group = cfg.group;
+ description = "wasabibackend daemon user";
+ home = cfg.dataDir;
+ isSystemUser = true;
+ };
+
+ users.groups.${cfg.group} = {};
+
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/networking/wg-quick.nix b/nixpkgs/nixos/modules/services/networking/wg-quick.nix
index ff1bdeed9f4..02fe40a22a1 100644
--- a/nixpkgs/nixos/modules/services/networking/wg-quick.nix
+++ b/nixpkgs/nixos/modules/services/networking/wg-quick.nix
@@ -29,7 +29,7 @@ let
type = with types; nullOr str;
default = null;
description = ''
- Base64 private key generated by wg genkey.
+ Base64 private key generated by <command>wg genkey</command>.
Warning: Consider using privateKeyFile instead if you do not
want to store the key in the world-readable Nix store.
@@ -41,7 +41,7 @@ let
type = with types; nullOr str;
default = null;
description = ''
- Private key file as generated by wg genkey.
+ Private key file as generated by <command>wg genkey</command>.
'';
};
@@ -106,9 +106,9 @@ let
description = ''
The kernel routing table to add this interface's
associated routes to. Setting this is useful for e.g. policy routing
- ("ip rule") or virtual routing and forwarding ("ip vrf"). Both numeric
- table IDs and table names (/etc/rt_tables) can be used. Defaults to
- "main".
+ ("ip rule") or virtual routing and forwarding ("ip vrf"). Both
+ numeric table IDs and table names (/etc/rt_tables) can be used.
+ Defaults to "main".
'';
};
@@ -139,7 +139,7 @@ let
publicKey = mkOption {
example = "xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=";
type = types.str;
- description = "The base64 public key the peer.";
+ description = "The base64 public key to the peer.";
};
presharedKey = mkOption {
@@ -147,8 +147,8 @@ let
example = "rVXs/Ni9tu3oDBLS4hOyAUAa1qTWVA3loR8eL20os3I=";
type = with types; nullOr str;
description = ''
- Base64 preshared key generated by wg genpsk. Optional,
- and may be omitted. This option adds an additional layer of
+ Base64 preshared key generated by <command>wg genpsk</command>.
+ Optional, and may be omitted. This option adds an additional layer of
symmetric-key cryptography to be mixed into the already existing
public-key cryptography, for post-quantum resistance.
@@ -162,8 +162,8 @@ let
example = "/private/wireguard_psk";
type = with types; nullOr str;
description = ''
- File pointing to preshared key as generated by wg pensk. Optional,
- and may be omitted. This option adds an additional layer of
+ File pointing to preshared key as generated by <command>wg genpsk</command>.
+ Optional, and may be omitted. This option adds an additional layer of
symmetric-key cryptography to be mixed into the already existing
public-key cryptography, for post-quantum resistance.
'';
diff --git a/nixpkgs/nixos/modules/services/networking/wireguard.nix b/nixpkgs/nixos/modules/services/networking/wireguard.nix
index e8f83f6dd8b..e07020349cf 100644
--- a/nixpkgs/nixos/modules/services/networking/wireguard.nix
+++ b/nixpkgs/nixos/modules/services/networking/wireguard.nix
@@ -91,11 +91,13 @@ let
table = mkOption {
default = "main";
type = types.str;
- description = ''The kernel routing table to add this interface's
- associated routes to. Setting this is useful for e.g. policy routing
- ("ip rule") or virtual routing and forwarding ("ip vrf"). Both numeric
- table IDs and table names (/etc/rt_tables) can be used. Defaults to
- "main".'';
+ description = ''
+ The kernel routing table to add this interface's
+ associated routes to. Setting this is useful for e.g. policy routing
+ ("ip rule") or virtual routing and forwarding ("ip vrf"). Both
+ numeric table IDs and table names (/etc/rt_tables) can be used.
+ Defaults to "main".
+ '';
};
peers = mkOption {
@@ -174,7 +176,7 @@ let
example = "/private/wireguard_psk";
type = with types; nullOr str;
description = ''
- File pointing to preshared key as generated by <command>wg pensk</command>.
+ File pointing to preshared key as generated by <command>wg genpsk</command>.
Optional, and may be omitted. This option adds an additional layer of
symmetric-key cryptography to be mixed into the already existing
public-key cryptography, for post-quantum resistance.
@@ -217,7 +219,6 @@ let
};
-
generatePathUnit = name: values:
assert (values.privateKey == null);
assert (values.privateKeyFile != null);
diff --git a/nixpkgs/nixos/modules/services/networking/wpa_supplicant.nix b/nixpkgs/nixos/modules/services/networking/wpa_supplicant.nix
index a7dea95056a..08a17d20ed7 100644
--- a/nixpkgs/nixos/modules/services/networking/wpa_supplicant.nix
+++ b/nixpkgs/nixos/modules/services/networking/wpa_supplicant.nix
@@ -4,7 +4,7 @@ with lib;
let
cfg = config.networking.wireless;
- configFile = if cfg.networks != {} then pkgs.writeText "wpa_supplicant.conf" ''
+ configFile = if cfg.networks != {} || cfg.extraConfig != "" || cfg.userControlled.enable then pkgs.writeText "wpa_supplicant.conf" ''
${optionalString cfg.userControlled.enable ''
ctrl_interface=DIR=/run/wpa_supplicant GROUP=${cfg.userControlled.group}
update_config=1''}
diff --git a/nixpkgs/nixos/modules/services/networking/xandikos.nix b/nixpkgs/nixos/modules/services/networking/xandikos.nix
index 87c029156b9..f1882261656 100644
--- a/nixpkgs/nixos/modules/services/networking/xandikos.nix
+++ b/nixpkgs/nixos/modules/services/networking/xandikos.nix
@@ -122,7 +122,7 @@ in
ExecStart = ''
${cfg.package}/bin/xandikos \
--directory /var/lib/xandikos \
- --listen_address ${cfg.address} \
+ --listen-address ${cfg.address} \
--port ${toString cfg.port} \
--route-prefix ${cfg.routePrefix} \
${lib.concatStringsSep " " cfg.extraOptions}
diff --git a/nixpkgs/nixos/modules/services/networking/yggdrasil.nix b/nixpkgs/nixos/modules/services/networking/yggdrasil.nix
index 0fe9a200a1b..a71c635c9f6 100644
--- a/nixpkgs/nixos/modules/services/networking/yggdrasil.nix
+++ b/nixpkgs/nixos/modules/services/networking/yggdrasil.nix
@@ -195,5 +195,8 @@ in {
# Make yggdrasilctl available on the command line.
environment.systemPackages = [ cfg.package ];
});
- meta.maintainers = with lib.maintainers; [ gazally ehmry ];
+ meta = {
+ doc = ./yggdrasil.xml;
+ maintainers = with lib.maintainers; [ gazally ehmry ];
+ };
}
diff --git a/nixpkgs/nixos/modules/services/networking/yggdrasil.xml b/nixpkgs/nixos/modules/services/networking/yggdrasil.xml
new file mode 100644
index 00000000000..c012cd4a929
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/yggdrasil.xml
@@ -0,0 +1,157 @@
+<?xml version="1.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="module-services-networking-yggdrasil">
+ <title>Yggdrasil</title>
+ <para>
+ <emphasis>Source:</emphasis>
+ <filename>modules/services/networking/yggdrasil/default.nix</filename>
+ </para>
+ <para>
+ <emphasis>Upstream documentation:</emphasis>
+ <link xlink:href="https://yggdrasil-network.github.io/"/>
+ </para>
+ <para>
+Yggdrasil is an early-stage implementation of a fully end-to-end encrypted,
+self-arranging IPv6 network.
+</para>
+ <section xml:id="module-services-networking-yggdrasil-configuration">
+ <title>Configuration</title>
+ <section xml:id="module-services-networking-yggdrasil-configuration-simple">
+ <title>Simple ephemeral node</title>
+ <para>
+An annotated example of a simple configuration:
+<programlisting>
+{
+ services.yggdrasil = {
+ enable = true;
+ persistentKeys = false;
+ # The NixOS module will generate new keys and a new IPv6 address each time
+ # it is started if persistentKeys is not enabled.
+
+ config = {
+ Peers = [
+ # Yggdrasil will automatically connect and "peer" with other nodes it
+ # discovers via link-local multicast annoucements. Unless this is the
+ # case (it probably isn't) a node needs peers within the existing
+ # network that it can tunnel to.
+ "tcp://1.2.3.4:1024"
+ "tcp://1.2.3.5:1024"
+ # Public peers can be found at
+ # https://github.com/yggdrasil-network/public-peers
+ ];
+ };
+ };
+}
+</programlisting>
+ </para>
+ </section>
+ <section xml:id="module-services-networking-yggdrasil-configuration-prefix">
+ <title>Persistent node with prefix</title>
+ <para>
+A node with a fixed address that announces a prefix:
+<programlisting>
+let
+ address = "210:5217:69c0:9afc:1b95:b9f:8718:c3d2";
+ prefix = "310:5217:69c0:9afc";
+ # taken from the output of "yggdrasilctl getself".
+in {
+
+ services.yggdrasil = {
+ enable = true;
+ persistentKeys = true; # Maintain a fixed public key and IPv6 address.
+ config = {
+ Peers = [ "tcp://1.2.3.4:1024" "tcp://1.2.3.5:1024" ];
+ NodeInfo = {
+ # This information is visible to the network.
+ name = config.networking.hostName;
+ location = "The North Pole";
+ };
+ };
+ };
+
+ boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = 1;
+ # Forward traffic under the prefix.
+
+ networking.interfaces.${eth0}.ipv6.addresses = [{
+ # Set a 300::/8 address on the local physical device.
+ address = prefix + "::1";
+ prefixLength = 64;
+ }];
+
+ services.radvd = {
+ # Annouce the 300::/8 prefix to eth0.
+ enable = true;
+ config = ''
+ interface eth0
+ {
+ AdvSendAdvert on;
+ AdvDefaultLifetime 0;
+ prefix ${prefix}::/64 {
+ AdvOnLink on;
+ AdvAutonomous on;
+ };
+ route 200::/8 {};
+ };
+ '';
+ };
+}
+</programlisting>
+ </para>
+ </section>
+ <section xml:id="module-services-networking-yggdrasil-configuration-container">
+ <title>Yggdrasil attached Container</title>
+ <para>
+A NixOS container attached to the Yggdrasil network via a node running on the
+host:
+ <programlisting>
+let
+ yggPrefix64 = "310:5217:69c0:9afc";
+ # Again, taken from the output of "yggdrasilctl getself".
+in
+{
+ boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = 1;
+ # Enable IPv6 forwarding.
+
+ networking = {
+ bridges.br0.interfaces = [ ];
+ # A bridge only to containers&#x2026;
+
+ interfaces.br0 = {
+ # &#x2026; configured with a prefix address.
+ ipv6.addresses = [{
+ address = "${yggPrefix64}::1";
+ prefixLength = 64;
+ }];
+ };
+ };
+
+ containers.foo = {
+ autoStart = true;
+ privateNetwork = true;
+ hostBridge = "br0";
+ # Attach the container to the bridge only.
+ config = { config, pkgs, ... }: {
+ networking.interfaces.eth0.ipv6 = {
+ addresses = [{
+ # Configure a prefix address.
+ address = "${yggPrefix64}::2";
+ prefixLength = 64;
+ }];
+ routes = [{
+ # Configure the prefix route.
+ address = "200::";
+ prefixLength = 7;
+ via = "${yggPrefix64}::1";
+ }];
+ };
+
+ services.httpd.enable = true;
+ networking.firewall.allowedTCPPorts = [ 80 ];
+ };
+ };
+
+}
+</programlisting>
+ </para>
+ </section>
+ </section>
+</chapter>
diff --git a/nixpkgs/nixos/modules/services/security/nginx-sso.nix b/nixpkgs/nixos/modules/services/security/nginx-sso.nix
index d792f90abe6..50d250fc4d7 100644
--- a/nixpkgs/nixos/modules/services/security/nginx-sso.nix
+++ b/nixpkgs/nixos/modules/services/security/nginx-sso.nix
@@ -4,12 +4,21 @@ with lib;
let
cfg = config.services.nginx.sso;
- pkg = getBin pkgs.nginx-sso;
+ pkg = getBin cfg.package;
configYml = pkgs.writeText "nginx-sso.yml" (builtins.toJSON cfg.configuration);
in {
options.services.nginx.sso = {
enable = mkEnableOption "nginx-sso service";
+ package = mkOption {
+ type = types.package;
+ default = pkgs.nginx-sso;
+ defaultText = "pkgs.nginx-sso";
+ description = ''
+ The nginx-sso package that should be used.
+ '';
+ };
+
configuration = mkOption {
type = types.attrsOf types.unspecified;
default = {};
diff --git a/nixpkgs/nixos/modules/services/security/oauth2_proxy.nix b/nixpkgs/nixos/modules/services/security/oauth2_proxy.nix
index d5c5437329e..2f9e94bd77b 100644
--- a/nixpkgs/nixos/modules/services/security/oauth2_proxy.nix
+++ b/nixpkgs/nixos/modules/services/security/oauth2_proxy.nix
@@ -99,7 +99,7 @@ in
##############################################
# PROVIDER configuration
- # Taken from: https://github.com/pusher/oauth2_proxy/blob/master/providers/providers.go
+ # Taken from: https://github.com/oauth2-proxy/oauth2-proxy/blob/master/providers/providers.go
provider = mkOption {
type = types.enum [
"google"
@@ -346,7 +346,9 @@ in
type = types.nullOr types.str;
default = null;
description = ''
- An optional cookie domain to force cookies to.
+ Optional cookie domains to force cookies to (ie: `.yourcompany.com`).
+ The longest domain matching the request's host will be used (or the shortest
+ cookie domain if there is no match).
'';
example = ".yourcompany.com";
};
@@ -537,7 +539,7 @@ in
extraConfig = mkOption {
default = {};
description = ''
- Extra config to pass to oauth2_proxy.
+ Extra config to pass to oauth2-proxy.
'';
};
@@ -545,7 +547,7 @@ in
type = types.nullOr types.path;
default = null;
description = ''
- oauth2_proxy allows passing sensitive configuration via environment variables.
+ oauth2-proxy allows passing sensitive configuration via environment variables.
Make a file that contains lines like
OAUTH2_PROXY_CLIENT_SECRET=asdfasdfasdf.apps.googleuserscontent.com
and specify the path here.
@@ -577,7 +579,7 @@ in
serviceConfig = {
User = "oauth2_proxy";
Restart = "always";
- ExecStart = "${cfg.package}/bin/oauth2_proxy ${configString}";
+ ExecStart = "${cfg.package}/bin/oauth2-proxy ${configString}";
EnvironmentFile = mkIf (cfg.keyFile != null) cfg.keyFile;
};
};
diff --git a/nixpkgs/nixos/modules/services/security/physlock.nix b/nixpkgs/nixos/modules/services/security/physlock.nix
index 61bcd84f2e6..690eb70079d 100644
--- a/nixpkgs/nixos/modules/services/security/physlock.nix
+++ b/nixpkgs/nixos/modules/services/security/physlock.nix
@@ -107,6 +107,7 @@ in
++ cfg.lockOn.extraTargets;
before = optional cfg.lockOn.suspend "systemd-suspend.service"
++ optional cfg.lockOn.hibernate "systemd-hibernate.service"
+ ++ optional (cfg.lockOn.hibernate || cfg.lockOn.suspend) "systemd-suspend-then-hibernate.service"
++ cfg.lockOn.extraTargets;
serviceConfig = {
Type = "forking";
diff --git a/nixpkgs/nixos/modules/services/security/tor.nix b/nixpkgs/nixos/modules/services/security/tor.nix
index 18c105b2f57..b33e905c67d 100644
--- a/nixpkgs/nixos/modules/services/security/tor.nix
+++ b/nixpkgs/nixos/modules/services/security/tor.nix
@@ -159,7 +159,7 @@ in
type = types.bool;
default = false;
description = ''
- Wheter to enable Tor control socket. Control socket is created
+ Whether to enable Tor control socket. Control socket is created
in <literal>${torRunDirectory}/control</literal>
'';
};
diff --git a/nixpkgs/nixos/modules/services/security/yubikey-agent.nix b/nixpkgs/nixos/modules/services/security/yubikey-agent.nix
new file mode 100644
index 00000000000..2972c64a364
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/security/yubikey-agent.nix
@@ -0,0 +1,60 @@
+# Global configuration for yubikey-agent.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.yubikey-agent;
+
+ # reuse the pinentryFlavor option from the gnupg module
+ pinentryFlavor = config.programs.gnupg.agent.pinentryFlavor;
+in
+{
+ ###### interface
+
+ meta.maintainers = with maintainers; [ philandstuff rawkode ];
+
+ options = {
+
+ services.yubikey-agent = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to start yubikey-agent when you log in. Also sets
+ SSH_AUTH_SOCK to point at yubikey-agent.
+
+ Note that yubikey-agent will use whatever pinentry is
+ specified in programs.gnupg.agent.pinentryFlavor.
+ '';
+ };
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.yubikey-agent;
+ defaultText = "pkgs.yubikey-agent";
+ description = ''
+ The package used for the yubikey-agent daemon.
+ '';
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ environment.systemPackages = [ cfg.package ];
+ systemd.packages = [ cfg.package ];
+
+ # This overrides the systemd user unit shipped with the
+ # yubikey-agent package
+ systemd.user.services.yubikey-agent = mkIf (pinentryFlavor != null) {
+ path = [ pkgs.pinentry.${pinentryFlavor} ];
+ };
+
+ environment.extraInit = ''
+ if [ -z "$SSH_AUTH_SOCK" -a -n "$XDG_RUNTIME_DIR" ]; then
+ export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/yubikey-agent/yubikey-agent.sock"
+ fi
+ '';
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/torrent/transmission.nix b/nixpkgs/nixos/modules/services/torrent/transmission.nix
index e7f5aaed844..1bfcf2de82f 100644
--- a/nixpkgs/nixos/modules/services/torrent/transmission.nix
+++ b/nixpkgs/nixos/modules/services/torrent/transmission.nix
@@ -179,6 +179,8 @@ in
${getLib pkgs.utillinuxMinimal.out}/lib/libblkid.so.* mr,
${getLib pkgs.utillinuxMinimal.out}/lib/libmount.so.* mr,
${getLib pkgs.utillinuxMinimal.out}/lib/libuuid.so.* mr,
+ ${getLib pkgs.gcc.cc.lib}/lib/libstdc++.so.* mr,
+ ${getLib pkgs.gcc.cc.lib}/lib/libgcc_s.so.* mr,
@{PROC}/sys/kernel/random/uuid r,
@{PROC}/sys/vm/overcommit_memory r,
diff --git a/nixpkgs/nixos/modules/services/web-apps/codimd.nix b/nixpkgs/nixos/modules/services/web-apps/codimd.nix
index 751f81649dd..ab922a38e5c 100644
--- a/nixpkgs/nixos/modules/services/web-apps/codimd.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/codimd.nix
@@ -93,7 +93,7 @@ in
type = types.bool;
default = true;
description = ''
- Wheter to enable HSTS if HTTPS is also enabled.
+ Whether to enable HSTS if HTTPS is also enabled.
'';
};
maxAgeSeconds = mkOption {
@@ -385,7 +385,7 @@ in
type = types.bool;
default = true;
description = ''
- Wether to enable email registration.
+ Whether to enable email registration.
'';
};
allowGravatar = mkOption {
diff --git a/nixpkgs/nixos/modules/services/web-apps/convos.nix b/nixpkgs/nixos/modules/services/web-apps/convos.nix
new file mode 100644
index 00000000000..8be11eec9f3
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/web-apps/convos.nix
@@ -0,0 +1,72 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.convos;
+in
+{
+ options.services.convos = {
+ enable = mkEnableOption "Convos";
+ listenPort = mkOption {
+ type = types.port;
+ default = 3000;
+ example = 8080;
+ description = "Port the web interface should listen on";
+ };
+ listenAddress = mkOption {
+ type = types.str;
+ default = "*";
+ example = "127.0.0.1";
+ description = "Address or host the web interface should listen on";
+ };
+ reverseProxy = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Enables reverse proxy support. This will allow Convos to automatically
+ pick up the <literal>X-Forwarded-For</literal> and
+ <literal>X-Request-Base</literal> HTTP headers set in your reverse proxy
+ web server. Note that enabling this option without a reverse proxy in
+ front will be a security issue.
+ '';
+ };
+ };
+ config = mkIf cfg.enable {
+ systemd.services.convos = {
+ description = "Convos Service";
+ wantedBy = [ "multi-user.target" ];
+ after = [ "networking.target" ];
+ environment = {
+ CONVOS_HOME = "%S/convos";
+ CONVOS_REVERSE_PROXY = if cfg.reverseProxy then "1" else "0";
+ MOJO_LISTEN = "http://${toString cfg.listenAddress}:${toString cfg.listenPort}";
+ };
+ serviceConfig = {
+ ExecStart = "${pkgs.convos}/bin/convos daemon";
+ Restart = "on-failure";
+ StateDirectory = "convos";
+ WorkingDirectory = "%S/convos";
+ DynamicUser = true;
+ MemoryDenyWriteExecute = true;
+ ProtectHome = true;
+ ProtectClock = true;
+ ProtectHostname = true;
+ ProtectKernelTunables = true;
+ ProtectKernelModules = true;
+ ProtectKernelLogs = true;
+ ProtectControlGroups = true;
+ PrivateDevices = true;
+ PrivateMounts = true;
+ PrivateUsers = true;
+ LockPersonality = true;
+ RestrictRealtime = true;
+ RestrictNamespaces = true;
+ RestrictAddressFamilies = [ "AF_INET" "AF_INET6"];
+ SystemCallFilter = "@system-service";
+ SystemCallArchitectures = "native";
+ CapabilityBoundingSet = "";
+ };
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/web-apps/dokuwiki.nix b/nixpkgs/nixos/modules/services/web-apps/dokuwiki.nix
index 33a828fa2cb..fe6b9210d24 100644
--- a/nixpkgs/nixos/modules/services/web-apps/dokuwiki.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/dokuwiki.nix
@@ -321,7 +321,7 @@ in
enable = true;
virtualHosts = mapAttrs (hostName: cfg: mkMerge [ cfg.nginx {
root = mkForce "${pkg hostName cfg}/share/dokuwiki";
- extraConfig = "fastcgi_param HTTPS on;";
+ extraConfig = lib.optionalString (cfg.nginx.addSSL || cfg.nginx.forceSSL || cfg.nginx.onlySSL || cfg.nginx.enableACME) "fastcgi_param HTTPS on;";
locations."~ /(conf/|bin/|inc/|install.php)" = {
extraConfig = "deny all;";
@@ -359,7 +359,7 @@ in
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param REDIRECT_STATUS 200;
fastcgi_pass unix:${config.services.phpfpm.pools."dokuwiki-${hostName}".socket};
- fastcgi_param HTTPS on;
+ ${lib.optionalString (cfg.nginx.addSSL || cfg.nginx.forceSSL || cfg.nginx.onlySSL || cfg.nginx.enableACME) "fastcgi_param HTTPS on;"}
'';
};
}]) eachSite;
diff --git a/nixpkgs/nixos/modules/services/web-apps/gerrit.nix b/nixpkgs/nixos/modules/services/web-apps/gerrit.nix
index b184c0754d4..657b1a4fc5b 100644
--- a/nixpkgs/nixos/modules/services/web-apps/gerrit.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/gerrit.nix
@@ -17,6 +17,10 @@ let
lib.generators.toGitINI cfg.settings
);
+ replicationConfig = pkgs.writeText "replication.conf" (
+ lib.generators.toGitINI cfg.replicationSettings
+ );
+
# Wrap the gerrit java with all the java options so it can be called
# like a normal CLI app
gerrit-cli = pkgs.writeShellScriptBin "gerrit" ''
@@ -106,6 +110,15 @@ in
'';
};
+ replicationSettings = mkOption {
+ type = gitIniType;
+ default = {};
+ description = ''
+ Replication configuration. This will be generated to the
+ <literal>etc/replication.config</literal> file.
+ '';
+ };
+
plugins = mkOption {
type = types.listOf types.package;
default = [];
@@ -138,6 +151,13 @@ in
config = mkIf cfg.enable {
+ assertions = [
+ {
+ assertion = cfg.replicationSettings != {} -> elem "replication" cfg.builtinPlugins;
+ message = "Gerrit replicationSettings require enabling the replication plugin";
+ }
+ ];
+
services.gerrit.settings = {
cache.directory = "/var/cache/gerrit";
container.heapLimit = cfg.jvmHeapLimit;
@@ -194,6 +214,7 @@ in
# copy the config, keep it mutable because Gerrit
ln -sfv ${gerritConfig} etc/gerrit.config
+ ln -sfv ${replicationConfig} etc/replication.config
# install the plugins
rm -rf plugins
diff --git a/nixpkgs/nixos/modules/services/web-apps/jitsi-meet.nix b/nixpkgs/nixos/modules/services/web-apps/jitsi-meet.nix
new file mode 100644
index 00000000000..3b2b2440491
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/web-apps/jitsi-meet.nix
@@ -0,0 +1,333 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.jitsi-meet;
+
+ # The configuration files are JS of format "var <<string>> = <<JSON>>;". In order to
+ # override only some settings, we need to extract the JSON, use jq to merge it with
+ # the config provided by user, and then reconstruct the file.
+ overrideJs =
+ source: varName: userCfg: appendExtra:
+ let
+ extractor = pkgs.writeText "extractor.js" ''
+ var fs = require("fs");
+ eval(fs.readFileSync(process.argv[2], 'utf8'));
+ process.stdout.write(JSON.stringify(eval(process.argv[3])));
+ '';
+ userJson = pkgs.writeText "user.json" (builtins.toJSON userCfg);
+ in (pkgs.runCommand "${varName}.js" { } ''
+ ${pkgs.nodejs}/bin/node ${extractor} ${source} ${varName} > default.json
+ (
+ echo "var ${varName} = "
+ ${pkgs.jq}/bin/jq -s '.[0] * .[1]' default.json ${userJson}
+ echo ";"
+ echo ${escapeShellArg appendExtra}
+ ) > $out
+ '');
+
+ # Essential config - it's probably not good to have these as option default because
+ # types.attrs doesn't do merging. Let's merge explicitly, can still be overriden if
+ # user desires.
+ defaultCfg = {
+ hosts = {
+ domain = cfg.hostName;
+ muc = "conference.${cfg.hostName}";
+ focus = "focus.${cfg.hostName}";
+ };
+ bosh = "//${cfg.hostName}/http-bind";
+ };
+in
+{
+ options.services.jitsi-meet = with types; {
+ enable = mkEnableOption "Jitsi Meet - Secure, Simple and Scalable Video Conferences";
+
+ hostName = mkOption {
+ type = str;
+ example = "meet.example.org";
+ description = ''
+ Hostname of the Jitsi Meet instance.
+ '';
+ };
+
+ config = mkOption {
+ type = attrs;
+ default = { };
+ example = literalExample ''
+ {
+ enableWelcomePage = false;
+ defaultLang = "fi";
+ }
+ '';
+ description = ''
+ Client-side web application settings that override the defaults in <filename>config.js</filename>.
+
+ See <link xlink:href="https://github.com/jitsi/jitsi-meet/blob/master/config.js" /> for default
+ configuration with comments.
+ '';
+ };
+
+ extraConfig = mkOption {
+ type = lines;
+ default = "";
+ description = ''
+ Text to append to <filename>config.js</filename> web application config file.
+
+ Can be used to insert JavaScript logic to determine user's region in cascading bridges setup.
+ '';
+ };
+
+ interfaceConfig = mkOption {
+ type = attrs;
+ default = { };
+ example = literalExample ''
+ {
+ SHOW_JITSI_WATERMARK = false;
+ SHOW_WATERMARK_FOR_GUESTS = false;
+ }
+ '';
+ description = ''
+ Client-side web-app interface settings that override the defaults in <filename>interface_config.js</filename>.
+
+ See <link xlink:href="https://github.com/jitsi/jitsi-meet/blob/master/interface_config.js" /> for
+ default configuration with comments.
+ '';
+ };
+
+ videobridge = {
+ enable = mkOption {
+ type = bool;
+ default = true;
+ description = ''
+ Whether to enable Jitsi Videobridge instance and configure it to connect to Prosody.
+
+ Additional configuration is possible with <option>services.jitsi-videobridge</option>.
+ '';
+ };
+
+ passwordFile = mkOption {
+ type = nullOr str;
+ default = null;
+ example = "/run/keys/videobridge";
+ description = ''
+ File containing password to the Prosody account for videobridge.
+
+ If <literal>null</literal>, a file with password will be generated automatically. Setting
+ this option is useful if you plan to connect additional videobridges to the XMPP server.
+ '';
+ };
+ };
+
+ jicofo.enable = mkOption {
+ type = bool;
+ default = true;
+ description = ''
+ Whether to enable JiCoFo instance and configure it to connect to Prosody.
+
+ Additional configuration is possible with <option>services.jicofo</option>.
+ '';
+ };
+
+ nginx.enable = mkOption {
+ type = bool;
+ default = true;
+ description = ''
+ Whether to enable nginx virtual host that will serve the javascript application and act as
+ a proxy for the XMPP server. Further nginx configuration can be done by adapting
+ <option>services.nginx.virtualHosts.&lt;hostName&gt;</option>.
+ When this is enabled, ACME will be used to retrieve a TLS certificate by default. To disable
+ this, set the <option>services.nginx.virtualHosts.&lt;hostName&gt;.enableACME</option> to
+ <literal>false</literal> and if appropriate do the same for
+ <option>services.nginx.virtualHosts.&lt;hostName&gt;.forceSSL</option>.
+ '';
+ };
+
+ prosody.enable = mkOption {
+ type = bool;
+ default = true;
+ description = ''
+ Whether to configure Prosody to relay XMPP messages between Jitsi Meet components. Turn this
+ off if you want to configure it manually.
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ services.prosody = mkIf cfg.prosody.enable {
+ enable = mkDefault true;
+ xmppComplianceSuite = mkDefault false;
+ modules = {
+ admin_adhoc = mkDefault false;
+ bosh = mkDefault true;
+ ping = mkDefault true;
+ roster = mkDefault true;
+ saslauth = mkDefault true;
+ tls = mkDefault true;
+ };
+ muc = [
+ {
+ domain = "conference.${cfg.hostName}";
+ name = "Jitsi Meet MUC";
+ roomLocking = false;
+ roomDefaultPublicJids = true;
+ extraConfig = ''
+ storage = "memory"
+ '';
+ }
+ {
+ domain = "internal.${cfg.hostName}";
+ name = "Jitsi Meet Videobridge MUC";
+ extraConfig = ''
+ storage = "memory"
+ admins = { "focus@auth.${cfg.hostName}", "jvb@auth.${cfg.hostName}" }
+ '';
+ #-- muc_room_cache_size = 1000
+ }
+ ];
+ extraModules = [ "pubsub" ];
+ extraConfig = mkAfter ''
+ Component "focus.${cfg.hostName}"
+ component_secret = os.getenv("JICOFO_COMPONENT_SECRET")
+ '';
+ virtualHosts.${cfg.hostName} = {
+ enabled = true;
+ domain = cfg.hostName;
+ extraConfig = ''
+ authentication = "anonymous"
+ c2s_require_encryption = false
+ admins = { "focus@auth.${cfg.hostName}" }
+ '';
+ ssl = {
+ cert = "/var/lib/jitsi-meet/jitsi-meet.crt";
+ key = "/var/lib/jitsi-meet/jitsi-meet.key";
+ };
+ };
+ virtualHosts."auth.${cfg.hostName}" = {
+ enabled = true;
+ domain = "auth.${cfg.hostName}";
+ extraConfig = ''
+ authentication = "internal_plain"
+ '';
+ ssl = {
+ cert = "/var/lib/jitsi-meet/jitsi-meet.crt";
+ key = "/var/lib/jitsi-meet/jitsi-meet.key";
+ };
+ };
+ };
+ systemd.services.prosody.serviceConfig = mkIf cfg.prosody.enable {
+ EnvironmentFile = [ "/var/lib/jitsi-meet/secrets-env" ];
+ SupplementaryGroups = [ "jitsi-meet" ];
+ };
+
+ users.groups.jitsi-meet = {};
+ systemd.tmpfiles.rules = [
+ "d '/var/lib/jitsi-meet' 0750 root jitsi-meet - -"
+ ];
+
+ systemd.services.jitsi-meet-init-secrets = {
+ wantedBy = [ "multi-user.target" ];
+ before = [ "jicofo.service" "jitsi-videobridge2.service" ] ++ (optional cfg.prosody.enable "prosody.service");
+ serviceConfig = {
+ Type = "oneshot";
+ };
+
+ script = let
+ secrets = [ "jicofo-component-secret" "jicofo-user-secret" ] ++ (optional (cfg.videobridge.passwordFile == null) "videobridge-secret");
+ videobridgeSecret = if cfg.videobridge.passwordFile != null then cfg.videobridge.passwordFile else "/var/lib/jitsi-meet/videobridge-secret";
+ in
+ ''
+ cd /var/lib/jitsi-meet
+ ${concatMapStringsSep "\n" (s: ''
+ if [ ! -f ${s} ]; then
+ tr -dc a-zA-Z0-9 </dev/urandom | head -c 64 > ${s}
+ chown root:jitsi-meet ${s}
+ chmod 640 ${s}
+ fi
+ '') secrets}
+
+ # for easy access in prosody
+ echo "JICOFO_COMPONENT_SECRET=$(cat jicofo-component-secret)" > secrets-env
+ chown root:jitsi-meet secrets-env
+ chmod 640 secrets-env
+ ''
+ + optionalString cfg.prosody.enable ''
+ ${config.services.prosody.package}/bin/prosodyctl register focus auth.${cfg.hostName} "$(cat /var/lib/jitsi-meet/jicofo-user-secret)"
+ ${config.services.prosody.package}/bin/prosodyctl register jvb auth.${cfg.hostName} "$(cat ${videobridgeSecret})"
+
+ # generate self-signed certificates
+ if [ ! -f /var/lib/jitsi-meet.crt ]; then
+ ${getBin pkgs.openssl}/bin/openssl req \
+ -x509 \
+ -newkey rsa:4096 \
+ -keyout /var/lib/jitsi-meet/jitsi-meet.key \
+ -out /var/lib/jitsi-meet/jitsi-meet.crt \
+ -days 36500 \
+ -nodes \
+ -subj '/CN=${cfg.hostName}/CN=auth.${cfg.hostName}'
+ chmod 640 /var/lib/jitsi-meet/jitsi-meet.{crt,key}
+ chown root:jitsi-meet /var/lib/jitsi-meet/jitsi-meet.{crt,key}
+ fi
+ '';
+ };
+
+ services.nginx = mkIf cfg.nginx.enable {
+ enable = mkDefault true;
+ virtualHosts.${cfg.hostName} = {
+ enableACME = mkDefault true;
+ forceSSL = mkDefault true;
+ root = pkgs.jitsi-meet;
+ extraConfig = ''
+ ssi on;
+ '';
+ locations."@root_path".extraConfig = ''
+ rewrite ^/(.*)$ / break;
+ '';
+ locations."~ ^/([^/\\?&:'\"]+)$".tryFiles = "$uri @root_path";
+ locations."=/http-bind" = {
+ proxyPass = "http://localhost:5280/http-bind";
+ extraConfig = ''
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header Host $host;
+ '';
+ };
+ locations."=/external_api.js" = mkDefault {
+ alias = "${pkgs.jitsi-meet}/libs/external_api.min.js";
+ };
+ locations."=/config.js" = mkDefault {
+ alias = overrideJs "${pkgs.jitsi-meet}/config.js" "config" (recursiveUpdate defaultCfg cfg.config) cfg.extraConfig;
+ };
+ locations."=/interface_config.js" = mkDefault {
+ alias = overrideJs "${pkgs.jitsi-meet}/interface_config.js" "interfaceConfig" cfg.interfaceConfig "";
+ };
+ };
+ };
+
+ services.jitsi-videobridge = mkIf cfg.videobridge.enable {
+ enable = true;
+ xmppConfigs."localhost" = {
+ userName = "jvb";
+ domain = "auth.${cfg.hostName}";
+ passwordFile = "/var/lib/jitsi-meet/videobridge-secret";
+ mucJids = "jvbbrewery@internal.${cfg.hostName}";
+ disableCertificateVerification = true;
+ };
+ };
+
+ services.jicofo = mkIf cfg.jicofo.enable {
+ enable = true;
+ xmppHost = "localhost";
+ xmppDomain = cfg.hostName;
+ userDomain = "auth.${cfg.hostName}";
+ userName = "focus";
+ userPasswordFile = "/var/lib/jitsi-meet/jicofo-user-secret";
+ componentPasswordFile = "/var/lib/jitsi-meet/jicofo-component-secret";
+ bridgeMuc = "jvbbrewery@internal.${cfg.hostName}";
+ config = {
+ "org.jitsi.jicofo.ALWAYS_TRUST_MODE_ENABLED" = "true";
+ };
+ };
+ };
+
+ meta.maintainers = lib.teams.jitsi.members;
+}
diff --git a/nixpkgs/nixos/modules/services/web-apps/moodle.nix b/nixpkgs/nixos/modules/services/web-apps/moodle.nix
index 1196780cf6e..f45eaa24d54 100644
--- a/nixpkgs/nixos/modules/services/web-apps/moodle.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/moodle.nix
@@ -40,7 +40,7 @@ let
$CFG->disableupdateautodeploy = true;
$CFG->pathtogs = '${pkgs.ghostscript}/bin/gs';
- $CFG->pathtophp = '${pkgs.php}/bin/php';
+ $CFG->pathtophp = '${phpExt}/bin/php';
$CFG->pathtodu = '${pkgs.coreutils}/bin/du';
$CFG->aspellpath = '${pkgs.aspell}/bin/aspell';
$CFG->pathtodot = '${pkgs.graphviz}/bin/dot';
@@ -55,6 +55,9 @@ let
mysqlLocal = cfg.database.createLocally && cfg.database.type == "mysql";
pgsqlLocal = cfg.database.createLocally && cfg.database.type == "pgsql";
+
+ phpExt = pkgs.php.withExtensions
+ ({ enabled, all }: with all; [ iconv mbstring curl openssl tokenizer xmlrpc soap ctype zip gd simplexml dom intl json sqlite3 pgsql pdo_sqlite pdo_pgsql pdo_odbc pdo_mysql pdo mysqli session zlib xmlreader fileinfo ]);
in
{
# interface
@@ -222,6 +225,7 @@ in
services.phpfpm.pools.moodle = {
inherit user group;
+ phpPackage = phpExt;
phpEnv.MOODLE_CONFIG = "${moodleConfig}";
phpOptions = ''
zend_extension = opcache.so
@@ -263,13 +267,13 @@ in
after = optional mysqlLocal "mysql.service" ++ optional pgsqlLocal "postgresql.service";
environment.MOODLE_CONFIG = moodleConfig;
script = ''
- ${pkgs.php}/bin/php ${cfg.package}/share/moodle/admin/cli/check_database_schema.php && rc=$? || rc=$?
+ ${phpExt}/bin/php ${cfg.package}/share/moodle/admin/cli/check_database_schema.php && rc=$? || rc=$?
- [ "$rc" == 1 ] && ${pkgs.php}/bin/php ${cfg.package}/share/moodle/admin/cli/upgrade.php \
+ [ "$rc" == 1 ] && ${phpExt}/bin/php ${cfg.package}/share/moodle/admin/cli/upgrade.php \
--non-interactive \
--allow-unstable
- [ "$rc" == 2 ] && ${pkgs.php}/bin/php ${cfg.package}/share/moodle/admin/cli/install_database.php \
+ [ "$rc" == 2 ] && ${phpExt}/bin/php ${cfg.package}/share/moodle/admin/cli/install_database.php \
--agree-license \
--adminpass=${cfg.initialPassword}
@@ -289,7 +293,7 @@ in
serviceConfig = {
User = user;
Group = group;
- ExecStart = "${pkgs.php}/bin/php ${cfg.package}/share/moodle/admin/cli/cron.php";
+ ExecStart = "${phpExt}/bin/php ${cfg.package}/share/moodle/admin/cli/cron.php";
};
};
diff --git a/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix b/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix
index f826096bf60..328561dc800 100644
--- a/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix
@@ -34,7 +34,7 @@ let
cd ${cfg.package}
sudo=exec
if [[ "$USER" != nextcloud ]]; then
- sudo='exec /run/wrappers/bin/sudo -u nextcloud --preserve-env=NEXTCLOUD_CONFIG_DIR'
+ sudo='exec /run/wrappers/bin/sudo -u nextcloud --preserve-env=NEXTCLOUD_CONFIG_DIR --preserve-env=OC_PASS'
fi
export NEXTCLOUD_CONFIG_DIR="${cfg.home}/config"
$sudo \
@@ -69,7 +69,7 @@ in {
package = mkOption {
type = types.package;
description = "Which package to use for the Nextcloud instance.";
- relatedPackages = [ "nextcloud17" "nextcloud18" ];
+ relatedPackages = [ "nextcloud17" "nextcloud18" "nextcloud19" ];
};
maxUploadSize = mkOption {
@@ -303,6 +303,14 @@ in {
'';
};
};
+ occ = mkOption {
+ type = types.package;
+ default = occ;
+ internal = true;
+ description = ''
+ The nextcloud-occ program preconfigured to target this Nextcloud instance.
+ '';
+ };
};
config = mkIf cfg.enable (mkMerge [
@@ -336,7 +344,16 @@ in {
server, and wait until the upgrade to 17 is finished.
Then, set `services.nextcloud.package` to `pkgs.nextcloud18` to upgrade to
- Nextcloud version 18.
+ Nextcloud version 18. Please note that Nextcloud 19 is already out and it's
+ recommended to upgrade to nextcloud19 after that.
+ '')
+ ++ (optional (versionOlder cfg.package.version "19") ''
+ A legacy Nextcloud install (from before NixOS 20.09/unstable) may be installed.
+
+ If/After nextcloud18 is installed successfully, you can safely upgrade to
+ nextcloud19. If not, please upgrade to nextcloud18 first since Nextcloud doesn't
+ support upgrades that skip multiple versions (i.e. an upgrade from 17 to 19 isn't
+ possible, but an upgrade from 18 to 19).
'');
services.nextcloud.package = with pkgs;
@@ -348,7 +365,8 @@ in {
`pkgs.nextcloud`.
''
else if versionOlder stateVersion "20.03" then nextcloud17
- else nextcloud18
+ else if versionOlder stateVersion "20.09" then nextcloud18
+ else nextcloud19
);
}
@@ -360,6 +378,11 @@ in {
};
systemd.services = {
+ # When upgrading the Nextcloud package, Nextcloud can report errors such as
+ # "The files of the app [all apps in /var/lib/nextcloud/apps] were not replaced correctly"
+ # Restarting phpfpm on Nextcloud package update fixes these issues (but this is a workaround).
+ phpfpm-nextcloud.restartTriggers = [ cfg.package ];
+
nextcloud-setup = let
c = cfg.config;
writePhpArrary = a: "[${concatMapStringsSep "," (val: ''"${toString val}"'') a}]";
diff --git a/nixpkgs/nixos/modules/services/web-apps/nextcloud.xml b/nixpkgs/nixos/modules/services/web-apps/nextcloud.xml
index fc454f8ba25..332e4d1ff3e 100644
--- a/nixpkgs/nixos/modules/services/web-apps/nextcloud.xml
+++ b/nixpkgs/nixos/modules/services/web-apps/nextcloud.xml
@@ -161,5 +161,11 @@
};
}</programlisting>
</para>
+
+ <para>
+ Ideally we should make sure that it's possible to jump two NixOS versions forward:
+ i.e. the warnings and the logic in the module should guard a user to upgrade from a
+ Nextcloud on e.g. 19.09 to a Nextcloud on 20.09.
+ </para>
</section>
</chapter>
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 8abee7130d7..e1d1217943b 100644
--- a/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix
@@ -708,6 +708,7 @@ in
wantedBy = [ "multi-user.target" ];
wants = concatLists (map (hostOpts: [ "acme-${hostOpts.hostName}.service" "acme-selfsigned-${hostOpts.hostName}.service" ]) vhostsACME);
after = [ "network.target" "fs.target" ] ++ map (hostOpts: "acme-selfsigned-${hostOpts.hostName}.service") vhostsACME;
+ before = map (hostOpts: "acme-${hostOpts.hostName}.service") vhostsACME;
path = [ pkg pkgs.coreutils pkgs.gnugrep ];
diff --git a/nixpkgs/nixos/modules/services/web-servers/molly-brown.nix b/nixpkgs/nixos/modules/services/web-servers/molly-brown.nix
new file mode 100644
index 00000000000..e9052a184b2
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/web-servers/molly-brown.nix
@@ -0,0 +1,117 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.molly-brown;
+
+ settingsType = with types;
+ attrsOf (oneOf [
+ int
+ str
+ (listOf str)
+ (attrsOf (oneOf [ int str (listOf str) (attrsOf str) ]))
+ ]) // {
+ description = "primitive expression convertable to TOML";
+ };
+
+ configFile = pkgs.runCommand "molly-brown.toml" {
+ buildInputs = [ pkgs.remarshal ];
+ preferLocalBuild = true;
+ passAsFile = [ "settings" ];
+ settings = builtins.toJSON cfg.settings;
+ } "remarshal -if json -of toml < $settingsPath > $out";
+in {
+
+ options.services.molly-brown = {
+
+ enable = mkEnableOption "Molly-Brown Gemini server";
+
+ port = mkOption {
+ default = 1965;
+ type = types.port;
+ description = ''
+ TCP port for molly-brown to bind to.
+ '';
+ };
+
+ hostName = mkOption {
+ type = types.str;
+ example = literalExample "config.networking.hostName";
+ default = config.networking.hostName;
+ description = ''
+ The hostname to respond to requests for. Requests for URLs with
+ other hosts will result in a status 53 (PROXY REQUEST REFUSED)
+ response.
+ '';
+ };
+
+ certPath = mkOption {
+ type = types.path;
+ example = "/var/lib/acme/example.com/cert.pem";
+ description = ''
+ Path to TLS certificate. An ACME certificate and key may be
+ shared with an HTTP server, but only if molly-brown has
+ permissions allowing it to read such keys.
+
+ As an example:
+ <programlisting>
+ security.acme.certs."example.com".allowKeysForGroup = true;
+ systemd.services.molly-brown.serviceConfig.SupplementaryGroups =
+ [ config.security.acme.certs."example.com".group ];
+ </programlisting>
+ '';
+ };
+
+ keyPath = mkOption {
+ type = types.path;
+ example = "/var/lib/acme/example.com/key.pem";
+ description = "Path to TLS key. See <option>CertPath</option>.";
+ };
+
+ docBase = mkOption {
+ type = types.path;
+ example = "/var/lib/molly-brown";
+ description = "Base directory for Gemini content.";
+ };
+
+ settings = mkOption {
+ type = settingsType;
+ default = { };
+ description = ''
+ molly-brown configuration. Refer to
+ <link xlink:href="https://tildegit.org/solderpunk/molly-brown/src/branch/master/example.conf"/>
+ for details on supported values.
+ '';
+ };
+
+ };
+
+ config = mkIf cfg.enable {
+
+ services.molly-brown.settings = let logDir = "/var/log/molly-brown";
+ in {
+ Port = cfg.port;
+ Hostname = cfg.hostName;
+ CertPath = cfg.certPath;
+ KeyPath = cfg.keyPath;
+ DocBase = cfg.docBase;
+ AccessLog = "${logDir}/access.log";
+ ErrorLog = "${logDir}/error.log";
+ };
+
+ systemd.services.molly-brown = {
+ description = "Molly Brown gemini server";
+ after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ serviceConfig = {
+ DynamicUser = true;
+ LogsDirectory = "molly-brown";
+ ExecStart = "${pkgs.molly-brown}/bin/molly-brown -c ${configFile}";
+ Restart = "always";
+ };
+ };
+
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix b/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix
index 8a015bb3556..4c4b7f39e6b 100644
--- a/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix
@@ -693,6 +693,10 @@ in
wantedBy = [ "multi-user.target" ];
wants = concatLists (map (vhostConfig: ["acme-${vhostConfig.serverName}.service" "acme-selfsigned-${vhostConfig.serverName}.service"]) acmeEnabledVhosts);
after = [ "network.target" ] ++ map (vhostConfig: "acme-selfsigned-${vhostConfig.serverName}.service") acmeEnabledVhosts;
+ # Nginx needs to be started in order to be able to request certificates
+ # (it's hosting the acme challenge after all)
+ # This fixes https://github.com/NixOS/nixpkgs/issues/81842
+ before = map (vhostConfig: "acme-${vhostConfig.serverName}.service") acmeEnabledVhosts;
stopIfChanged = false;
preStart = ''
${cfg.preStart}
diff --git a/nixpkgs/nixos/modules/services/web-servers/unit/default.nix b/nixpkgs/nixos/modules/services/web-servers/unit/default.nix
index 989866144e1..65dcdbed000 100644
--- a/nixpkgs/nixos/modules/services/web-servers/unit/default.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/unit/default.nix
@@ -102,7 +102,7 @@ in {
PIDFile = "/run/unit/unit.pid";
ExecStart = ''
${cfg.package}/bin/unitd --control 'unix:/run/unit/control.unit.sock' --pid '/run/unit/unit.pid' \
- --log '${cfg.logDir}/unit.log' --state '${cfg.stateDir}' \
+ --log '${cfg.logDir}/unit.log' --state '${cfg.stateDir}' --tmp '/tmp' \
--user ${cfg.user} --group ${cfg.group}
'';
ExecStop = ''
diff --git a/nixpkgs/nixos/modules/services/x11/colord.nix b/nixpkgs/nixos/modules/services/x11/colord.nix
index cf113ad2af8..31ccee6aa33 100644
--- a/nixpkgs/nixos/modules/services/x11/colord.nix
+++ b/nixpkgs/nixos/modules/services/x11/colord.nix
@@ -26,7 +26,7 @@ in {
systemd.packages = [ pkgs.colord ];
- environment.etc."tmpfiles.d/colord.conf".source = "${pkgs.colord}/lib/tmpfiles.d/colord.conf";
+ systemd.tmpfiles.packages = [ pkgs.colord ];
users.users.colord = {
isSystemUser = true;
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome3.nix
index bbc7feb2d04..69cf9832172 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -37,10 +37,10 @@ let
chmod -R a+w $out/share/gsettings-schemas/nixos-gsettings-overrides
cat - > $out/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas/nixos-defaults.gschema.override <<- EOF
[org.gnome.desktop.background]
- picture-uri='file://${pkgs.nixos-artwork.wallpapers.simple-dark-gray}/share/artwork/gnome/nix-wallpaper-simple-dark-gray.png'
+ picture-uri='file://${pkgs.nixos-artwork.wallpapers.simple-dark-gray.gnomeFilePath}'
[org.gnome.desktop.screensaver]
- picture-uri='file://${pkgs.nixos-artwork.wallpapers.simple-dark-gray-bottom}/share/artwork/gnome/nix-wallpaper-simple-dark-gray_bottom.png'
+ picture-uri='file://${pkgs.nixos-artwork.wallpapers.simple-dark-gray-bottom.gnomeFilePath}'
[org.gnome.shell]
favorite-apps=[ 'org.gnome.Epiphany.desktop', 'org.gnome.Geary.desktop', 'org.gnome.Music.desktop', 'org.gnome.Photos.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ]
@@ -320,6 +320,8 @@ in
gnome-shell
gnome-shell-extensions
gnome-themes-extra
+ pkgs.nixos-artwork.wallpapers.simple-dark-gray
+ pkgs.nixos-artwork.wallpapers.simple-dark-gray-bottom
pkgs.gnome-user-docs
pkgs.orca
pkgs.glib # for gsettings
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix
index 5fcc8590232..6dabca6bf09 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix
@@ -180,6 +180,7 @@ in
gtk3.out
hicolor-icon-theme
lightlocker
+ nixos-artwork.wallpapers.simple-dark-gray
onboard
qgnomeplatform
shared-mime-info
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix
index 6d48b899d23..75bf55a2639 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix
@@ -321,7 +321,7 @@ in
fonts.fonts = with pkgs; [ noto-fonts hack-font ];
fonts.fontconfig.defaultFonts = {
- monospace = [ "Hack" "Noto Mono" ];
+ monospace = [ "Hack" "Noto Sans Mono" ];
sansSerif = [ "Noto Sans" ];
serif = [ "Noto Serif" ];
};
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/default.nix b/nixpkgs/nixos/modules/services/x11/display-managers/default.nix
index aa6a5ec42be..e990a66d198 100644
--- a/nixpkgs/nixos/modules/services/x11/display-managers/default.nix
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/default.nix
@@ -332,12 +332,45 @@ in
};
+ # Configuration for automatic login. Common for all DM.
+ autoLogin = mkOption {
+ type = types.submodule {
+ options = {
+ enable = mkOption {
+ type = types.bool;
+ default = cfg.displayManager.autoLogin.user != null;
+ description = ''
+ Automatically log in as <option>autoLogin.user</option>.
+ '';
+ };
+
+ user = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description = ''
+ User to be used for the automatic login.
+ '';
+ };
+ };
+ };
+
+ default = {};
+ description = ''
+ Auto login configuration attrset.
+ '';
+ };
+
};
};
config = {
assertions = [
+ { assertion = cfg.displayManager.autoLogin.enable -> cfg.displayManager.autoLogin.user != null;
+ message = ''
+ services.xserver.displayManager.autoLogin.enable requires services.xserver.displayManager.autoLogin.user to be set
+ '';
+ }
{
assertion = cfg.desktopManager.default != null || cfg.windowManager.default != null -> cfg.displayManager.defaultSession == defaultSessionFromLegacyOptions;
message = "You cannot use both services.xserver.displayManager.defaultSession option and legacy options (services.xserver.desktopManager.default and services.xserver.windowManager.default).";
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/gdm.nix b/nixpkgs/nixos/modules/services/x11/display-managers/gdm.nix
index 622ea62f3a9..573049ab07a 100644
--- a/nixpkgs/nixos/modules/services/x11/display-managers/gdm.nix
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/gdm.nix
@@ -37,6 +37,22 @@ let
in
{
+ imports = [
+ (mkRenamedOptionModule [ "services" "xserver" "displayManager" "gdm" "autoLogin" "enable" ] [
+ "services"
+ "xserver"
+ "displayManager"
+ "autoLogin"
+ "enable"
+ ])
+ (mkRenamedOptionModule [ "services" "xserver" "displayManager" "gdm" "autoLogin" "user" ] [
+ "services"
+ "xserver"
+ "displayManager"
+ "autoLogin"
+ "user"
+ ])
+ ];
meta = {
maintainers = teams.gnome.members;
@@ -56,40 +72,13 @@ in
debugging messages in GDM
'';
- autoLogin = mkOption {
- default = {};
+ # Auto login options specific to GDM
+ autoLogin.delay = mkOption {
+ type = types.int;
+ default = 0;
description = ''
- Auto login configuration attrset.
+ Seconds of inactivity after which the autologin will be performed.
'';
-
- type = types.submodule {
- options = {
- enable = mkOption {
- type = types.bool;
- default = false;
- description = ''
- Automatically log in as the sepecified <option>autoLogin.user</option>.
- '';
- };
-
- user = mkOption {
- type = types.nullOr types.str;
- default = null;
- description = ''
- User to be used for the autologin.
- '';
- };
-
- delay = mkOption {
- type = types.int;
- default = 0;
- description = ''
- Seconds of inactivity after which the autologin will be performed.
- '';
- };
-
- };
- };
};
wayland = mkOption {
@@ -128,12 +117,6 @@ in
config = mkIf cfg.gdm.enable {
- assertions = [
- { assertion = cfg.gdm.autoLogin.enable -> cfg.gdm.autoLogin.user != null;
- message = "GDM auto-login requires services.xserver.displayManager.gdm.autoLogin.user to be set";
- }
- ];
-
services.xserver.displayManager.lightdm.enable = false;
users.users.gdm =
@@ -287,14 +270,14 @@ in
environment.etc."gdm/custom.conf".text = ''
[daemon]
WaylandEnable=${if cfg.gdm.wayland then "true" else "false"}
- ${optionalString cfg.gdm.autoLogin.enable (
+ ${optionalString cfg.autoLogin.enable (
if cfg.gdm.autoLogin.delay > 0 then ''
TimedLoginEnable=true
- TimedLogin=${cfg.gdm.autoLogin.user}
+ TimedLogin=${cfg.autoLogin.user}
TimedLoginDelay=${toString cfg.gdm.autoLogin.delay}
'' else ''
AutomaticLoginEnable=true
- AutomaticLogin=${cfg.gdm.autoLogin.user}
+ AutomaticLogin=${cfg.autoLogin.user}
'')
}
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/pantheon.nix b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/pantheon.nix
index 087c6b9c38a..9bc9e2bf616 100644
--- a/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/pantheon.nix
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/pantheon.nix
@@ -43,7 +43,7 @@ in
services.xserver.displayManager.lightdm.extraSeatDefaults = "greeter-show-manual-login=true";
environment.etc."lightdm/io.elementary.greeter.conf".source = "${pkgs.pantheon.elementary-greeter}/etc/lightdm/io.elementary.greeter.conf";
- environment.etc."wingpanel.d/io.elementary.greeter.whitelist".source = "${pkgs.pantheon.elementary-default-settings}/etc/wingpanel.d/io.elementary.greeter.whitelist";
+ environment.etc."wingpanel.d/io.elementary.greeter.allowed".source = "${pkgs.pantheon.elementary-default-settings}/etc/wingpanel.d/io.elementary.greeter.allowed";
};
}
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/lightdm.nix b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm.nix
index 479548863b4..3bee21fa822 100644
--- a/nixpkgs/nixos/modules/services/x11/display-managers/lightdm.nix
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm.nix
@@ -53,8 +53,8 @@ let
${optionalString cfg.greeter.enable ''
greeter-session = ${cfg.greeter.name}
''}
- ${optionalString cfg.autoLogin.enable ''
- autologin-user = ${cfg.autoLogin.user}
+ ${optionalString dmcfg.autoLogin.enable ''
+ autologin-user = ${dmcfg.autoLogin.user}
autologin-user-timeout = ${toString cfg.autoLogin.timeout}
autologin-session = ${sessionData.autologinSession}
''}
@@ -82,6 +82,20 @@ in
./lightdm-greeters/enso-os.nix
./lightdm-greeters/pantheon.nix
./lightdm-greeters/tiny.nix
+ (mkRenamedOptionModule [ "services" "xserver" "displayManager" "lightdm" "autoLogin" "enable" ] [
+ "services"
+ "xserver"
+ "displayManager"
+ "autoLogin"
+ "enable"
+ ])
+ (mkRenamedOptionModule [ "services" "xserver" "displayManager" "lightdm" "autoLogin" "user" ] [
+ "services"
+ "xserver"
+ "displayManager"
+ "autoLogin"
+ "user"
+ ])
];
options = {
@@ -132,8 +146,9 @@ in
};
background = mkOption {
- type = types.str;
- default = "${pkgs.nixos-artwork.wallpapers.simple-dark-gray-bottom}/share/artwork/gnome/nix-wallpaper-simple-dark-gray_bottom.png";
+ type = types.path;
+ # Manual cannot depend on packages, we are actually setting the default in config below.
+ defaultText = "pkgs.nixos-artwork.wallpapers.simple-dark-gray-bottom.gnomeFilePath";
description = ''
The background image or color to use.
'';
@@ -148,39 +163,13 @@ in
description = "Extra lines to append to SeatDefaults section.";
};
- autoLogin = mkOption {
- default = {};
+ # Configuration for automatic login specific to LightDM
+ autoLogin.timeout = mkOption {
+ type = types.int;
+ default = 0;
description = ''
- Configuration for automatic login.
+ Show the greeter for this many seconds before automatic login occurs.
'';
-
- type = types.submodule {
- options = {
- enable = mkOption {
- type = types.bool;
- default = false;
- description = ''
- Automatically log in as the specified <option>autoLogin.user</option>.
- '';
- };
-
- user = mkOption {
- type = types.nullOr types.str;
- default = null;
- description = ''
- User to be used for the automatic login.
- '';
- };
-
- timeout = mkOption {
- type = types.int;
- default = 0;
- description = ''
- Show the greeter for this many seconds before automatic login occurs.
- '';
- };
- };
- };
};
};
@@ -194,17 +183,12 @@ in
LightDM requires services.xserver.enable to be true
'';
}
- { assertion = cfg.autoLogin.enable -> cfg.autoLogin.user != null;
- message = ''
- LightDM auto-login requires services.xserver.displayManager.lightdm.autoLogin.user to be set
- '';
- }
- { assertion = cfg.autoLogin.enable -> sessionData.autologinSession != null;
+ { assertion = dmcfg.autoLogin.enable -> sessionData.autologinSession != null;
message = ''
LightDM auto-login requires that services.xserver.displayManager.defaultSession is set.
'';
}
- { assertion = !cfg.greeter.enable -> (cfg.autoLogin.enable && cfg.autoLogin.timeout == 0);
+ { assertion = !cfg.greeter.enable -> (dmcfg.autoLogin.enable && cfg.autoLogin.timeout == 0);
message = ''
LightDM can only run without greeter if automatic login is enabled and the timeout for it
is set to zero.
@@ -212,9 +196,12 @@ in
}
];
+ # Keep in sync with the defaultText value from the option definition.
+ services.xserver.displayManager.lightdm.background = mkDefault pkgs.nixos-artwork.wallpapers.simple-dark-gray-bottom.gnomeFilePath;
+
# Set default session in session chooser to a specified values – basically ignore session history.
# Auto-login is already covered by a config value.
- services.xserver.displayManager.job.preStart = optionalString (!cfg.autoLogin.enable && dmcfg.defaultSession != null) ''
+ services.xserver.displayManager.job.preStart = optionalString (!dmcfg.autoLogin.enable && dmcfg.defaultSession != null) ''
${setSessionScript}/bin/set-session ${dmcfg.defaultSession}
'';
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/sddm.nix b/nixpkgs/nixos/modules/services/x11/display-managers/sddm.nix
index 2f42271da87..e63bb2e4453 100644
--- a/nixpkgs/nixos/modules/services/x11/display-managers/sddm.nix
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/sddm.nix
@@ -61,9 +61,9 @@ let
EnableHidpi=${if cfg.enableHidpi then "true" else "false"}
SessionDir=${dmcfg.sessionData.desktops}/share/wayland-sessions
- ${optionalString cfg.autoLogin.enable ''
+ ${optionalString dmcfg.autoLogin.enable ''
[Autologin]
- User=${cfg.autoLogin.user}
+ User=${dmcfg.autoLogin.user}
Session=${autoLoginSessionName}.desktop
Relogin=${boolToString cfg.autoLogin.relogin}
''}
@@ -78,6 +78,20 @@ in
imports = [
(mkRemovedOptionModule [ "services" "xserver" "displayManager" "sddm" "themes" ]
"Set the option `services.xserver.displayManager.sddm.package' instead.")
+ (mkRenamedOptionModule [ "services" "xserver" "displayManager" "sddm" "autoLogin" "enable" ] [
+ "services"
+ "xserver"
+ "displayManager"
+ "autoLogin"
+ "enable"
+ ])
+ (mkRenamedOptionModule [ "services" "xserver" "displayManager" "sddm" "autoLogin" "user" ] [
+ "services"
+ "xserver"
+ "displayManager"
+ "autoLogin"
+ "user"
+ ])
];
options = {
@@ -153,40 +167,14 @@ in
'';
};
- autoLogin = mkOption {
- default = {};
+ # Configuration for automatic login specific to SDDM
+ autoLogin.relogin = mkOption {
+ type = types.bool;
+ default = false;
description = ''
- Configuration for automatic login.
+ If true automatic login will kick in again on session exit (logout), otherwise it
+ will only log in automatically when the display-manager is started.
'';
-
- type = types.submodule {
- options = {
- enable = mkOption {
- type = types.bool;
- default = false;
- description = ''
- Automatically log in as <option>autoLogin.user</option>.
- '';
- };
-
- user = mkOption {
- type = types.nullOr types.str;
- default = null;
- description = ''
- User to be used for the automatic login.
- '';
- };
-
- relogin = mkOption {
- type = types.bool;
- default = false;
- description = ''
- If true automatic login will kick in again on session exit (logout), otherwise it
- will only log in automatically when the display-manager is started.
- '';
- };
- };
- };
};
};
@@ -201,12 +189,7 @@ in
SDDM requires services.xserver.enable to be true
'';
}
- { assertion = cfg.autoLogin.enable -> cfg.autoLogin.user != null;
- message = ''
- SDDM auto-login requires services.xserver.displayManager.sddm.autoLogin.user to be set
- '';
- }
- { assertion = cfg.autoLogin.enable -> autoLoginSessionName != null;
+ { assertion = dmcfg.autoLogin.enable -> autoLoginSessionName != null;
message = ''
SDDM auto-login requires that services.xserver.displayManager.defaultSession is set.
'';
diff --git a/nixpkgs/nixos/modules/services/x11/xserver.nix b/nixpkgs/nixos/modules/services/x11/xserver.nix
index 6aec1c0753a..400173745d3 100644
--- a/nixpkgs/nixos/modules/services/x11/xserver.nix
+++ b/nixpkgs/nixos/modules/services/x11/xserver.nix
@@ -246,7 +246,7 @@ in
videoDrivers = mkOption {
type = types.listOf types.str;
# !!! We'd like "nv" here, but it segfaults the X server.
- default = [ "radeon" "cirrus" "vesa" "vmware" "modesetting" ];
+ default = [ "radeon" "cirrus" "vesa" "modesetting" ];
example = [
"ati_unfree" "amdgpu" "amdgpu-pro"
"nv" "nvidia" "nvidiaLegacy390" "nvidiaLegacy340" "nvidiaLegacy304"
diff --git a/nixpkgs/nixos/modules/system/activation/top-level.nix b/nixpkgs/nixos/modules/system/activation/top-level.nix
index f6739977fa4..fb8644dd13a 100644
--- a/nixpkgs/nixos/modules/system/activation/top-level.nix
+++ b/nixpkgs/nixos/modules/system/activation/top-level.nix
@@ -92,9 +92,7 @@ let
# `switch-to-configuration' that activates the configuration and
# makes it bootable.
baseSystem = pkgs.stdenvNoCC.mkDerivation {
- name = let hn = config.networking.hostName;
- nn = if (hn != "") then hn else "unnamed";
- in "nixos-system-${nn}-${config.system.nixos.label}";
+ name = "nixos-system-${config.system.name}-${config.system.nixos.label}";
preferLocalBuild = true;
allowSubstitutes = false;
buildCommand = systemBuilder;
@@ -265,6 +263,21 @@ in
'';
};
+ system.name = mkOption {
+ type = types.str;
+ default =
+ if config.networking.hostName == ""
+ then "unnamed"
+ else config.networking.hostName;
+ defaultText = '''networking.hostName' if non empty else "unnamed"'';
+ description = ''
+ The name of the system used in the <option>system.build.toplevel</option> derivation.
+ </para><para>
+ That derivation has the following name:
+ <literal>"nixos-system-''${config.system.name}-''${config.system.nixos.label}"</literal>
+ '';
+ };
+
};
diff --git a/nixpkgs/nixos/modules/system/boot/initrd-network.nix b/nixpkgs/nixos/modules/system/boot/initrd-network.nix
index 0ab6e626b34..ec794d6eb01 100644
--- a/nixpkgs/nixos/modules/system/boot/initrd-network.nix
+++ b/nixpkgs/nixos/modules/system/boot/initrd-network.nix
@@ -139,7 +139,7 @@ in
boot.initrd.postMountCommands = mkIf cfg.flushBeforeStage2 ''
for iface in $ifaces; do
ip address flush "$iface"
- ip link down "$iface"
+ ip link set "$iface" down
done
'';
diff --git a/nixpkgs/nixos/modules/system/boot/initrd-openvpn.nix b/nixpkgs/nixos/modules/system/boot/initrd-openvpn.nix
new file mode 100644
index 00000000000..7553c2aebb1
--- /dev/null
+++ b/nixpkgs/nixos/modules/system/boot/initrd-openvpn.nix
@@ -0,0 +1,81 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.boot.initrd.network.openvpn;
+
+in
+
+{
+
+ options = {
+
+ boot.initrd.network.openvpn.enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Starts an OpenVPN client during initrd boot. It can be used to e.g.
+ remotely accessing the SSH service controlled by
+ <option>boot.initrd.network.ssh</option> or other network services
+ included. Service is killed when stage-1 boot is finished.
+ '';
+ };
+
+ boot.initrd.network.openvpn.configuration = mkOption {
+ type = types.path; # Same type as boot.initrd.secrets
+ description = ''
+ The configuration file for OpenVPN.
+
+ <warning>
+ <para>
+ Unless your bootloader supports initrd secrets, this configuration
+ is stored insecurely in the global Nix store.
+ </para>
+ </warning>
+ '';
+ example = "./configuration.ovpn";
+ };
+
+ };
+
+ config = mkIf (config.boot.initrd.network.enable && cfg.enable) {
+ assertions = [
+ {
+ assertion = cfg.configuration != null;
+ message = "You should specify a configuration for initrd OpenVPN";
+ }
+ ];
+
+ # Add kernel modules needed for OpenVPN
+ boot.initrd.kernelModules = [ "tun" "tap" ];
+
+ # Add openvpn and ip binaries to the initrd
+ # The shared libraries are required for DNS resolution
+ boot.initrd.extraUtilsCommands = ''
+ copy_bin_and_libs ${pkgs.openvpn}/bin/openvpn
+ copy_bin_and_libs ${pkgs.iproute}/bin/ip
+
+ cp -pv ${pkgs.glibc}/lib/libresolv.so.2 $out/lib
+ cp -pv ${pkgs.glibc}/lib/libnss_dns.so.2 $out/lib
+ '';
+
+ boot.initrd.secrets = {
+ "/etc/initrd.ovpn" = cfg.configuration;
+ };
+
+ # openvpn --version would exit with 1 instead of 0
+ boot.initrd.extraUtilsCommandsTest = ''
+ $out/bin/openvpn --show-gateway
+ '';
+
+ # Add `iproute /bin/ip` to the config, to ensure that openvpn
+ # is able to set the routes
+ boot.initrd.network.postCommands = ''
+ (cat /etc/initrd.ovpn; echo -e '\niproute /bin/ip') | \
+ openvpn /dev/stdin &
+ '';
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/system/boot/kernel_config.nix b/nixpkgs/nixos/modules/system/boot/kernel_config.nix
index a316782dfc5..783685c9dfe 100644
--- a/nixpkgs/nixos/modules/system/boot/kernel_config.nix
+++ b/nixpkgs/nixos/modules/system/boot/kernel_config.nix
@@ -22,7 +22,7 @@ let
mergeFalseByDefault = locs: defs:
if defs == [] then abort "This case should never happen."
- else if any (x: x == false) defs then false
+ else if any (x: x == false) (getValues defs) then false
else true;
kernelItem = types.submodule {
@@ -54,7 +54,8 @@ let
type = types.bool // { merge = mergeFalseByDefault; };
default = false;
description = ''
- Wether option should generate a failure when unused.
+ Whether option should generate a failure when unused.
+ Upon merging values, mandatory wins over optional.
'';
};
};
@@ -121,7 +122,7 @@ in
type = types.attrsOf kernelItem;
example = literalExample '' with lib.kernel; {
"9P_NET" = yes;
- USB = optional yes;
+ USB = option yes;
MMC_BLOCK_MINORS = freeform "32";
}'';
description = ''
diff --git a/nixpkgs/nixos/modules/system/boot/loader/generic-extlinux-compatible/default.nix b/nixpkgs/nixos/modules/system/boot/loader/generic-extlinux-compatible/default.nix
index af39c7bb684..bd508bbe8ea 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/generic-extlinux-compatible/default.nix
+++ b/nixpkgs/nixos/modules/system/boot/loader/generic-extlinux-compatible/default.nix
@@ -4,11 +4,15 @@ with lib;
let
blCfg = config.boot.loader;
+ dtCfg = config.hardware.deviceTree;
cfg = blCfg.generic-extlinux-compatible;
timeoutStr = if blCfg.timeout == null then "-1" else toString blCfg.timeout;
+ # The builder used to write during system activation
builder = import ./extlinux-conf-builder.nix { inherit pkgs; };
+ # The builder exposed in populateCmd, which runs on the build architecture
+ populateBuilder = import ./extlinux-conf-builder.nix { pkgs = pkgs.buildPackages; };
in
{
options = {
@@ -34,11 +38,28 @@ in
Maximum number of configurations in the boot menu.
'';
};
+
+ populateCmd = mkOption {
+ type = types.str;
+ readOnly = true;
+ description = ''
+ Contains the builder command used to populate an image,
+ honoring all options except the <literal>-c &lt;path-to-default-configuration&gt;</literal>
+ argument.
+ Useful to have for sdImage.populateRootCommands
+ '';
+ };
+
};
};
- config = mkIf cfg.enable {
- system.build.installBootLoader = "${builder} -g ${toString cfg.configurationLimit} -t ${timeoutStr} -c";
- system.boot.loader.id = "generic-extlinux-compatible";
- };
+ config = let
+ builderArgs = "-g ${toString cfg.configurationLimit} -t ${timeoutStr}" + lib.optionalString (dtCfg.name != null) " -n ${dtCfg.name}";
+ in
+ mkIf cfg.enable {
+ system.build.installBootLoader = "${builder} ${builderArgs} -c";
+ system.boot.loader.id = "generic-extlinux-compatible";
+
+ boot.loader.generic-extlinux-compatible.populateCmd = "${populateBuilder} ${builderArgs}";
+ };
}
diff --git a/nixpkgs/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh b/nixpkgs/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh
index 0092ee92b62..854684b87fa 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh
+++ b/nixpkgs/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh
@@ -6,7 +6,7 @@ export PATH=/empty
for i in @path@; do PATH=$PATH:$i/bin; done
usage() {
- echo "usage: $0 -t <timeout> -c <path-to-default-configuration> [-d <boot-dir>] [-g <num-generations>]" >&2
+ echo "usage: $0 -t <timeout> -c <path-to-default-configuration> [-d <boot-dir>] [-g <num-generations>] [-n <dtbName>]" >&2
exit 1
}
@@ -15,7 +15,7 @@ default= # Default configuration
target=/boot # Target directory
numGenerations=0 # Number of other generations to include in the menu
-while getopts "t:c:d:g:" opt; do
+while getopts "t:c:d:g:n:" opt; do
case "$opt" in
t) # U-Boot interprets '0' as infinite and negative as instant boot
if [ "$OPTARG" -lt 0 ]; then
@@ -29,6 +29,7 @@ while getopts "t:c:d:g:" opt; do
c) default="$OPTARG" ;;
d) target="$OPTARG" ;;
g) numGenerations="$OPTARG" ;;
+ n) dtbName="$OPTARG" ;;
\?) usage ;;
esac
done
@@ -96,7 +97,17 @@ addEntry() {
echo " LINUX ../nixos/$(basename $kernel)"
echo " INITRD ../nixos/$(basename $initrd)"
if [ -d "$dtbDir" ]; then
- echo " FDTDIR ../nixos/$(basename $dtbs)"
+ # if a dtbName was specified explicitly, use that, else use FDTDIR
+ if [ -n "$dtbName" ]; then
+ echo " FDT ../nixos/$(basename $dtbs)/${dtbName}"
+ else
+ echo " FDTDIR ../nixos/$(basename $dtbs)"
+ fi
+ else
+ if [ -n "$dtbName" ]; then
+ echo "Explicitly requested dtbName $dtbName, but there's no FDTDIR - bailing out." >&2
+ exit 1
+ fi
fi
echo " APPEND systemConfig=$path init=$path/init $extraParams"
}
diff --git a/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix b/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix
index 67e8bf6fd65..20e39628eab 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix
+++ b/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix
@@ -55,11 +55,14 @@ let
storePath = config.boot.loader.grub.storePath;
bootloaderId = if args.efiBootloaderId == null then "NixOS${efiSysMountPoint'}" else args.efiBootloaderId;
timeout = if config.boot.loader.timeout == null then -1 else config.boot.loader.timeout;
+ users = if cfg.users == {} || cfg.version != 1 then cfg.users else throw "GRUB version 1 does not support user accounts.";
+ theme = f cfg.theme;
inherit efiSysMountPoint;
inherit (args) devices;
inherit (efi) canTouchEfiVariables;
inherit (cfg)
version extraConfig extraPerEntryConfig extraEntries forceInstall useOSProber
+ extraGrubInstallArgs
extraEntriesBeforeNixOS extraPrepareConfig configurationLimit copyKernels
default fsIdentifier efiSupport efiInstallAsRemovable gfxmodeEfi gfxmodeBios gfxpayloadEfi gfxpayloadBios;
path = with pkgs; makeBinPath (
@@ -83,7 +86,7 @@ let
] ++ (optional (cfg.fontSize!=null) "--size ${toString cfg.fontSize}")))
);
- defaultSplash = "${pkgs.nixos-artwork.wallpapers.simple-dark-gray-bootloader}/share/artwork/gnome/nix-wallpaper-simple-dark-gray_bootloader.png";
+ defaultSplash = pkgs.nixos-artwork.wallpapers.simple-dark-gray-bootloader.gnomeFilePath;
in
{
@@ -137,6 +140,67 @@ in
'';
};
+ users = mkOption {
+ default = {};
+ example = {
+ root = { hashedPasswordFile = "/path/to/file"; };
+ };
+ description = ''
+ User accounts for GRUB. When specified, the GRUB command line and
+ all boot options except the default are password-protected.
+ All passwords and hashes provided will be stored in /boot/grub/grub.cfg,
+ and will be visible to any local user who can read this file. Additionally,
+ any passwords and hashes provided directly in a Nix configuration
+ (as opposed to external files) will be copied into the Nix store, and
+ will be visible to all local users.
+ '';
+ type = with types; attrsOf (submodule {
+ options = {
+ hashedPasswordFile = mkOption {
+ example = "/path/to/file";
+ default = null;
+ type = with types; uniq (nullOr str);
+ description = ''
+ Specifies the path to a file containing the password hash
+ for the account, generated with grub-mkpasswd-pbkdf2.
+ This hash will be stored in /boot/grub/grub.cfg, and will
+ be visible to any local user who can read this file.
+ '';
+ };
+ hashedPassword = mkOption {
+ example = "grub.pbkdf2.sha512.10000.674DFFDEF76E13EA...2CC972B102CF4355";
+ default = null;
+ type = with types; uniq (nullOr str);
+ description = ''
+ Specifies the password hash for the account,
+ generated with grub-mkpasswd-pbkdf2.
+ This hash will be copied to the Nix store, and will be visible to all local users.
+ '';
+ };
+ passwordFile = mkOption {
+ example = "/path/to/file";
+ default = null;
+ type = with types; uniq (nullOr str);
+ description = ''
+ Specifies the path to a file containing the
+ clear text password for the account.
+ This password will be stored in /boot/grub/grub.cfg, and will
+ be visible to any local user who can read this file.
+ '';
+ };
+ password = mkOption {
+ example = "Pa$$w0rd!";
+ default = null;
+ type = with types; uniq (nullOr str);
+ description = ''
+ Specifies the clear text password for the account.
+ This password will be copied to the Nix store, and will be visible to all local users.
+ '';
+ };
+ };
+ });
+ };
+
mirroredBoots = mkOption {
default = [ ];
example = [
@@ -236,6 +300,33 @@ in
'';
};
+ extraGrubInstallArgs = mkOption {
+ default = [ ];
+ example = [ "--modules=nativedisk ahci pata part_gpt part_msdos diskfilter mdraid1x lvm ext2" ];
+ type = types.listOf types.str;
+ description = ''
+ Additional arguments passed to <literal>grub-install</literal>.
+
+ A use case for this is to build specific GRUB2 modules
+ directly into the GRUB2 kernel image, so that they are available
+ and activated even in the <literal>grub rescue</literal> shell.
+
+ They are also necessary when the BIOS/UEFI is bugged and cannot
+ correctly read large disks (e.g. above 2 TB), so GRUB2's own
+ <literal>nativedisk</literal> and related modules can be used
+ to use its own disk drivers. The example shows one such case.
+ This is also useful for booting from USB.
+ See the
+ <link xlink:href="http://git.savannah.gnu.org/cgit/grub.git/tree/grub-core/commands/nativedisk.c?h=grub-2.04#n326">
+ GRUB source code
+ </link>
+ for which disk modules are available.
+
+ The list elements are passed directly as <literal>argv</literal>
+ arguments to the <literal>grub-install</literal> program, in order.
+ '';
+ };
+
extraPerEntryConfig = mkOption {
default = "";
example = "root (hd0)";
@@ -336,6 +427,19 @@ in
'';
};
+ theme = mkOption {
+ type = types.nullOr types.path;
+ example = literalExample "pkgs.nixos-grub2-theme";
+ default = null;
+ description = ''
+ Grub theme to be used.
+
+ <note><para>
+ This options has no effect for GRUB 1.
+ </para></note>
+ '';
+ };
+
splashMode = mkOption {
type = types.enum [ "normal" "stretch" ];
default = "stretch";
@@ -607,7 +711,7 @@ in
in pkgs.writeScript "install-grub.sh" (''
#!${pkgs.runtimeShell}
set -e
- export PERL5LIB=${with pkgs.perlPackages; makePerlPath [ FileSlurp XMLLibXML XMLSAX XMLSAXBase ListCompare ]}
+ export PERL5LIB=${with pkgs.perlPackages; makePerlPath [ FileSlurp FileCopyRecursive XMLLibXML XMLSAX XMLSAXBase ListCompare JSON ]}
${optionalString cfg.enableCryptodisk "export GRUB_ENABLE_CRYPTODISK=y"}
'' + flip concatMapStrings cfg.mirroredBoots (args: ''
${pkgs.perl}/bin/perl ${install-grub-pl} ${grubConfig args} $@
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 e469b18abd0..59f5638044f 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl
+++ b/nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl
@@ -6,8 +6,11 @@ use File::Basename;
use File::Path;
use File::stat;
use File::Copy;
+use File::Copy::Recursive qw(rcopy pathrm);
use File::Slurp;
use File::Temp;
+use JSON;
+use File::Find;
require List::Compare;
use POSIX;
use Cwd;
@@ -20,6 +23,16 @@ my $dom = XML::LibXML->load_xml(location => $ARGV[0]);
sub get { my ($name) = @_; return $dom->findvalue("/expr/attrs/attr[\@name = '$name']/*/\@value"); }
+sub getList {
+ my ($name) = @_;
+ my @list = ();
+ foreach my $entry ($dom->findnodes("/expr/attrs/attr[\@name = '$name']/list/string/\@value")) {
+ $entry = $entry->findvalue(".") or die;
+ push(@list, $entry);
+ }
+ return @list;
+}
+
sub readFile {
my ($fn) = @_; local $/ = undef;
open FILE, "<$fn" or return undef; my $s = <FILE>; close FILE;
@@ -71,6 +84,7 @@ my $gfxpayloadBios = get("gfxpayloadBios");
my $bootloaderId = get("bootloaderId");
my $forceInstall = get("forceInstall");
my $font = get("font");
+my $theme = get("theme");
$ENV{'PATH'} = get("path");
die "unsupported GRUB version\n" if $grubVersion != 1 && $grubVersion != 2;
@@ -241,12 +255,51 @@ if ($grubVersion == 1) {
timeout $timeout
";
if ($splashImage) {
- copy $splashImage, "$bootPath/background.xpm.gz" or die "cannot copy $splashImage to $bootPath\n";
+ copy $splashImage, "$bootPath/background.xpm.gz" or die "cannot copy $splashImage to $bootPath: $!\n";
$conf .= "splashimage " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/background.xpm.gz\n";
}
}
else {
+ my @users = ();
+ foreach my $user ($dom->findnodes('/expr/attrs/attr[@name = "users"]/attrs/attr')) {
+ my $name = $user->findvalue('@name') or die;
+ my $hashedPassword = $user->findvalue('./attrs/attr[@name = "hashedPassword"]/string/@value');
+ my $hashedPasswordFile = $user->findvalue('./attrs/attr[@name = "hashedPasswordFile"]/string/@value');
+ my $password = $user->findvalue('./attrs/attr[@name = "password"]/string/@value');
+ my $passwordFile = $user->findvalue('./attrs/attr[@name = "passwordFile"]/string/@value');
+
+ if ($hashedPasswordFile) {
+ open(my $f, '<', $hashedPasswordFile) or die "Can't read file '$hashedPasswordFile'!";
+ $hashedPassword = <$f>;
+ chomp $hashedPassword;
+ }
+ if ($passwordFile) {
+ open(my $f, '<', $passwordFile) or die "Can't read file '$passwordFile'!";
+ $password = <$f>;
+ chomp $password;
+ }
+
+ if ($hashedPassword) {
+ if (index($hashedPassword, "grub.pbkdf2.") == 0) {
+ $conf .= "\npassword_pbkdf2 $name $hashedPassword";
+ }
+ else {
+ die "Password hash for GRUB user '$name' is not valid!";
+ }
+ }
+ elsif ($password) {
+ $conf .= "\npassword $name $password";
+ }
+ else {
+ die "GRUB user '$name' has no password!";
+ }
+ push(@users, $name);
+ }
+ if (@users) {
+ $conf .= "\nset superusers=\"" . join(' ',@users) . "\"\n";
+ }
+
if ($copyKernels == 0) {
$conf .= "
" . $grubStore->search;
@@ -280,7 +333,7 @@ else {
";
if ($font) {
- copy $font, "$bootPath/converted-font.pf2" or die "cannot copy $font to $bootPath\n";
+ copy $font, "$bootPath/converted-font.pf2" or die "cannot copy $font to $bootPath: $!\n";
$conf .= "
insmod font
if loadfont " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/converted-font.pf2; then
@@ -308,7 +361,7 @@ else {
background_color '$backgroundColor'
";
}
- copy $splashImage, "$bootPath/background$suffix" or die "cannot copy $splashImage to $bootPath\n";
+ copy $splashImage, "$bootPath/background$suffix" or die "cannot copy $splashImage to $bootPath: $!\n";
$conf .= "
insmod " . substr($suffix, 1) . "
if background_image --mode '$splashMode' " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/background$suffix; then
@@ -320,6 +373,28 @@ else {
fi
";
}
+
+ rmtree("$bootPath/theme") or die "cannot clean up theme folder in $bootPath\n" if -e "$bootPath/theme";
+
+ if ($theme) {
+ # Copy theme
+ rcopy($theme, "$bootPath/theme") or die "cannot copy $theme to $bootPath\n";
+ $conf .= "
+ # Sets theme.
+ set theme=" . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/theme/theme.txt
+ export theme
+ # Load theme fonts, if any
+ ";
+
+ find( { wanted => sub {
+ if ($_ =~ /\.pf2$/i) {
+ $font = File::Spec->abs2rel($File::Find::name, $theme);
+ $conf .= "
+ loadfont " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/theme/$font
+ ";
+ }
+ }, no_chdir => 1 }, $theme );
+ }
}
$conf .= "$extraConfig\n";
@@ -342,15 +417,15 @@ sub copyToKernelsDir {
# kernels or initrd if this script is ever interrupted.
if (! -e $dst) {
my $tmp = "$dst.tmp";
- copy $path, $tmp or die "cannot copy $path to $tmp\n";
- rename $tmp, $dst or die "cannot rename $tmp to $dst\n";
+ copy $path, $tmp or die "cannot copy $path to $tmp: $!\n";
+ rename $tmp, $dst or die "cannot rename $tmp to $dst: $!\n";
}
$copied{$dst} = 1;
return ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/kernels/$name";
}
sub addEntry {
- my ($name, $path) = @_;
+ my ($name, $path, $options) = @_;
return unless -e "$path/kernel" && -e "$path/initrd";
my $kernel = copyToKernelsDir(Cwd::abs_path("$path/kernel"));
@@ -366,10 +441,10 @@ sub addEntry {
# Make sure initrd is not world readable (won't work if /boot is FAT)
umask 0137;
my $initrdSecretsPathTemp = File::Temp::mktemp("$initrdSecretsPath.XXXXXXXX");
- system("$path/append-initrd-secrets", $initrdSecretsPathTemp) == 0 or die "failed to create initrd secrets\n";
+ system("$path/append-initrd-secrets", $initrdSecretsPathTemp) == 0 or die "failed to create initrd secrets: $!\n";
# Check whether any secrets were actually added
if (-e $initrdSecretsPathTemp && ! -z _) {
- rename $initrdSecretsPathTemp, $initrdSecretsPath or die "failed to move initrd secrets into place\n";
+ rename $initrdSecretsPathTemp, $initrdSecretsPath or die "failed to move initrd secrets into place: $!\n";
$copied{$initrdSecretsPath} = 1;
$initrd .= " " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/kernels/$initrdName-secrets";
} else {
@@ -396,7 +471,7 @@ sub addEntry {
$conf .= " " . ($xen ? "module" : "kernel") . " $kernel $kernelParams\n";
$conf .= " " . ($xen ? "module" : "initrd") . " $initrd\n\n";
} else {
- $conf .= "menuentry \"$name\" {\n";
+ $conf .= "menuentry \"$name\" " . ($options||"") . " {\n";
$conf .= $grubBoot->search . "\n";
if ($copyKernels == 0) {
$conf .= $grubStore->search . "\n";
@@ -413,7 +488,7 @@ sub addEntry {
# Add default entries.
$conf .= "$extraEntries\n" if $extraEntriesBeforeNixOS;
-addEntry("NixOS - Default", $defaultConfig);
+addEntry("NixOS - Default", $defaultConfig, "--unrestricted");
$conf .= "$extraEntries\n" unless $extraEntriesBeforeNixOS;
@@ -536,7 +611,7 @@ if (get("useOSProber") eq "true") {
}
# Atomically switch to the new config
-rename $tmpFile, $confFile or die "cannot rename $tmpFile to $confFile\n";
+rename $tmpFile, $confFile or die "cannot rename $tmpFile to $confFile: $!\n";
# Remove obsolete files from $bootPath/kernels.
@@ -557,9 +632,12 @@ struct(GrubState => {
efi => '$',
devices => '$',
efiMountPoint => '$',
+ extraGrubInstallArgs => '@',
});
+# If you add something to the state file, only add it to the end
+# because it is read line-by-line.
sub readGrubState {
- my $defaultGrubState = GrubState->new(name => "", version => "", efi => "", devices => "", efiMountPoint => "" );
+ my $defaultGrubState = GrubState->new(name => "", version => "", efi => "", devices => "", efiMountPoint => "", extraGrubInstallArgs => () );
open FILE, "<$bootPath/grub/state" or return $defaultGrubState;
local $/ = "\n";
my $name = <FILE>;
@@ -572,24 +650,37 @@ sub readGrubState {
chomp($devices);
my $efiMountPoint = <FILE>;
chomp($efiMountPoint);
+ # Historically, arguments in the state file were one per each line, but that
+ # gets really messy when newlines are involved, structured arguments
+ # like lists are needed (they have to have a separator encoding), or even worse,
+ # when we need to remove a setting in the future. Thus, the 6th line is a JSON
+ # object that can store structured data, with named keys, and all new state
+ # should go in there.
+ my $jsonStateLine = <FILE>;
+ # For historical reasons we do not check the values above for un-definedness
+ # (that is, when the state file has too few lines and EOF is reached),
+ # because the above come from the first version of this logic and are thus
+ # guaranteed to be present.
+ $jsonStateLine = defined $jsonStateLine ? $jsonStateLine : '{}'; # empty JSON object
+ chomp($jsonStateLine);
+ if ($jsonStateLine eq "") {
+ $jsonStateLine = '{}'; # empty JSON object
+ }
+ my %jsonState = %{decode_json($jsonStateLine)};
+ my @extraGrubInstallArgs = exists($jsonState{'extraGrubInstallArgs'}) ? @{$jsonState{'extraGrubInstallArgs'}} : ();
close FILE;
- my $grubState = GrubState->new(name => $name, version => $version, efi => $efi, devices => $devices, efiMountPoint => $efiMountPoint );
+ my $grubState = GrubState->new(name => $name, version => $version, efi => $efi, devices => $devices, efiMountPoint => $efiMountPoint, extraGrubInstallArgs => \@extraGrubInstallArgs );
return $grubState
}
-sub getDeviceTargets {
- my @devices = ();
- foreach my $dev ($dom->findnodes('/expr/attrs/attr[@name = "devices"]/list/string/@value')) {
- $dev = $dev->findvalue(".") or die;
- push(@devices, $dev);
- }
- return @devices;
-}
-my @deviceTargets = getDeviceTargets();
+my @deviceTargets = getList('devices');
my $prevGrubState = readGrubState();
my @prevDeviceTargets = split/,/, $prevGrubState->devices;
+my @extraGrubInstallArgs = getList('extraGrubInstallArgs');
+my @prevExtraGrubInstallArgs = @{$prevGrubState->extraGrubInstallArgs};
my $devicesDiffer = scalar (List::Compare->new( '-u', '-a', \@deviceTargets, \@prevDeviceTargets)->get_symmetric_difference());
+my $extraGrubInstallArgsDiffer = scalar (List::Compare->new( '-u', '-a', \@extraGrubInstallArgs, \@prevExtraGrubInstallArgs)->get_symmetric_difference());
my $nameDiffer = get("fullName") ne $prevGrubState->name;
my $versionDiffer = get("fullVersion") ne $prevGrubState->version;
my $efiDiffer = $efiTarget ne $prevGrubState->efi;
@@ -598,25 +689,25 @@ if (($ENV{'NIXOS_INSTALL_GRUB'} // "") eq "1") {
warn "NIXOS_INSTALL_GRUB env var deprecated, use NIXOS_INSTALL_BOOTLOADER";
$ENV{'NIXOS_INSTALL_BOOTLOADER'} = "1";
}
-my $requireNewInstall = $devicesDiffer || $nameDiffer || $versionDiffer || $efiDiffer || $efiMountPointDiffer || (($ENV{'NIXOS_INSTALL_BOOTLOADER'} // "") eq "1");
+my $requireNewInstall = $devicesDiffer || $extraGrubInstallArgsDiffer || $nameDiffer || $versionDiffer || $efiDiffer || $efiMountPointDiffer || (($ENV{'NIXOS_INSTALL_BOOTLOADER'} // "") eq "1");
# install a symlink so that grub can detect the boot drive
-my $tmpDir = File::Temp::tempdir(CLEANUP => 1) or die "Failed to create temporary space";
-symlink "$bootPath", "$tmpDir/boot" or die "Failed to symlink $tmpDir/boot";
+my $tmpDir = File::Temp::tempdir(CLEANUP => 1) or die "Failed to create temporary space: $!";
+symlink "$bootPath", "$tmpDir/boot" or die "Failed to symlink $tmpDir/boot: $!";
# install non-EFI GRUB
if (($requireNewInstall != 0) && ($efiTarget eq "no" || $efiTarget eq "both")) {
foreach my $dev (@deviceTargets) {
next if $dev eq "nodev";
print STDERR "installing the GRUB $grubVersion boot loader on $dev...\n";
- my @command = ("$grub/sbin/grub-install", "--recheck", "--root-directory=$tmpDir", Cwd::abs_path($dev));
+ my @command = ("$grub/sbin/grub-install", "--recheck", "--root-directory=$tmpDir", Cwd::abs_path($dev), @extraGrubInstallArgs);
if ($forceInstall eq "true") {
push @command, "--force";
}
if ($grubTarget ne "") {
push @command, "--target=$grubTarget";
}
- (system @command) == 0 or die "$0: installation of GRUB on $dev failed\n";
+ (system @command) == 0 or die "$0: installation of GRUB on $dev failed: $!\n";
}
}
@@ -624,7 +715,7 @@ if (($requireNewInstall != 0) && ($efiTarget eq "no" || $efiTarget eq "both")) {
# install EFI GRUB
if (($requireNewInstall != 0) && ($efiTarget eq "only" || $efiTarget eq "both")) {
print STDERR "installing the GRUB $grubVersion EFI boot loader into $efiSysMountPoint...\n";
- my @command = ("$grubEfi/sbin/grub-install", "--recheck", "--target=$grubTargetEfi", "--boot-directory=$bootPath", "--efi-directory=$efiSysMountPoint");
+ my @command = ("$grubEfi/sbin/grub-install", "--recheck", "--target=$grubTargetEfi", "--boot-directory=$bootPath", "--efi-directory=$efiSysMountPoint", @extraGrubInstallArgs);
if ($forceInstall eq "true") {
push @command, "--force";
}
@@ -635,17 +726,29 @@ if (($requireNewInstall != 0) && ($efiTarget eq "only" || $efiTarget eq "both"))
push @command, "--removable" if $efiInstallAsRemovable eq "true";
}
- (system @command) == 0 or die "$0: installation of GRUB EFI into $efiSysMountPoint failed\n";
+ (system @command) == 0 or die "$0: installation of GRUB EFI into $efiSysMountPoint failed: $!\n";
}
# update GRUB state file
if ($requireNewInstall != 0) {
- open FILE, ">$bootPath/grub/state" or die "cannot create $bootPath/grub/state: $!\n";
+ # Temp file for atomic rename.
+ my $stateFile = "$bootPath/grub/state";
+ my $stateFileTmp = $stateFile . ".tmp";
+
+ open FILE, ">$stateFileTmp" or die "cannot create $stateFileTmp: $!\n";
print FILE get("fullName"), "\n" or die;
print FILE get("fullVersion"), "\n" or die;
print FILE $efiTarget, "\n" or die;
print FILE join( ",", @deviceTargets ), "\n" or die;
print FILE $efiSysMountPoint, "\n" or die;
+ my %jsonState = (
+ extraGrubInstallArgs => \@extraGrubInstallArgs
+ );
+ my $jsonStateLine = encode_json(\%jsonState);
+ print FILE $jsonStateLine, "\n" or die;
close FILE or die;
+
+ # Atomically switch to the new state file
+ rename $stateFileTmp, $stateFile or die "cannot rename $stateFileTmp to $stateFile: $!\n";
}
diff --git a/nixpkgs/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.sh b/nixpkgs/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.sh
index c8b5bf2e61a..0541ca1ba62 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.sh
+++ b/nixpkgs/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.sh
@@ -1,4 +1,7 @@
-#! @bash@/bin/sh -e
+#! @bash@/bin/sh
+
+# This can end up being called disregarding the shebang.
+set -e
shopt -s nullglob
diff --git a/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py b/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
index f48a085ce57..97e824fe629 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
+++ b/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
@@ -47,9 +47,9 @@ def write_loader_conf(profile, generation):
if "@timeout@" != "":
f.write("timeout @timeout@\n")
if profile:
- f.write("default nixos-%s-generation-%d\n" % (profile, generation))
+ f.write("default nixos-%s-generation-%d.conf\n" % (profile, generation))
else:
- f.write("default nixos-generation-%d\n" % (generation))
+ f.write("default nixos-generation-%d.conf\n" % (generation))
if not @editor@:
f.write("editor 0\n");
f.write("console-mode @consoleMode@\n");
@@ -197,6 +197,22 @@ def main():
subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "install"])
else:
subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "--no-variables", "install"])
+ else:
+ # Update bootloader to latest if needed
+ systemd_version = subprocess.check_output(["@systemd@/bin/bootctl", "--version"], universal_newlines=True).split()[1]
+ sdboot_status = subprocess.check_output(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "status"], universal_newlines=True)
+
+ # See status_binaries() in systemd bootctl.c for code which generates this
+ m = re.search("^\W+File:.*/EFI/(BOOT|systemd)/.*\.efi \(systemd-boot (\d+)\)$",
+ sdboot_status, re.IGNORECASE | re.MULTILINE)
+ if m is None:
+ print("could not find any previously installed systemd-boot")
+ else:
+ sdboot_version = m.group(2)
+ if systemd_version > sdboot_version:
+ print("updating systemd-boot from %s to %s" % (sdboot_version, systemd_version))
+ subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "update"])
+
mkdir_p("@efiSysMountPoint@/efi/nixos")
mkdir_p("@efiSysMountPoint@/loader/entries")
diff --git a/nixpkgs/nixos/modules/system/boot/luksroot.nix b/nixpkgs/nixos/modules/system/boot/luksroot.nix
index 31f1e22cda3..166f89c7066 100644
--- a/nixpkgs/nixos/modules/system/boot/luksroot.nix
+++ b/nixpkgs/nixos/modules/system/boot/luksroot.nix
@@ -140,7 +140,7 @@ let
umount /crypt-ramfs 2>/dev/null
'';
- openCommand = name': { name, device, header, keyFile, keyFileSize, keyFileOffset, allowDiscards, yubikey, gpgCard, fido2, fallbackToPassword, ... }: assert name' == name;
+ openCommand = name': { name, device, header, keyFile, keyFileSize, keyFileOffset, allowDiscards, yubikey, gpgCard, fido2, fallbackToPassword, preOpenCommands, postOpenCommands,... }: assert name' == name;
let
csopen = "cryptsetup luksOpen ${device} ${name} ${optionalString allowDiscards "--allow-discards"} ${optionalString (header != null) "--header=${header}"}";
cschange = "cryptsetup luksChangeKey ${device} ${optionalString (header != null) "--header=${header}"}";
@@ -412,11 +412,17 @@ let
}
''}
+ # commands to run right before we mount our device
+ ${preOpenCommands}
+
${if (luks.yubikeySupport && (yubikey != null)) || (luks.gpgSupport && (gpgCard != null)) || (luks.fido2Support && (fido2.credential != null)) then ''
open_with_hardware
'' else ''
open_normally
''}
+
+ # commands to run right after we mounted our device
+ ${postOpenCommands}
'';
askPass = pkgs.writeScriptBin "cryptsetup-askpass" ''
@@ -467,8 +473,6 @@ in
[ "aes" "aes_generic" "blowfish" "twofish"
"serpent" "cbc" "xts" "lrw" "sha1" "sha256" "sha512"
"af_alg" "algif_skcipher"
-
- (if pkgs.stdenv.hostPlatform.system == "x86_64-linux" then "aes_x86_64" else "aes_i586")
];
description = ''
A list of cryptographic kernel modules needed to decrypt the root device(s).
@@ -735,6 +739,30 @@ in
};
});
};
+
+ preOpenCommands = mkOption {
+ type = types.lines;
+ default = "";
+ example = ''
+ mkdir -p /tmp/persistent
+ mount -t zfs rpool/safe/persistent /tmp/persistent
+ '';
+ description = ''
+ Commands that should be run right before we try to mount our LUKS device.
+ This can be useful, if the keys needed to open the drive is on another partion.
+ '';
+ };
+
+ postOpenCommands = mkOption {
+ type = types.lines;
+ default = "";
+ example = ''
+ umount /tmp/persistent
+ '';
+ description = ''
+ Commands that should be run right after we have mounted our LUKS device.
+ '';
+ };
};
}));
};
diff --git a/nixpkgs/nixos/modules/system/boot/modprobe.nix b/nixpkgs/nixos/modules/system/boot/modprobe.nix
index dee0ab470c9..c75f32c4d99 100644
--- a/nixpkgs/nixos/modules/system/boot/modprobe.nix
+++ b/nixpkgs/nixos/modules/system/boot/modprobe.nix
@@ -28,7 +28,7 @@ with lib;
Any additional configuration to be appended to the generated
<filename>modprobe.conf</filename>. This is typically used to
specify module options. See
- <citerefentry><refentrytitle>modprobe.conf</refentrytitle>
+ <citerefentry><refentrytitle>modprobe.d</refentrytitle>
<manvolnum>5</manvolnum></citerefentry> for details.
'';
type = types.lines;
diff --git a/nixpkgs/nixos/modules/system/boot/networkd.nix b/nixpkgs/nixos/modules/system/boot/networkd.nix
index 9b34b12e73a..721080949e0 100644
--- a/nixpkgs/nixos/modules/system/boot/networkd.nix
+++ b/nixpkgs/nixos/modules/system/boot/networkd.nix
@@ -302,7 +302,7 @@ let
checkDhcpV6 = checkUnitConfig "DHCPv6" [
(assertOnlyFields [
- "UseDns" "UseNTP" "RapidCommit" "ForceDHCPv6PDOtherInformation"
+ "UseDNS" "UseNTP" "RapidCommit" "ForceDHCPv6PDOtherInformation"
"PrefixDelegationHint"
])
(assertValueOneOf "UseDNS" boolValues)
@@ -488,7 +488,7 @@ let
vlanConfig = mkOption {
default = {};
- example = { Id = "4"; };
+ example = { Id = 4; };
type = types.addCheck (types.attrsOf unitOption) checkVlan;
description = ''
Each attribute in this set specifies an option in the
@@ -1178,14 +1178,22 @@ in
users.users.systemd-network.group = "systemd-network";
systemd.additionalUpstreamSystemUnits = [
- "systemd-networkd.service" "systemd-networkd-wait-online.service"
+ "systemd-networkd-wait-online.service"
+ "systemd-networkd.service"
+ "systemd-networkd.socket"
];
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-networkd is socket-activated by kernel netlink route change
+ # messages. It is important to have systemd buffer those on behalf of
+ # networkd.
+ systemd.sockets.systemd-networkd.wantedBy = [ "sockets.target" ];
+
systemd.services.systemd-networkd = {
wantedBy = [ "multi-user.target" ];
+ aliases = [ "dbus-org.freedesktop.network1.service" ];
restartTriggers = map (x: x.source) (attrValues unitFiles);
# prevent race condition with interface renaming (#39069)
requires = [ "systemd-udev-settle.service" ];
diff --git a/nixpkgs/nixos/modules/system/boot/plymouth.nix b/nixpkgs/nixos/modules/system/boot/plymouth.nix
index 23fce22366d..55e5b07ed61 100644
--- a/nixpkgs/nixos/modules/system/boot/plymouth.nix
+++ b/nixpkgs/nixos/modules/system/boot/plymouth.nix
@@ -102,6 +102,8 @@ in
systemd.services.plymouth-poweroff.wantedBy = [ "poweroff.target" ];
systemd.services.plymouth-reboot.wantedBy = [ "reboot.target" ];
systemd.services.plymouth-read-write.wantedBy = [ "sysinit.target" ];
+ systemd.services.systemd-ask-password-plymouth.wantedBy = ["multi-user.target"];
+ systemd.paths.systemd-ask-password-plymouth.wantedBy = ["multi-user.target"];
boot.initrd.extraUtilsCommands = ''
copy_bin_and_libs ${pkgs.plymouth}/bin/plymouthd
@@ -146,6 +148,7 @@ in
# We use `mkAfter` to ensure that LUKS password prompt would be shown earlier than the splash screen.
boot.initrd.preLVMCommands = mkAfter ''
mkdir -p /etc/plymouth
+ mkdir -p /run/plymouth
ln -s ${configFile} /etc/plymouth/plymouthd.conf
ln -s $extraUtils/share/plymouth/plymouthd.defaults /etc/plymouth/plymouthd.defaults
ln -s $extraUtils/share/plymouth/logo.png /etc/plymouth/logo.png
diff --git a/nixpkgs/nixos/modules/system/boot/resolved.nix b/nixpkgs/nixos/modules/system/boot/resolved.nix
index b7aaef575ac..b024f9cf5ee 100644
--- a/nixpkgs/nixos/modules/system/boot/resolved.nix
+++ b/nixpkgs/nixos/modules/system/boot/resolved.nix
@@ -148,6 +148,7 @@ in
systemd.services.systemd-resolved = {
wantedBy = [ "multi-user.target" ];
+ aliases = [ "dbus-org.freedesktop.resolve1.service" ];
restartTriggers = [ config.environment.etc."systemd/resolved.conf".source ];
};
diff --git a/nixpkgs/nixos/modules/system/boot/stage-1-init.sh b/nixpkgs/nixos/modules/system/boot/stage-1-init.sh
index 607aec87f01..54e3a691b2f 100644
--- a/nixpkgs/nixos/modules/system/boot/stage-1-init.sh
+++ b/nixpkgs/nixos/modules/system/boot/stage-1-init.sh
@@ -144,6 +144,14 @@ for o in $(cat /proc/cmdline); do
set -- $(IFS==; echo $o)
stage2Init=$2
;;
+ boot.persistence=*)
+ set -- $(IFS==; echo $o)
+ persistence=$2
+ ;;
+ boot.persistence.opt=*)
+ set -- $(IFS==; echo $o)
+ persistence_opt=$2
+ ;;
boot.trace|debugtrace)
# Show each command.
set -x
@@ -534,6 +542,14 @@ while read -u 3 mountPoint; do
continue
fi
+ if [ "$mountPoint" = / ] && [ "$device" = tmpfs ] && [ ! -z "$persistence" ]; then
+ echo persistence...
+ waitDevice "$persistence"
+ echo enabling persistence...
+ mountFS "$persistence" "$mountPoint" "$persistence_opt" "auto"
+ continue
+ fi
+
mountFS "$device" "$mountPoint" "$options" "$fsType"
done
diff --git a/nixpkgs/nixos/modules/system/boot/stage-1.nix b/nixpkgs/nixos/modules/system/boot/stage-1.nix
index 9bf3228d1ad..7f13f67e8ef 100644
--- a/nixpkgs/nixos/modules/system/boot/stage-1.nix
+++ b/nixpkgs/nixos/modules/system/boot/stage-1.nix
@@ -111,8 +111,8 @@ let
copy_bin_and_libs ${pkgs.utillinux}/sbin/blkid
# Copy dmsetup and lvm.
- copy_bin_and_libs ${pkgs.lvm2}/sbin/dmsetup
- copy_bin_and_libs ${pkgs.lvm2}/sbin/lvm
+ copy_bin_and_libs ${getBin pkgs.lvm2}/bin/dmsetup
+ copy_bin_and_libs ${getBin pkgs.lvm2}/bin/lvm
# Add RAID mdadm tool.
copy_bin_and_libs ${pkgs.mdadm}/sbin/mdadm
@@ -235,7 +235,7 @@ let
--replace cdrom_id ${extraUtils}/bin/cdrom_id \
--replace ${pkgs.coreutils}/bin/basename ${extraUtils}/bin/basename \
--replace ${pkgs.utillinux}/bin/blkid ${extraUtils}/bin/blkid \
- --replace ${pkgs.lvm2}/sbin ${extraUtils}/bin \
+ --replace ${getBin pkgs.lvm2}/bin ${extraUtils}/bin \
--replace ${pkgs.mdadm}/sbin ${extraUtils}/sbin \
--replace ${pkgs.bash}/bin/sh ${extraUtils}/bin/sh \
--replace ${udev} ${extraUtils}
@@ -559,10 +559,12 @@ in
default = false;
type = types.bool;
description = ''
- If set, this file system will be mounted in the initial
- ramdisk. By default, this applies to the root file system
- and to the file system containing
- <filename>/nix/store</filename>.
+ If set, this file system will be mounted in the initial ramdisk.
+ Note that the file system will always be mounted in the initial
+ ramdisk if its mount point is one of the following:
+ ${concatStringsSep ", " (
+ forEach utils.pathsNeededForBoot (i: "<filename>${i}</filename>")
+ )}.
'';
};
});
@@ -584,7 +586,7 @@ in
{ assertion = !config.boot.loader.supportsInitrdSecrets ->
all (source:
builtins.isPath source ||
- (builtins.isString source && hasPrefix source builtins.storeDir))
+ (builtins.isString source && hasPrefix builtins.storeDir source))
(attrValues config.boot.initrd.secrets);
message = ''
boot.loader.initrd.secrets values must be unquoted paths when
diff --git a/nixpkgs/nixos/modules/system/boot/stage-2-init.sh b/nixpkgs/nixos/modules/system/boot/stage-2-init.sh
index d1de7920df9..936077b9df1 100644
--- a/nixpkgs/nixos/modules/system/boot/stage-2-init.sh
+++ b/nixpkgs/nixos/modules/system/boot/stage-2-init.sh
@@ -169,4 +169,4 @@ exec {logOutFd}>&- {logErrFd}>&-
echo "starting systemd..."
PATH=/run/current-system/systemd/lib/systemd:@fsPackagesPath@ \
LOCALE_ARCHIVE=/run/current-system/sw/lib/locale/locale-archive \
- exec systemd
+ exec @systemdExecutable@
diff --git a/nixpkgs/nixos/modules/system/boot/stage-2.nix b/nixpkgs/nixos/modules/system/boot/stage-2.nix
index 6b0b4722730..dd6d83ee009 100644
--- a/nixpkgs/nixos/modules/system/boot/stage-2.nix
+++ b/nixpkgs/nixos/modules/system/boot/stage-2.nix
@@ -10,6 +10,7 @@ let
src = ./stage-2-init.sh;
shellDebug = "${pkgs.bashInteractive}/bin/bash";
shell = "${pkgs.bash}/bin/bash";
+ inherit (config.boot) systemdExecutable;
isExecutable = true;
inherit (config.nix) readOnlyStore;
inherit useHostResolvConf;
@@ -72,6 +73,15 @@ in
'';
};
+ systemdExecutable = mkOption {
+ default = "systemd";
+ type = types.str;
+ description = ''
+ The program to execute to start systemd. Typically
+ <literal>systemd</literal>, which will find systemd in the
+ PATH.
+ '';
+ };
};
};
diff --git a/nixpkgs/nixos/modules/system/boot/systemd-unit-options.nix b/nixpkgs/nixos/modules/system/boot/systemd-unit-options.nix
index bee21f1a8f3..c6dbb96951a 100644
--- a/nixpkgs/nixos/modules/system/boot/systemd-unit-options.nix
+++ b/nixpkgs/nixos/modules/system/boot/systemd-unit-options.nix
@@ -233,6 +233,7 @@ in rec {
path = mkOption {
default = [];
+ type = with types; listOf (oneOf [ package str ]);
apply = ps: "${makeBinPath ps}:${makeSearchPathOutput "bin" "sbin" ps}";
description = ''
Packages added to the service's <envar>PATH</envar>
diff --git a/nixpkgs/nixos/modules/system/boot/systemd.nix b/nixpkgs/nixos/modules/system/boot/systemd.nix
index 99892a28115..86bd81d781a 100644
--- a/nixpkgs/nixos/modules/system/boot/systemd.nix
+++ b/nixpkgs/nixos/modules/system/boot/systemd.nix
@@ -749,6 +749,25 @@ in
'';
};
+ systemd.tmpfiles.packages = mkOption {
+ type = types.listOf types.package;
+ default = [];
+ example = literalExample "[ pkgs.lvm2 ]";
+ apply = map getLib;
+ description = ''
+ List of packages containing <command>systemd-tmpfiles</command> rules.
+
+ All files ending in .conf found in
+ <filename><replaceable>pkg</replaceable>/lib/tmpfiles.d</filename>
+ will be included.
+ If this folder does not exist or does not contain any files an error will be returned instead.
+
+ If a <filename>lib</filename> output is available, rules are searched there and only there.
+ If there is no <filename>lib</filename> output it will fall back to <filename>out</filename>
+ and if that does not exist either, the default output will be used.
+ '';
+ };
+
systemd.user.units = mkOption {
description = "Definition of systemd per-user units.";
default = {};
@@ -818,6 +837,49 @@ in
'';
};
+ systemd.watchdog.device = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ example = "/dev/watchdog";
+ description = ''
+ The path to a hardware watchdog device which will be managed by systemd.
+ If not specified, systemd will default to /dev/watchdog.
+ '';
+ };
+
+ systemd.watchdog.runtimeTime = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "30s";
+ description = ''
+ The amount of time which can elapse before a watchdog hardware device
+ will automatically reboot the system. Valid time units include "ms",
+ "s", "min", "h", "d", and "w".
+ '';
+ };
+
+ systemd.watchdog.rebootTime = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "10m";
+ description = ''
+ The amount of time which can elapse after a reboot has been triggered
+ before a watchdog hardware device will automatically reboot the system.
+ Valid time units include "ms", "s", "min", "h", "d", and "w".
+ '';
+ };
+
+ systemd.watchdog.kexecTime = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "10m";
+ description = ''
+ The amount of time which can elapse when kexec is being executed before
+ a watchdog hardware device will automatically reboot the system. This
+ option should only be enabled if reloadTime is also enabled. Valid
+ time units include "ms", "s", "min", "h", "d", and "w".
+ '';
+ };
};
@@ -826,8 +888,13 @@ in
config = {
warnings = concatLists (mapAttrsToList (name: service:
- optional (service.serviceConfig.Type or "" == "oneshot" && service.serviceConfig.Restart or "no" != "no")
- "Service ‘${name}.service’ with ‘Type=oneshot’ must have ‘Restart=no’") cfg.services);
+ let
+ type = service.serviceConfig.Type or "";
+ restart = service.serviceConfig.Restart or "no";
+ in optional
+ (type == "oneshot" && (restart == "always" || restart == "on-success"))
+ "Service '${name}.service' with 'Type=oneshot' cannot have 'Restart=always' or 'Restart=on-success'")
+ cfg.services);
system.build.units = cfg.units;
@@ -884,6 +951,19 @@ in
DefaultIPAccounting=yes
''}
DefaultLimitCORE=infinity
+ ${optionalString (config.systemd.watchdog.device != null) ''
+ WatchdogDevice=${config.systemd.watchdog.device}
+ ''}
+ ${optionalString (config.systemd.watchdog.runtimeTime != null) ''
+ RuntimeWatchdogSec=${config.systemd.watchdog.runtimeTime}
+ ''}
+ ${optionalString (config.systemd.watchdog.rebootTime != null) ''
+ RebootWatchdogSec=${config.systemd.watchdog.rebootTime}
+ ''}
+ ${optionalString (config.systemd.watchdog.kexecTime != null) ''
+ KExecWatchdogSec=${config.systemd.watchdog.kexecTime}
+ ''}
+
${config.systemd.extraConfig}
'';
@@ -931,24 +1011,18 @@ in
"sysctl.d/50-coredump.conf".source = "${systemd}/example/sysctl.d/50-coredump.conf";
"sysctl.d/50-default.conf".source = "${systemd}/example/sysctl.d/50-default.conf";
- "tmpfiles.d/00-nixos.conf".text = ''
- # This file is created automatically and should not be modified.
- # Please change the option ‘systemd.tmpfiles.rules’ instead.
-
- ${concatStringsSep "\n" cfg.tmpfiles.rules}
- '';
-
- "tmpfiles.d/home.conf".source = "${systemd}/example/tmpfiles.d/home.conf";
- "tmpfiles.d/journal-nocow.conf".source = "${systemd}/example/tmpfiles.d/journal-nocow.conf";
- "tmpfiles.d/portables.conf".source = "${systemd}/example/tmpfiles.d/portables.conf";
- "tmpfiles.d/static-nodes-permissions.conf".source = "${systemd}/example/tmpfiles.d/static-nodes-permissions.conf";
- "tmpfiles.d/systemd.conf".source = "${systemd}/example/tmpfiles.d/systemd.conf";
- "tmpfiles.d/systemd-nologin.conf".source = "${systemd}/example/tmpfiles.d/systemd-nologin.conf";
- "tmpfiles.d/systemd-nspawn.conf".source = "${systemd}/example/tmpfiles.d/systemd-nspawn.conf";
- "tmpfiles.d/systemd-tmp.conf".source = "${systemd}/example/tmpfiles.d/systemd-tmp.conf";
- "tmpfiles.d/tmp.conf".source = "${systemd}/example/tmpfiles.d/tmp.conf";
- "tmpfiles.d/var.conf".source = "${systemd}/example/tmpfiles.d/var.conf";
- "tmpfiles.d/x11.conf".source = "${systemd}/example/tmpfiles.d/x11.conf";
+ "tmpfiles.d".source = (pkgs.symlinkJoin {
+ name = "tmpfiles.d";
+ paths = cfg.tmpfiles.packages;
+ postBuild = ''
+ for i in $(cat $pathsPath); do
+ (test -d $i/lib/tmpfiles.d && test $(ls $i/lib/tmpfiles.d/*.conf | wc -l) -ge 1) || (
+ echo "ERROR: The path $i was passed to systemd.tmpfiles.packages but either does not contain the folder lib/tmpfiles.d or if it contains that folder, there are no files ending in .conf in it."
+ exit 1
+ )
+ done
+ '';
+ }) + "/lib/tmpfiles.d";
"systemd/system-generators" = { source = hooks "generators" cfg.generators; };
"systemd/system-shutdown" = { source = hooks "shutdown" cfg.shutdown; };
@@ -969,6 +1043,36 @@ in
unitConfig.X-StopOnReconfiguration = true;
};
+ systemd.tmpfiles.packages = [
+ # Default tmpfiles rules provided by systemd
+ (pkgs.runCommand "systemd-default-tmpfiles" {} ''
+ mkdir -p $out/lib/tmpfiles.d
+ cd $out/lib/tmpfiles.d
+
+ ln -s "${systemd}/example/tmpfiles.d/home.conf"
+ ln -s "${systemd}/example/tmpfiles.d/journal-nocow.conf"
+ ln -s "${systemd}/example/tmpfiles.d/static-nodes-permissions.conf"
+ ln -s "${systemd}/example/tmpfiles.d/systemd.conf"
+ ln -s "${systemd}/example/tmpfiles.d/systemd-nologin.conf"
+ ln -s "${systemd}/example/tmpfiles.d/systemd-nspawn.conf"
+ ln -s "${systemd}/example/tmpfiles.d/systemd-tmp.conf"
+ ln -s "${systemd}/example/tmpfiles.d/tmp.conf"
+ ln -s "${systemd}/example/tmpfiles.d/var.conf"
+ ln -s "${systemd}/example/tmpfiles.d/x11.conf"
+ '')
+ # User-specified tmpfiles rules
+ (pkgs.writeTextFile {
+ name = "nixos-tmpfiles.d";
+ destination = "/lib/tmpfiles.d/00-nixos.conf";
+ text = ''
+ # This file is created automatically and should not be modified.
+ # Please change the option ‘systemd.tmpfiles.rules’ instead.
+
+ ${concatStringsSep "\n" cfg.tmpfiles.rules}
+ '';
+ })
+ ];
+
systemd.units =
mapAttrs' (n: v: nameValuePair "${n}.path" (pathToUnit n v)) cfg.paths
// mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit n v)) cfg.services
diff --git a/nixpkgs/nixos/modules/system/boot/timesyncd.nix b/nixpkgs/nixos/modules/system/boot/timesyncd.nix
index 9e2f36ca01f..35fb5578b07 100644
--- a/nixpkgs/nixos/modules/system/boot/timesyncd.nix
+++ b/nixpkgs/nixos/modules/system/boot/timesyncd.nix
@@ -41,6 +41,7 @@ with lib;
systemd.services.systemd-timesyncd = {
wantedBy = [ "sysinit.target" ];
+ aliases = [ "dbus-org.freedesktop.timesync1.service" ];
restartTriggers = [ config.environment.etc."systemd/timesyncd.conf".source ];
};
diff --git a/nixpkgs/nixos/modules/tasks/encrypted-devices.nix b/nixpkgs/nixos/modules/tasks/encrypted-devices.nix
index bc0933f16fe..9c3f2d8fccb 100644
--- a/nixpkgs/nixos/modules/tasks/encrypted-devices.nix
+++ b/nixpkgs/nixos/modules/tasks/encrypted-devices.nix
@@ -37,7 +37,14 @@ let
default = null;
example = "/mnt-root/root/.swapkey";
type = types.nullOr types.str;
- description = "File system location of keyfile. This unlocks the drive after the root has been mounted to <literal>/mnt-root</literal>.";
+ description = ''
+ Path to a keyfile used to unlock the backing encrypted
+ device. At the time this keyfile is accessed, the
+ <literal>neededForBoot</literal> filesystems (see
+ <literal>fileSystems.&lt;name?&gt;.neededForBoot</literal>)
+ will have been mounted under <literal>/mnt-root</literal>,
+ so the keyfile path should usually start with "/mnt-root/".
+ '';
};
};
};
@@ -65,12 +72,16 @@ in
boot.initrd = {
luks = {
devices =
- builtins.listToAttrs (map (dev: { name = dev.encrypted.label; value = { device = dev.encrypted.blkDev; }; }) keylessEncDevs);
+ builtins.listToAttrs (map (dev: {
+ name = dev.encrypted.label;
+ value = { device = dev.encrypted.blkDev; };
+ }) keylessEncDevs);
forceLuksSupportInInitrd = true;
};
postMountCommands =
- concatMapStrings (dev: "cryptsetup luksOpen --key-file ${dev.encrypted.keyFile} ${dev.encrypted.blkDev} ${dev.encrypted.label};\n") keyedEncDevs;
+ concatMapStrings (dev:
+ "cryptsetup luksOpen --key-file ${dev.encrypted.keyFile} ${dev.encrypted.blkDev} ${dev.encrypted.label};\n"
+ ) keyedEncDevs;
};
};
}
-
diff --git a/nixpkgs/nixos/modules/tasks/filesystems/btrfs.nix b/nixpkgs/nixos/modules/tasks/filesystems/btrfs.nix
index f64493e1a3c..c0ff28039b1 100644
--- a/nixpkgs/nixos/modules/tasks/filesystems/btrfs.nix
+++ b/nixpkgs/nixos/modules/tasks/filesystems/btrfs.nix
@@ -128,7 +128,10 @@ in
Nice = 19;
IOSchedulingClass = "idle";
ExecStart = "${pkgs.btrfs-progs}/bin/btrfs scrub start -B ${fs}";
- ExecStop = "${pkgs.btrfs-progs}/bin/btrfs scrub cancel ${fs}";
+ # if the service is stopped before scrub end, cancel it
+ ExecStop = pkgs.writeShellScript "btrfs-scrub-maybe-cancel" ''
+ (${pkgs.btrfs-progs}/bin/btrfs scrub status ${fs} | ${pkgs.gnugrep}/bin/grep finished) || ${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 71eed4d6f1a..c9d9c6c1657 100644
--- a/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix
+++ b/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix
@@ -197,9 +197,7 @@ in
Request encryption keys or passwords for all encrypted datasets on import.
For root pools the encryption key can be supplied via both an
interactive prompt (keylocation=prompt) and from a file
- (keylocation=file://). Note that for data pools the encryption key can
- be only loaded from a file and not via interactive prompt since the
- import is processed in a background systemd service.
+ (keylocation=file://).
'';
};
@@ -490,7 +488,11 @@ in
description = "Import ZFS pool \"${pool}\"";
# we need systemd-udev-settle until https://github.com/zfsonlinux/zfs/pull/4943 is merged
requires = [ "systemd-udev-settle.service" ];
- after = [ "systemd-udev-settle.service" "systemd-modules-load.service" ];
+ after = [
+ "systemd-udev-settle.service"
+ "systemd-modules-load.service"
+ "systemd-ask-password-console.service"
+ ];
wantedBy = (getPoolMounts pool) ++ [ "local-fs.target" ];
before = (getPoolMounts pool) ++ [ "local-fs.target" ];
unitConfig = {
@@ -515,7 +517,20 @@ in
done
poolImported "${pool}" || poolImport "${pool}" # Try one last time, e.g. to import a degraded pool.
if poolImported "${pool}"; then
- ${optionalString cfgZfs.requestEncryptionCredentials "\"${packages.zfsUser}/sbin/zfs\" load-key -r \"${pool}\""}
+ ${optionalString cfgZfs.requestEncryptionCredentials ''
+ ${packages.zfsUser}/sbin/zfs list -rHo name,keylocation ${pool} | while IFS=$'\t' read ds kl; do
+ (case "$kl" in
+ none )
+ ;;
+ prompt )
+ ${config.systemd.package}/bin/systemd-ask-password "Enter key for $ds:" | ${packages.zfsUser}/sbin/zfs load-key "$ds"
+ ;;
+ * )
+ ${packages.zfsUser}/sbin/zfs load-key "$ds"
+ ;;
+ esac) < /dev/null # To protect while read ds kl in case anything reads stdin
+ done
+ ''}
echo "Successfully imported ${pool}"
else
exit 1
diff --git a/nixpkgs/nixos/modules/tasks/lvm.nix b/nixpkgs/nixos/modules/tasks/lvm.nix
index d56a8a2f63a..2c3cc4c5467 100644
--- a/nixpkgs/nixos/modules/tasks/lvm.nix
+++ b/nixpkgs/nixos/modules/tasks/lvm.nix
@@ -1,17 +1,70 @@
{ config, lib, pkgs, ... }:
with lib;
+let
+ cfg = config.services.lvm;
+in {
+ options.services.lvm = {
+ package = mkOption {
+ type = types.package;
+ default = if cfg.dmeventd.enable then pkgs.lvm2_dmeventd else pkgs.lvm2;
+ internal = true;
+ defaultText = "pkgs.lvm2";
+ description = ''
+ This option allows you to override the LVM package that's used on the system
+ (udev rules, tmpfiles, systemd services).
+ Defaults to pkgs.lvm2, or pkgs.lvm2_dmeventd if dmeventd is enabled.
+ '';
+ };
+ dmeventd.enable = mkEnableOption "the LVM dmevent daemon";
+ boot.thin.enable = mkEnableOption "support for booting from ThinLVs";
+ };
-{
-
- ###### implementation
+ config = mkMerge [
+ (mkIf (!config.boot.isContainer) {
+ systemd.tmpfiles.packages = [ cfg.package.out ];
+ environment.systemPackages = [ cfg.package ];
+ systemd.packages = [ cfg.package ];
- config = mkIf (!config.boot.isContainer) {
+ # TODO: update once https://github.com/NixOS/nixpkgs/pull/93006 was merged
+ services.udev.packages = [ cfg.package.out ];
+ })
+ (mkIf cfg.dmeventd.enable {
+ systemd.sockets."dm-event".wantedBy = [ "sockets.target" ];
+ systemd.services."lvm2-monitor".wantedBy = [ "sysinit.target" ];
- environment.systemPackages = [ pkgs.lvm2 ];
+ environment.etc."lvm/lvm.conf".text = ''
+ dmeventd/executable = "${cfg.package}/bin/dmeventd"
+ '';
+ })
+ (mkIf cfg.boot.thin.enable {
+ boot.initrd = {
+ kernelModules = [ "dm-snapshot" "dm-thin-pool" ];
- services.udev.packages = [ pkgs.lvm2 ];
+ extraUtilsCommands = ''
+ copy_bin_and_libs ${pkgs.thin-provisioning-tools}/bin/pdata_tools
+ copy_bin_and_libs ${pkgs.thin-provisioning-tools}/bin/thin_check
+ '';
+ };
- };
+ environment.etc."lvm/lvm.conf".text = ''
+ global/thin_check_executable = "${pkgs.thin-provisioning-tools}/bin/thin_check"
+ '';
+ })
+ (mkIf (cfg.dmeventd.enable || cfg.boot.thin.enable) {
+ boot.initrd.preLVMCommands = ''
+ mkdir -p /etc/lvm
+ cat << EOF >> /etc/lvm/lvm.conf
+ ${optionalString cfg.boot.thin.enable ''
+ global/thin_check_executable = "$(command -v thin_check)"
+ ''}
+ ${optionalString cfg.dmeventd.enable ''
+ dmeventd/executable = "$(command -v false)"
+ activation/monitoring = 0
+ ''}
+ EOF
+ '';
+ })
+ ];
}
diff --git a/nixpkgs/nixos/modules/tasks/network-interfaces-scripted.nix b/nixpkgs/nixos/modules/tasks/network-interfaces-scripted.nix
index d895c58bab0..2e87197176b 100644
--- a/nixpkgs/nixos/modules/tasks/network-interfaces-scripted.nix
+++ b/nixpkgs/nixos/modules/tasks/network-interfaces-scripted.nix
@@ -232,18 +232,22 @@ let
'';
preStop = ''
state="/run/nixos/network/routes/${i.name}"
- while read cidr; do
- echo -n "deleting route $cidr... "
- ip route del "$cidr" dev "${i.name}" >/dev/null 2>&1 && echo "done" || echo "failed"
- done < "$state"
- rm -f "$state"
+ if [ -e "$state" ]; then
+ while read cidr; do
+ echo -n "deleting route $cidr... "
+ ip route del "$cidr" dev "${i.name}" >/dev/null 2>&1 && echo "done" || echo "failed"
+ done < "$state"
+ rm -f "$state"
+ fi
state="/run/nixos/network/addresses/${i.name}"
- while read cidr; do
- echo -n "deleting address $cidr... "
- ip addr del "$cidr" dev "${i.name}" >/dev/null 2>&1 && echo "done" || echo "failed"
- done < "$state"
- rm -f "$state"
+ if [ -e "$state" ]; then
+ while read cidr; do
+ echo -n "deleting address $cidr... "
+ ip addr del "$cidr" dev "${i.name}" >/dev/null 2>&1 && echo "done" || echo "failed"
+ done < "$state"
+ rm -f "$state"
+ fi
'';
};
diff --git a/nixpkgs/nixos/modules/virtualisation/containers.nix b/nixpkgs/nixos/modules/virtualisation/containers.nix
index 7d184575640..3a6767d84a9 100644
--- a/nixpkgs/nixos/modules/virtualisation/containers.nix
+++ b/nixpkgs/nixos/modules/virtualisation/containers.nix
@@ -23,6 +23,15 @@ in
maintainers = [] ++ lib.teams.podman.members;
};
+
+ imports = [
+ (
+ lib.mkRemovedOptionModule
+ [ "virtualisation" "containers" "users" ]
+ "All users with `isNormalUser = true` set now get appropriate subuid/subgid mappings."
+ )
+ ];
+
options.virtualisation.containers = {
enable =
@@ -34,6 +43,25 @@ in
'';
};
+ containersConf = mkOption {
+ default = {};
+ description = "containers.conf configuration";
+ type = types.submodule {
+ options = {
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Extra configuration that should be put in the containers.conf
+ configuration file
+ '';
+
+ };
+ };
+ };
+ };
+
registries = {
search = mkOption {
type = types.listOf types.str;
@@ -80,43 +108,20 @@ in
'';
};
- users = mkOption {
- default = [];
- type = types.listOf types.str;
- description = ''
- List of users to set up subuid/subgid mappings for.
- This is a requirement for running rootless containers.
- '';
- };
-
};
config = lib.mkIf cfg.enable {
+ environment.etc."containers/containers.conf".text = ''
+ [network]
+ cni_plugin_dirs = ["${pkgs.cni-plugins}/bin/"]
+
+ '' + cfg.containersConf.extraConfig;
+
environment.etc."containers/registries.conf".source = toTOML "registries.conf" {
registries = lib.mapAttrs (n: v: { registries = v; }) cfg.registries;
};
- users.extraUsers = builtins.listToAttrs (
- (
- builtins.foldl' (
- acc: user: {
- values = acc.values ++ [
- {
- name = user;
- value = {
- subUidRanges = [ { startUid = acc.offset; count = 65536; } ];
- subGidRanges = [ { startGid = acc.offset; count = 65536; } ];
- };
- }
- ];
- offset = acc.offset + 65536;
- }
- )
- { values = []; offset = 100000; } (lib.unique cfg.users)
- ).values
- );
-
environment.etc."containers/policy.json".source =
if cfg.policy != {} then pkgs.writeText "policy.json" (builtins.toJSON cfg.policy)
else copyFile "${pkgs.skopeo.src}/default-policy.json";
diff --git a/nixpkgs/nixos/modules/virtualisation/docker.nix b/nixpkgs/nixos/modules/virtualisation/docker.nix
index 7d196a46276..d87ada35a0a 100644
--- a/nixpkgs/nixos/modules/virtualisation/docker.nix
+++ b/nixpkgs/nixos/modules/virtualisation/docker.nix
@@ -149,6 +149,7 @@ in
###### implementation
config = mkIf cfg.enable (mkMerge [{
+ boot.kernelModules = [ "bridge" "veth" ];
environment.systemPackages = [ cfg.package ]
++ optional cfg.enableNvidia pkgs.nvidia-docker;
users.groups.docker.gid = config.ids.gids.docker;
diff --git a/nixpkgs/nixos/modules/virtualisation/libvirtd.nix b/nixpkgs/nixos/modules/virtualisation/libvirtd.nix
index 43b5fcfa8fa..1d6a9457dde 100644
--- a/nixpkgs/nixos/modules/virtualisation/libvirtd.nix
+++ b/nixpkgs/nixos/modules/virtualisation/libvirtd.nix
@@ -265,8 +265,8 @@ in {
restartIfChanged = false;
};
- systemd.sockets.libvirtd .wantedBy = [ "sockets.target" ];
- systemd.sockets.libvirtd-tcp.wantedBy = [ "sockets.target" ];
+ # https://libvirt.org/daemons.html#monolithic-systemd-integration
+ systemd.sockets.libvirtd.wantedBy = [ "sockets.target" ];
security.polkit.extraConfig = ''
polkit.addRule(function(action, subject) {
diff --git a/nixpkgs/nixos/modules/virtualisation/lxd.nix b/nixpkgs/nixos/modules/virtualisation/lxd.nix
index 53b89a9f55b..3958fc2c1d7 100644
--- a/nixpkgs/nixos/modules/virtualisation/lxd.nix
+++ b/nixpkgs/nixos/modules/virtualisation/lxd.nix
@@ -15,7 +15,6 @@ in
###### interface
options = {
-
virtualisation.lxd = {
enable = mkOption {
type = types.bool;
@@ -25,12 +24,18 @@ in
containers. Users in the "lxd" group can interact with
the daemon (e.g. to start or stop containers) using the
<command>lxc</command> command line tool, among others.
+
+ Most of the time, you'll also want to start lxcfs, so
+ that containers can "see" the limits:
+ <code>
+ virtualisation.lxc.lxcfs.enable = true;
+ </code>
'';
};
package = mkOption {
type = types.package;
- default = pkgs.lxd;
+ default = pkgs.lxd.override { nftablesSupport = config.networking.nftables.enable; };
defaultText = "pkgs.lxd";
description = ''
The LXD package to use.
@@ -65,6 +70,7 @@ in
with nixos.
'';
};
+
recommendedSysctlSettings = mkOption {
type = types.bool;
default = false;
@@ -83,7 +89,6 @@ in
###### implementation
config = mkIf cfg.enable {
-
environment.systemPackages = [ cfg.package ];
security.apparmor = {
@@ -115,6 +120,12 @@ in
LimitNOFILE = "1048576";
LimitNPROC = "infinity";
TasksMax = "infinity";
+
+ # By default, `lxd` loads configuration files from hard-coded
+ # `/usr/share/lxc/config` - since this is a no-go for us, we have to
+ # explicitly tell it where the actual configuration files are
+ Environment = mkIf (config.virtualisation.lxc.lxcfs.enable)
+ "LXD_LXC_TEMPLATE_CONFIG=${pkgs.lxcfs}/share/lxc/config";
};
};
diff --git a/nixpkgs/nixos/modules/virtualisation/podman.nix b/nixpkgs/nixos/modules/virtualisation/podman.nix
index 652850bf500..e0e2f04e24c 100644
--- a/nixpkgs/nixos/modules/virtualisation/podman.nix
+++ b/nixpkgs/nixos/modules/virtualisation/podman.nix
@@ -28,6 +28,10 @@ let
in
{
+ imports = [
+ (lib.mkRenamedOptionModule [ "virtualisation" "podman" "libpod" ] [ "virtualisation" "containers" "containersConf" ])
+ ];
+
meta = {
maintainers = lib.teams.podman.members;
};
@@ -67,25 +71,6 @@ in
'';
};
- libpod = mkOption {
- default = {};
- description = "Libpod configuration";
- type = types.submodule {
- options = {
-
- extraConfig = mkOption {
- type = types.lines;
- default = "";
- description = ''
- Extra configuration that should be put in the libpod.conf
- configuration file
- '';
-
- };
- };
- };
- };
-
package = lib.mkOption {
type = types.package;
default = podmanPackage;
@@ -103,11 +88,6 @@ in
environment.systemPackages = [ cfg.package ]
++ lib.optional cfg.dockerCompat dockerCompat;
- environment.etc."containers/libpod.conf".text = ''
- cni_plugin_dir = ["${pkgs.cni-plugins}/bin/"]
-
- '' + cfg.libpod.extraConfig;
-
environment.etc."cni/net.d/87-podman-bridge.conflist".source = copyFile "${pkgs.podman-unwrapped.src}/cni/87-podman-bridge.conflist";
# Enable common /etc/containers configuration
diff --git a/nixpkgs/nixos/modules/virtualisation/qemu-vm.nix b/nixpkgs/nixos/modules/virtualisation/qemu-vm.nix
index 4592ffcfe4d..a650dd72c2a 100644
--- a/nixpkgs/nixos/modules/virtualisation/qemu-vm.nix
+++ b/nixpkgs/nixos/modules/virtualisation/qemu-vm.nix
@@ -16,11 +16,6 @@ let
qemu = config.system.build.qemu or pkgs.qemu_test;
- vmName =
- if config.networking.hostName == ""
- then "noname"
- else config.networking.hostName;
-
cfg = config.virtualisation;
consoles = lib.concatMapStringsSep " " (c: "console=${c}") cfg.qemu.consoles;
@@ -46,6 +41,13 @@ let
description = "Extra options passed to device flag.";
};
+ name = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description =
+ "A name for the drive. Must be unique in the drives list. Not passed to qemu.";
+ };
+
};
};
@@ -74,6 +76,32 @@ let
drivesCmdLine = drives: concatStringsSep " " (imap1 driveCmdline drives);
+
+ # Creates a device name from a 1-based a numerical index, e.g.
+ # * `driveDeviceName 1` -> `/dev/vda`
+ # * `driveDeviceName 2` -> `/dev/vdb`
+ driveDeviceName = idx:
+ let letter = elemAt lowerChars (idx - 1);
+ in if cfg.qemu.diskInterface == "scsi" then
+ "/dev/sd${letter}"
+ else
+ "/dev/vd${letter}";
+
+ lookupDriveDeviceName = driveName: driveList:
+ (findSingle (drive: drive.name == driveName)
+ (throw "Drive ${driveName} not found")
+ (throw "Multiple drives named ${driveName}") driveList).device;
+
+ addDeviceNames =
+ imap1 (idx: drive: drive // { device = driveDeviceName idx; });
+
+ efiPrefix =
+ if (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) then "${pkgs.OVMF.fd}/FV/OVMF"
+ else if pkgs.stdenv.isAarch64 then "${pkgs.OVMF.fd}/FV/AAVMF"
+ else throw "No EFI firmware available for platform";
+ efiFirmware = "${efiPrefix}_CODE.fd";
+ efiVarsDefault = "${efiPrefix}_VARS.fd";
+
# Shell script to start the VM.
startVM =
''
@@ -99,10 +127,14 @@ let
# A writable boot disk can be booted from automatically.
${qemu}/bin/qemu-img create -f qcow2 -b ${bootDisk}/disk.img $TMPDIR/disk.img || exit 1
+ NIX_EFI_VARS=$(readlink -f ''${NIX_EFI_VARS:-${cfg.efiVars}})
+
${if cfg.useEFIBoot then ''
- # VM needs a writable flash BIOS.
- cp ${bootDisk}/bios.bin $TMPDIR || exit 1
- chmod 0644 $TMPDIR/bios.bin || exit 1
+ # VM needs writable EFI vars
+ if ! test -e "$NIX_EFI_VARS"; then
+ cp ${bootDisk}/efi-vars.fd "$NIX_EFI_VARS" || exit 1
+ chmod 0644 "$NIX_EFI_VARS" || exit 1
+ fi
'' else ''
''}
'' else ''
@@ -119,7 +151,7 @@ let
# Start QEMU.
exec ${qemuBinary qemu} \
- -name ${vmName} \
+ -name ${config.system.name} \
-m ${toString config.virtualisation.memorySize} \
-smp ${toString config.virtualisation.cores} \
-device virtio-rng-pci \
@@ -139,6 +171,8 @@ let
# Generate a hard disk image containing a /boot partition and GRUB
# in the MBR. Used when the `useBootLoader' option is set.
+ # Uses `runInLinuxVM` to create the image in a throwaway VM.
+ # See note [Disk layout with `useBootLoader`].
# FIXME: use nixos/lib/make-disk-image.nix.
bootDisk =
pkgs.vmTools.runInLinuxVM (
@@ -147,21 +181,22 @@ let
''
mkdir $out
diskImage=$out/disk.img
- bootFlash=$out/bios.bin
- ${qemu}/bin/qemu-img create -f qcow2 $diskImage "40M"
+ ${qemu}/bin/qemu-img create -f qcow2 $diskImage "60M"
${if cfg.useEFIBoot then ''
- cp ${pkgs.OVMF-CSM.fd}/FV/OVMF.fd $bootFlash
- chmod 0644 $bootFlash
+ efiVars=$out/efi-vars.fd
+ cp ${efiVarsDefault} $efiVars
+ chmod 0644 $efiVars
'' else ''
''}
'';
buildInputs = [ pkgs.utillinux ];
- QEMU_OPTS = if cfg.useEFIBoot
- then "-pflash $out/bios.bin -nographic -serial pty"
- else "-nographic -serial pty";
+ QEMU_OPTS = "-nographic -serial stdio -monitor none"
+ + lib.optionalString cfg.useEFIBoot (
+ " -drive if=pflash,format=raw,unit=0,readonly=on,file=${efiFirmware}"
+ + " -drive if=pflash,format=raw,unit=1,file=$efiVars");
}
''
- # Create a /boot EFI partition with 40M and arbitrary but fixed GUIDs for reproducibility
+ # Create a /boot EFI partition with 60M and arbitrary but fixed GUIDs for reproducibility
${pkgs.gptfdisk}/bin/sgdisk \
--set-alignment=1 --new=1:34:2047 --change-name=1:BIOSBootPartition --typecode=1:ef02 \
--set-alignment=512 --largest-new=2 --change-name=2:EFISystem --typecode=2:ef00 \
@@ -172,6 +207,19 @@ let
--partition-guid=2:970C694F-AFD0-4B99-B750-CDB7A329AB6F \
--hybrid 2 \
--recompute-chs /dev/vda
+
+ ${optionalString (config.boot.loader.grub.device != "/dev/vda")
+ # In this throwaway VM, we only have the /dev/vda disk, but the
+ # actual VM described by `config` (used by `switch-to-configuration`
+ # below) may set `boot.loader.grub.device` to a different device
+ # that's nonexistent in the throwaway VM.
+ # Create a symlink for that device, so that the `grub-install`
+ # by `switch-to-configuration` will hit /dev/vda anyway.
+ ''
+ ln -s /dev/vda ${config.boot.loader.grub.device}
+ ''
+ }
+
${pkgs.dosfstools}/bin/mkfs.fat -F16 /dev/vda2
export MTOOLS_SKIP_CHECK=1
${pkgs.mtools}/bin/mlabel -i /dev/vda2 ::boot
@@ -185,6 +233,10 @@ let
mkdir /boot
mount /dev/vda2 /boot
+ ${optionalString config.boot.loader.efi.canTouchEfiVariables ''
+ mount -t efivarfs efivarfs /sys/firmware/efi/efivars
+ ''}
+
# This is needed for GRUB 0.97, which doesn't know about virtio devices.
mkdir /boot/grub
echo '(hd0) /dev/vda' > /boot/grub/device.map
@@ -237,7 +289,7 @@ in
virtualisation.diskImage =
mkOption {
- default = "./${vmName}.qcow2";
+ default = "./${config.system.name}.qcow2";
description =
''
Path to the disk image containing the root filesystem.
@@ -396,6 +448,7 @@ in
mkOption {
type = types.listOf (types.submodule driveOpts);
description = "Drives passed to qemu.";
+ apply = addDeviceNames;
};
diskInterface =
@@ -441,11 +494,53 @@ in
'';
};
+ virtualisation.efiVars =
+ mkOption {
+ default = "./${config.system.name}-efi-vars.fd";
+ description =
+ ''
+ Path to nvram image containing UEFI variables. The will be created
+ on startup if it does not exist.
+ '';
+ };
+
+ virtualisation.bios =
+ mkOption {
+ default = null;
+ type = types.nullOr types.package;
+ description =
+ ''
+ An alternate BIOS (such as <package>qboot</package>) with which to start the VM.
+ Should contain a file named <literal>bios.bin</literal>.
+ If <literal>null</literal>, QEMU's builtin SeaBIOS will be used.
+ '';
+ };
+
};
config = {
- boot.loader.grub.device = mkVMOverride cfg.bootDevice;
+ # Note [Disk layout with `useBootLoader`]
+ #
+ # If `useBootLoader = true`, we configure 2 drives:
+ # `/dev/?da` for the root disk, and `/dev/?db` for the boot disk
+ # which has the `/boot` partition and the boot loader.
+ # Concretely:
+ #
+ # * The second drive's image `disk.img` is created in `bootDisk = ...`
+ # using a throwaway VM. Note that there the disk is always `/dev/vda`,
+ # even though in the final VM it will be at `/dev/*b`.
+ # * The disks are attached in `virtualisation.qemu.drives`.
+ # Their order makes them appear as devices `a`, `b`, etc.
+ # * `fileSystems."/boot"` is adjusted to be on device `b`.
+
+ # If `useBootLoader`, GRUB goes to the second disk, see
+ # note [Disk layout with `useBootLoader`].
+ boot.loader.grub.device = mkVMOverride (
+ if cfg.useBootLoader
+ then driveDeviceName 2 # second disk
+ else cfg.bootDevice
+ );
boot.initrd.extraUtilsCommands =
''
@@ -500,8 +595,7 @@ in
optional cfg.writableStore "overlay"
++ optional (cfg.qemu.diskInterface == "scsi") "sym53c8xx";
- virtualisation.bootDevice =
- mkDefault (if cfg.qemu.diskInterface == "scsi" then "/dev/sda" else "/dev/vda");
+ virtualisation.bootDevice = mkDefault (driveDeviceName 1);
virtualisation.pathsInNixDB = [ config.system.build.toplevel ];
@@ -519,7 +613,11 @@ in
''-append "$(cat ${config.system.build.toplevel}/kernel-params) init=${config.system.build.toplevel}/init regInfo=${regInfo}/registration ${consoles} $QEMU_KERNEL_PARAMS"''
])
(mkIf cfg.useEFIBoot [
- "-pflash $TMPDIR/bios.bin"
+ "-drive if=pflash,format=raw,unit=0,readonly,file=${efiFirmware}"
+ "-drive if=pflash,format=raw,unit=1,file=$NIX_EFI_VARS"
+ ])
+ (mkIf (cfg.bios != null) [
+ "-bios ${cfg.bios}/bios.bin"
])
(mkIf (!cfg.graphics) [
"-nographic"
@@ -527,25 +625,22 @@ in
];
virtualisation.qemu.drives = mkMerge [
+ [{
+ name = "root";
+ file = "$NIX_DISK_IMAGE";
+ driveExtraOpts.cache = "writeback";
+ driveExtraOpts.werror = "report";
+ }]
(mkIf cfg.useBootLoader [
+ # The order of this list determines the device names, see
+ # note [Disk layout with `useBootLoader`].
{
- file = "$NIX_DISK_IMAGE";
- driveExtraOpts.cache = "writeback";
- driveExtraOpts.werror = "report";
- }
- {
+ name = "boot";
file = "$TMPDIR/disk.img";
driveExtraOpts.media = "disk";
deviceExtraOpts.bootindex = "1";
}
])
- (mkIf (!cfg.useBootLoader) [
- {
- file = "$NIX_DISK_IMAGE";
- driveExtraOpts.cache = "writeback";
- driveExtraOpts.werror = "report";
- }
- ])
(imap0 (idx: _: {
file = "$(pwd)/empty${toString idx}.qcow2";
driveExtraOpts.werror = "report";
@@ -593,9 +688,9 @@ in
};
} // optionalAttrs cfg.useBootLoader
{ "/boot" =
- { device = "/dev/vdb2";
+ # see note [Disk layout with `useBootLoader`]
+ { device = "${lookupDriveDeviceName "boot" cfg.qemu.drives}2"; # 2 for e.g. `vdb2`, as created in `bootDisk`
fsType = "vfat";
- options = [ "ro" ];
noCheck = true; # fsck fails on a r/o filesystem
};
});
@@ -612,7 +707,7 @@ in
''
mkdir -p $out/bin
ln -s ${config.system.build.toplevel} $out/system
- ln -s ${pkgs.writeScript "run-nixos-vm" startVM} $out/bin/run-${vmName}-vm
+ ln -s ${pkgs.writeScript "run-nixos-vm" startVM} $out/bin/run-${config.system.name}-vm
'';
# When building a regular system configuration, override whatever
diff --git a/nixpkgs/nixos/modules/virtualisation/virtualbox-guest.nix b/nixpkgs/nixos/modules/virtualisation/virtualbox-guest.nix
index 834b994e92d..486951983d3 100644
--- a/nixpkgs/nixos/modules/virtualisation/virtualbox-guest.nix
+++ b/nixpkgs/nixos/modules/virtualisation/virtualbox-guest.nix
@@ -68,7 +68,7 @@ in
SUBSYSTEM=="misc", KERNEL=="vboxguest", TAG+="systemd"
'';
} (mkIf cfg.x11 {
- services.xserver.videoDrivers = mkOverride 50 [ "virtualbox" "modesetting" ];
+ services.xserver.videoDrivers = mkOverride 50 [ "vmware" "virtualbox" "modesetting" ];
services.xserver.config =
''
diff --git a/nixpkgs/nixos/modules/virtualisation/virtualbox-image.nix b/nixpkgs/nixos/modules/virtualisation/virtualbox-image.nix
index 788b4d9d976..fa580e8b42d 100644
--- a/nixpkgs/nixos/modules/virtualisation/virtualbox-image.nix
+++ b/nixpkgs/nixos/modules/virtualisation/virtualbox-image.nix
@@ -58,6 +58,35 @@ in {
Run <literal>VBoxManage modifyvm --help</literal> to see more options.
'';
};
+ extraDisk = mkOption {
+ description = ''
+ Optional extra disk/hdd configuration.
+ The disk will be an 'ext4' partition on a separate VMDK file.
+ '';
+ default = null;
+ example = {
+ label = "storage";
+ mountPoint = "/home/demo/storage";
+ size = 100 * 1024;
+ };
+ type = types.nullOr (types.submodule {
+ options = {
+ size = mkOption {
+ type = types.int;
+ description = "Size in MiB";
+ };
+ label = mkOption {
+ type = types.str;
+ default = "vm-extra-storage";
+ description = "Label for the disk partition";
+ };
+ mountPoint = mkOption {
+ type = types.str;
+ description = "Path where to mount this disk.";
+ };
+ };
+ });
+ };
};
};
@@ -72,6 +101,7 @@ in {
audiocontroller = "ac97";
audio = "alsa";
audioout = "on";
+ graphicscontroller = "vmsvga";
rtcuseutc = "on";
usb = "on";
usbehci = "on";
@@ -95,6 +125,20 @@ in {
echo "creating VirtualBox pass-through disk wrapper (no copying involved)..."
VBoxManage internalcommands createrawvmdk -filename disk.vmdk -rawdisk $diskImage
+ ${optionalString (cfg.extraDisk != null) ''
+ echo "creating extra disk: data-disk.raw"
+ dataDiskImage=data-disk.raw
+ truncate -s ${toString cfg.extraDisk.size}M $dataDiskImage
+
+ parted --script $dataDiskImage -- \
+ mklabel msdos \
+ mkpart primary ext4 1MiB -1
+ eval $(partx $dataDiskImage -o START,SECTORS --nr 1 --pairs)
+ mkfs.ext4 -F -L ${cfg.extraDisk.label} $dataDiskImage -E offset=$(sectorsToBytes $START) $(sectorsToKilobytes $SECTORS)K
+ echo "creating extra disk: data-disk.vmdk"
+ VBoxManage internalcommands createrawvmdk -filename data-disk.vmdk -rawdisk $dataDiskImage
+ ''}
+
echo "creating VirtualBox VM..."
vmName="${cfg.vmName}";
VBoxManage createvm --name "$vmName" --register \
@@ -105,6 +149,10 @@ in {
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
+ ${optionalString (cfg.extraDisk != null) ''
+ VBoxManage storageattach "$vmName" --storagectl SATA --port 1 --device 0 --type hdd \
+ --medium data-disk.vmdk
+ ''}
echo "exporting VirtualBox VM..."
mkdir -p $out
@@ -118,11 +166,19 @@ in {
'';
};
- fileSystems."/" = {
- device = "/dev/disk/by-label/nixos";
- autoResize = true;
- fsType = "ext4";
- };
+ fileSystems = {
+ "/" = {
+ device = "/dev/disk/by-label/nixos";
+ autoResize = true;
+ fsType = "ext4";
+ };
+ } // (lib.optionalAttrs (cfg.extraDisk != null) {
+ ${cfg.extraDisk.mountPoint} = {
+ device = "/dev/disk/by-label/" + cfg.extraDisk.label;
+ autoResize = true;
+ fsType = "ext4";
+ };
+ });
boot.growPartition = true;
boot.loader.grub.device = "/dev/sda";