aboutsummaryrefslogtreecommitdiff
path: root/nixpkgs/nixos
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
parentde94c6c62e2f86b3667386a42690d6bb376a2f58 (diff)
parent8e2b14aceb1d40c7e8b84c03a7c78955359872bb (diff)
Merge commit '8e2b14aceb1d40c7e8b84c03a7c78955359872bb'
Diffstat (limited to 'nixpkgs/nixos')
-rw-r--r--nixpkgs/nixos/doc/manual/administration/boot-problems.xml31
-rw-r--r--nixpkgs/nixos/doc/manual/configuration/configuration.xml1
-rw-r--r--nixpkgs/nixos/doc/manual/configuration/gpu-accel.xml193
-rw-r--r--nixpkgs/nixos/doc/manual/configuration/profiles/demo.xml3
-rw-r--r--nixpkgs/nixos/doc/manual/configuration/x-windows.xml46
-rw-r--r--nixpkgs/nixos/doc/manual/development/running-nixos-tests-interactively.xml9
-rw-r--r--nixpkgs/nixos/doc/manual/development/settings-options.xml179
-rw-r--r--nixpkgs/nixos/doc/manual/development/writing-modules.xml1
-rw-r--r--nixpkgs/nixos/doc/manual/development/writing-nixos-tests.xml20
-rw-r--r--nixpkgs/nixos/doc/manual/installation/installing-from-other-distro.xml2
-rw-r--r--nixpkgs/nixos/doc/manual/installation/installing-pxe.xml2
-rw-r--r--nixpkgs/nixos/doc/manual/installation/installing-virtualbox-guest.xml2
-rw-r--r--nixpkgs/nixos/doc/manual/installation/installing.xml6
-rw-r--r--nixpkgs/nixos/doc/manual/man-nixos-build-vms.xml6
-rw-r--r--nixpkgs/nixos/doc/manual/man-nixos-enter.xml10
-rw-r--r--nixpkgs/nixos/doc/manual/man-nixos-rebuild.xml2
-rw-r--r--nixpkgs/nixos/doc/manual/release-notes/rl-2003.xml2
-rw-r--r--nixpkgs/nixos/doc/manual/release-notes/rl-2009.xml254
-rw-r--r--nixpkgs/nixos/lib/make-disk-image.nix85
-rw-r--r--nixpkgs/nixos/lib/make-ext4-fs.nix39
-rw-r--r--nixpkgs/nixos/lib/make-iso9660-image.nix8
-rw-r--r--nixpkgs/nixos/lib/make-iso9660-image.sh23
-rw-r--r--nixpkgs/nixos/lib/make-options-doc/default.nix6
-rw-r--r--nixpkgs/nixos/lib/qemu-flags.nix11
-rw-r--r--nixpkgs/nixos/lib/test-driver/Logger.pm8
-rw-r--r--nixpkgs/nixos/lib/test-driver/test-driver.py47
-rw-r--r--nixpkgs/nixos/lib/testing-python.nix2
-rw-r--r--nixpkgs/nixos/lib/utils.nix8
-rw-r--r--nixpkgs/nixos/maintainers/scripts/azure-new/.gitignore2
-rw-r--r--nixpkgs/nixos/maintainers/scripts/azure-new/README.md2
-rwxr-xr-xnixpkgs/nixos/maintainers/scripts/azure-new/upload-image.sh4
-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
-rw-r--r--nixpkgs/nixos/release.nix5
-rw-r--r--nixpkgs/nixos/tests/acme.nix62
-rw-r--r--nixpkgs/nixos/tests/all-tests.nix24
-rw-r--r--nixpkgs/nixos/tests/bcachefs.nix2
-rw-r--r--nixpkgs/nixos/tests/bitcoind.nix46
-rw-r--r--nixpkgs/nixos/tests/blockbook-frontend.nix28
-rw-r--r--nixpkgs/nixos/tests/borgbackup.nix2
-rw-r--r--nixpkgs/nixos/tests/ceph-multi-node.nix6
-rw-r--r--nixpkgs/nixos/tests/ceph-single-node.nix6
-rw-r--r--nixpkgs/nixos/tests/common/auto.nix4
-rw-r--r--nixpkgs/nixos/tests/consul.nix136
-rw-r--r--nixpkgs/nixos/tests/containers-portforward.nix2
-rw-r--r--nixpkgs/nixos/tests/convos.nix30
-rw-r--r--nixpkgs/nixos/tests/corerad.nix37
-rw-r--r--nixpkgs/nixos/tests/docker-preloader.nix4
-rw-r--r--nixpkgs/nixos/tests/docker-tools.nix79
-rw-r--r--nixpkgs/nixos/tests/docker.nix4
-rw-r--r--nixpkgs/nixos/tests/dokuwiki.nix5
-rw-r--r--nixpkgs/nixos/tests/gnome3-xorg.nix6
-rw-r--r--nixpkgs/nixos/tests/gnome3.nix6
-rw-r--r--nixpkgs/nixos/tests/go-neb.nix44
-rw-r--r--nixpkgs/nixos/tests/graphite.nix11
-rw-r--r--nixpkgs/nixos/tests/grub.nix60
-rw-r--r--nixpkgs/nixos/tests/home-assistant.nix132
-rw-r--r--nixpkgs/nixos/tests/hydra/common.nix1
-rw-r--r--nixpkgs/nixos/tests/hydra/db-migration.nix6
-rw-r--r--nixpkgs/nixos/tests/ihatemoney.nix13
-rw-r--r--nixpkgs/nixos/tests/initrd-network-openvpn/default.nix145
-rw-r--r--nixpkgs/nixos/tests/initrd-network-openvpn/initrd.ovpn29
-rw-r--r--nixpkgs/nixos/tests/initrd-network-openvpn/shared.key21
-rw-r--r--nixpkgs/nixos/tests/installed-tests/default.nix6
-rw-r--r--nixpkgs/nixos/tests/installed-tests/flatpak.nix9
-rw-r--r--nixpkgs/nixos/tests/installed-tests/ibus.nix14
-rw-r--r--nixpkgs/nixos/tests/installed-tests/ostree.nix11
-rw-r--r--nixpkgs/nixos/tests/installer.nix21
-rw-r--r--nixpkgs/nixos/tests/ipfs.nix18
-rw-r--r--nixpkgs/nixos/tests/jitsi-meet.nix55
-rw-r--r--nixpkgs/nixos/tests/kubernetes/base.nix1
-rw-r--r--nixpkgs/nixos/tests/leaps.nix2
-rw-r--r--nixpkgs/nixos/tests/lorri/default.nix2
-rw-r--r--nixpkgs/nixos/tests/lxd-nftables.nix50
-rw-r--r--nixpkgs/nixos/tests/lxd.nix135
-rw-r--r--nixpkgs/nixos/tests/matrix-synapse.nix4
-rw-r--r--nixpkgs/nixos/tests/molly-brown.nix71
-rw-r--r--nixpkgs/nixos/tests/mongodb.nix6
-rw-r--r--nixpkgs/nixos/tests/ncdns.nix77
-rw-r--r--nixpkgs/nixos/tests/networking.nix21
-rw-r--r--nixpkgs/nixos/tests/nextcloud/basic.nix8
-rw-r--r--nixpkgs/nixos/tests/nfs/kerberos.nix4
-rw-r--r--nixpkgs/nixos/tests/nginx-variants.nix33
-rw-r--r--nixpkgs/nixos/tests/plasma5.nix2
-rw-r--r--nixpkgs/nixos/tests/podman.nix3
-rw-r--r--nixpkgs/nixos/tests/postfix-raise-smtpd-tls-security-level.nix44
-rw-r--r--nixpkgs/nixos/tests/postfix.nix76
-rw-r--r--nixpkgs/nixos/tests/prometheus-exporters.nix117
-rw-r--r--nixpkgs/nixos/tests/pt2-clone.nix35
-rw-r--r--nixpkgs/nixos/tests/qboot.nix13
-rw-r--r--nixpkgs/nixos/tests/radicale.nix28
-rw-r--r--nixpkgs/nixos/tests/restic.nix55
-rw-r--r--nixpkgs/nixos/tests/sddm.nix4
-rw-r--r--nixpkgs/nixos/tests/slurm.nix93
-rw-r--r--nixpkgs/nixos/tests/snapcast.nix58
-rw-r--r--nixpkgs/nixos/tests/sslh.nix83
-rw-r--r--nixpkgs/nixos/tests/sudo.nix2
-rw-r--r--nixpkgs/nixos/tests/syncthing-init.nix3
-rw-r--r--nixpkgs/nixos/tests/syncthing.nix65
-rw-r--r--nixpkgs/nixos/tests/systemd-boot.nix89
-rw-r--r--nixpkgs/nixos/tests/systemd-networkd-vrf.nix24
-rw-r--r--nixpkgs/nixos/tests/systemd.nix27
-rw-r--r--nixpkgs/nixos/tests/taskserver.nix310
-rw-r--r--nixpkgs/nixos/tests/teeworlds.nix55
-rw-r--r--nixpkgs/nixos/tests/tiddlywiki.nix2
-rw-r--r--nixpkgs/nixos/tests/trezord.nix5
-rw-r--r--nixpkgs/nixos/tests/trickster.nix6
-rw-r--r--nixpkgs/nixos/tests/wasabibackend.nix38
-rw-r--r--nixpkgs/nixos/tests/xandikos.nix4
-rw-r--r--nixpkgs/nixos/tests/xfce.nix4
-rw-r--r--nixpkgs/nixos/tests/yggdrasil.nix42
-rw-r--r--nixpkgs/nixos/tests/zigbee2mqtt.nix19
286 files changed, 9053 insertions, 2116 deletions
diff --git a/nixpkgs/nixos/doc/manual/administration/boot-problems.xml b/nixpkgs/nixos/doc/manual/administration/boot-problems.xml
index 5fa0b29e6d6..badc374ebcf 100644
--- a/nixpkgs/nixos/doc/manual/administration/boot-problems.xml
+++ b/nixpkgs/nixos/doc/manual/administration/boot-problems.xml
@@ -19,9 +19,9 @@
</term>
<listitem>
<para>
- Start a root shell if something goes wrong in stage 1 of the boot process
- (the initial ramdisk). This is disabled by default because there is no
- authentication for the root shell.
+ Allows the user to start a root shell if something goes wrong in stage 1
+ of the boot process (the initial ramdisk). This is disabled by default
+ because there is no authentication for the root shell.
</para>
</listitem>
</varlistentry>
@@ -51,6 +51,22 @@
</varlistentry>
<varlistentry>
<term>
+ <literal>boot.debug1mounts</literal>
+ </term>
+ <listitem>
+ <para>
+ Like <literal>boot.debug1</literal> or
+ <literal>boot.debug1devices</literal>, but runs stage1 until all
+ filesystems that are mounted during initrd are mounted (see
+ <option><link linkend="opt-fileSystems._name__.neededForBoot">neededForBoot</link></option>
+ ). As a motivating example, this could be useful if you've forgotten to set
+ <option><link linkend="opt-fileSystems._name__.neededForBoot">neededForBoot</link></option>
+ on a file system.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
<literal>boot.trace</literal>
</term>
<listitem>
@@ -91,6 +107,15 @@
</para>
<para>
+ Notice that for <literal>boot.shell_on_fail</literal>,
+ <literal>boot.debug1</literal>, <literal>boot.debug1devices</literal>, and
+ <literal>boot.debug1mounts</literal>, if you did <emphasis>not</emphasis>
+ select "start the new shell as pid 1", and you <literal>exit</literal> from
+ the new shell, boot will proceed normally from the point where it failed, as
+ if you'd chosen "ignore the error and continue".
+ </para>
+
+ <para>
If no login prompts or X11 login screens appear (e.g. due to hanging
dependencies), you can press Alt+ArrowUp. If you’re lucky, this will start
rescue mode (described above). (Also note that since most units have a
diff --git a/nixpkgs/nixos/doc/manual/configuration/configuration.xml b/nixpkgs/nixos/doc/manual/configuration/configuration.xml
index 507d28814ea..6eb8f50baca 100644
--- a/nixpkgs/nixos/doc/manual/configuration/configuration.xml
+++ b/nixpkgs/nixos/doc/manual/configuration/configuration.xml
@@ -18,6 +18,7 @@
<xi:include href="user-mgmt.xml" />
<xi:include href="file-systems.xml" />
<xi:include href="x-windows.xml" />
+ <xi:include href="gpu-accel.xml" />
<xi:include href="xfce.xml" />
<xi:include href="networking.xml" />
<xi:include href="linux-kernel.xml" />
diff --git a/nixpkgs/nixos/doc/manual/configuration/gpu-accel.xml b/nixpkgs/nixos/doc/manual/configuration/gpu-accel.xml
new file mode 100644
index 00000000000..0aa629cce98
--- /dev/null
+++ b/nixpkgs/nixos/doc/manual/configuration/gpu-accel.xml
@@ -0,0 +1,193 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ version="5.0"
+ xml:id="sec-gpu-accel">
+ <title>GPU acceleration</title>
+
+ <para>
+ NixOS provides various APIs that benefit from GPU hardware
+ acceleration, such as VA-API and VDPAU for video playback; OpenGL and
+ Vulkan for 3D graphics; and OpenCL for general-purpose computing.
+ This chapter describes how to set up GPU hardware acceleration (as far
+ as this is not done automatically) and how to verify that hardware
+ acceleration is indeed used.
+ </para>
+
+ <para>
+ Most of the aforementioned APIs are agnostic with regards to which
+ display server is used. Consequently, these instructions should apply
+ both to the X Window System and Wayland compositors.
+ </para>
+
+ <section xml:id="sec-gpu-accel-opencl">
+ <title>OpenCL</title>
+
+ <para>
+ <link xlink:href="https://en.wikipedia.org/wiki/OpenCL">OpenCL</link> is a
+ general compute API. It is used by various applications such as
+ Blender and Darktable to accelerate certain operations.
+ </para>
+
+ <para>
+ OpenCL applications load drivers through the <emphasis>Installable Client
+ Driver</emphasis> (ICD) mechanism. In this mechanism, an ICD file
+ specifies the path to the OpenCL driver for a particular GPU family.
+ In NixOS, there are two ways to make ICD files visible to the ICD
+ loader. The first is through the <varname>OCL_ICD_VENDORS</varname>
+ environment variable. This variable can contain a directory which
+ is scanned by the ICL loader for ICD files. For example:
+
+ <screen><prompt>$</prompt> export \
+ OCL_ICD_VENDORS=`nix-build '&lt;nixpkgs&gt;' --no-out-link -A rocm-opencl-icd`/etc/OpenCL/vendors/</screen>
+ </para>
+
+ <para>
+ The second mechanism is to add the OpenCL driver package to
+ <xref linkend="opt-hardware.opengl.extraPackages"/>. This links the
+ ICD file under <filename>/run/opengl-driver</filename>, where it will
+ be visible to the ICD loader.
+ </para>
+
+ <para>
+ The proper installation of OpenCL drivers can be verified through
+ the <command>clinfo</command> command of the <package>clinfo</package>
+ package. This command will report the number of hardware devices
+ that is found and give detailed information for each device:
+ </para>
+
+ <screen><prompt>$</prompt> clinfo | head -n3
+Number of platforms 1
+Platform Name AMD Accelerated Parallel Processing
+Platform Vendor Advanced Micro Devices, Inc.</screen>
+
+ <section xml:id="sec-gpu-accel-opencl-amd">
+ <title>AMD</title>
+
+ <para>
+ Modern AMD <link
+ xlink:href="https://en.wikipedia.org/wiki/Graphics_Core_Next">Graphics
+ Core Next</link> (GCN) GPUs are supported through the
+ <package>rocm-opencl-icd</package> package. Adding this package to
+ <xref linkend="opt-hardware.opengl.extraPackages"/> enables OpenCL
+ support. However, OpenCL Image support is provided through the
+ non-free <package>rocm-runtime-ext</package> package. This package can
+ be added to the same configuration option, but requires that
+ <varname>allowUnfree</varname> option is is enabled for nixpkgs. Full
+ OpenCL support on supported AMD GPUs is thus enabled as follows:
+
+ <programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [
+ rocm-opencl-icd
+ rocm-runtime-ext
+];</programlisting>
+ </para>
+
+ <para>
+ It is also possible to use the OpenCL Image extension without a
+ system-wide installation of the <package>rocm-runtime-ext</package>
+ package by setting the <varname>ROCR_EXT_DIR</varname> environment
+ variable to the directory that contains the extension:
+
+ <screen><prompt>$</prompt> export \
+ROCR_EXT_DIR=`nix-build '&lt;nixpkgs&gt;' --no-out-link -A rocm-runtime-ext`/lib/rocm-runtime-ext</screen>
+ </para>
+
+ <para>
+ With either approach, you can verify that OpenCL Image support
+ is indeed working with the <command>clinfo</command> command:
+
+ <screen><prompt>$</prompt> clinfo | grep Image
+ Image support Yes</screen>
+ </para>
+ </section>
+ </section>
+
+ <section xml:id="sec-gpu-accel-vulkan">
+ <title>Vulkan</title>
+
+ <para>
+ <link xlink:href="https://en.wikipedia.org/wiki/Vulkan_(API)">Vulkan</link> is a
+ graphics and compute API for GPUs. It is used directly by games or indirectly though
+ compatibility layers like <link xlink:href="https://github.com/doitsujin/dxvk/wiki">DXVK</link>.
+ </para>
+
+ <para>
+ By default, if <xref linkend="opt-hardware.opengl.driSupport"/> is enabled,
+ <package>mesa</package> is installed and provides Vulkan for supported hardware.
+ </para>
+
+ <para>
+ Similar to OpenCL, Vulkan drivers are loaded through the <emphasis>Installable Client
+ Driver</emphasis> (ICD) mechanism. ICD files for Vulkan are JSON files that specify
+ the path to the driver library and the supported Vulkan version. All successfully
+ loaded drivers are exposed to the application as different GPUs.
+ In NixOS, there are two ways to make ICD files visible to Vulkan applications: an
+ environment variable and a module option.
+ </para>
+
+ <para>
+ The first option is through the <varname>VK_ICD_FILENAMES</varname>
+ environment variable. This variable can contain multiple JSON files, separated by
+ <literal>:</literal>. For example:
+
+ <screen><prompt>$</prompt> export \
+ VK_ICD_FILENAMES=`nix-build '&lt;nixpkgs&gt;' --no-out-link -A amdvlk`/share/vulkan/icd.d/amd_icd64.json</screen>
+ </para>
+
+ <para>
+ The second mechanism is to add the Vulkan driver package to
+ <xref linkend="opt-hardware.opengl.extraPackages"/>. This links the
+ ICD file under <filename>/run/opengl-driver</filename>, where it will
+ be visible to the ICD loader.
+ </para>
+
+ <para>
+ The proper installation of Vulkan drivers can be verified through
+ the <command>vulkaninfo</command> command of the <package>vulkan-tools</package>
+ package. This command will report the hardware devices and drivers found,
+ in this example output amdvlk and radv:
+ </para>
+
+ <screen><prompt>$</prompt> vulkaninfo | grep GPU
+ GPU id : 0 (Unknown AMD GPU)
+ GPU id : 1 (AMD RADV NAVI10 (LLVM 9.0.1))
+ ...
+GPU0:
+ deviceType = PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
+ deviceName = Unknown AMD GPU
+GPU1:
+ deviceType = PHYSICAL_DEVICE_TYPE_DISCRETE_GPU</screen>
+
+ <para>
+ A simple graphical application that uses Vulkan is <command>vkcube</command>
+ from the <package>vulkan-tools</package> package.
+ </para>
+
+ <section xml:id="sec-gpu-accel-vulkan-amd">
+ <title>AMD</title>
+
+ <para>
+ Modern AMD <link
+ xlink:href="https://en.wikipedia.org/wiki/Graphics_Core_Next">Graphics
+ Core Next</link> (GCN) GPUs are supported through either radv, which is
+ part of <package>mesa</package>, or the <package>amdvlk</package> package.
+ Adding the <package>amdvlk</package> package to
+ <xref linkend="opt-hardware.opengl.extraPackages"/> makes both drivers
+ available for applications and lets them choose. A specific driver can
+ be forced as follows:
+
+ <programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [
+ <package>amdvlk</package>
+];
+
+# For amdvlk
+<xref linkend="opt-environment.variables"/>.VK_ICD_FILENAMES =
+ "/run/opengl-driver/share/vulkan/icd.d/amd_icd64.json";
+# For radv
+<xref linkend="opt-environment.variables"/>.VK_ICD_FILENAMES =
+ "/run/opengl-driver/share/vulkan/icd.d/radeon_icd.x86_64.json";
+</programlisting>
+ </para>
+ </section>
+ </section>
+</chapter>
diff --git a/nixpkgs/nixos/doc/manual/configuration/profiles/demo.xml b/nixpkgs/nixos/doc/manual/configuration/profiles/demo.xml
index 395a5ec357c..bc801bb3dc5 100644
--- a/nixpkgs/nixos/doc/manual/configuration/profiles/demo.xml
+++ b/nixpkgs/nixos/doc/manual/configuration/profiles/demo.xml
@@ -9,7 +9,6 @@
This profile just enables a <systemitem class="username">demo</systemitem>
user, with password <literal>demo</literal>, uid <literal>1000</literal>,
<systemitem class="groupname">wheel</systemitem> group and
- <link linkend="opt-services.xserver.displayManager.sddm.autoLogin"> autologin
- in the SDDM display manager</link>.
+ <link linkend="opt-services.xserver.displayManager.autoLogin">autologin in the SDDM display manager</link>.
</para>
</section>
diff --git a/nixpkgs/nixos/doc/manual/configuration/x-windows.xml b/nixpkgs/nixos/doc/manual/configuration/x-windows.xml
index 110712baf5f..18f0be5e7f3 100644
--- a/nixpkgs/nixos/doc/manual/configuration/x-windows.xml
+++ b/nixpkgs/nixos/doc/manual/configuration/x-windows.xml
@@ -90,10 +90,50 @@
using lightdm for a user <literal>alice</literal>:
<programlisting>
<xref linkend="opt-services.xserver.displayManager.lightdm.enable"/> = true;
-<xref linkend="opt-services.xserver.displayManager.lightdm.autoLogin.enable"/> = true;
-<xref linkend="opt-services.xserver.displayManager.lightdm.autoLogin.user"/> = "alice";
+<xref linkend="opt-services.xserver.displayManager.autoLogin.enable"/> = true;
+<xref linkend="opt-services.xserver.displayManager.autoLogin.user"/> = "alice";
</programlisting>
- The options are named identically for all other display managers.
+ </para>
+ </simplesect>
+ <simplesect xml:id="sec-x11--graphics-cards-intel">
+ <title>Intel Graphics drivers</title>
+ <para>
+ There are two choices for Intel Graphics drivers in X.org:
+ <literal>modesetting</literal> (included in the <package>xorg-server</package> itself)
+ and <literal>intel</literal> (provided by the package <package>xf86-video-intel</package>).
+ </para>
+ <para>
+ The default and recommended is <literal>modesetting</literal>.
+ It is a generic driver which uses the kernel
+ <link xlink:href="https://en.wikipedia.org/wiki/Mode_setting">mode setting</link>
+ (KMS) mechanism. It supports Glamor (2D graphics acceleration via OpenGL)
+ and is actively maintained but may perform worse in some cases (like in old chipsets).
+ </para>
+ <para>
+ The second driver, <literal>intel</literal>, is specific to Intel GPUs,
+ but not recommended by most distributions: it lacks several modern features
+ (for example, it doesn't support Glamor) and the package hasn't been officially
+ updated since 2015.
+ </para>
+ <para>
+ The results vary depending on the hardware, so you may have to try both drivers.
+ Use the option <xref linkend="opt-services.xserver.videoDrivers"/> to set one.
+ The recommended configuration for modern systems is:
+<programlisting>
+ <xref linkend="opt-services.xserver.videoDrivers"/> = [ "modesetting" ];
+ <xref linkend="opt-services.xserver.useGlamor"/> = true;
+</programlisting>
+ If you experience screen tearing no matter what, this configuration was
+ reported to resolve the issue:
+<programlisting>
+ <xref linkend="opt-services.xserver.videoDrivers"/> = [ "intel" ];
+ <xref linkend="opt-services.xserver.deviceSection"/> = ''
+ Option "DRI" "2"
+ Option "TearFree" "true"
+ '';
+</programlisting>
+ Note that this will likely downgrade the performance compared to
+ <literal>modesetting</literal> or <literal>intel</literal> with DRI 3 (default).
</para>
</simplesect>
<simplesect xml:id="sec-x11-graphics-cards-nvidia">
diff --git a/nixpkgs/nixos/doc/manual/development/running-nixos-tests-interactively.xml b/nixpkgs/nixos/doc/manual/development/running-nixos-tests-interactively.xml
index 31216874c70..a11a9382764 100644
--- a/nixpkgs/nixos/doc/manual/development/running-nixos-tests-interactively.xml
+++ b/nixpkgs/nixos/doc/manual/development/running-nixos-tests-interactively.xml
@@ -38,7 +38,12 @@ starting VDE switch for network 1
</para>
<para>
- The machine state is kept across VM restarts in
- <filename>/tmp/vm-state-</filename><varname>machinename</varname>.
+ You can re-use the VM states coming from a previous run
+ by setting the <command>--keep-vm-state</command> flag.
+<screen>
+<prompt>$ </prompt>./result/bin/nixos-run-vms --keep-vm-state
+</screen>
+ The machine state is stored in the
+ <filename>$TMPDIR/vm-state-</filename><varname>machinename</varname> directory.
</para>
</section>
diff --git a/nixpkgs/nixos/doc/manual/development/settings-options.xml b/nixpkgs/nixos/doc/manual/development/settings-options.xml
new file mode 100644
index 00000000000..84895adb444
--- /dev/null
+++ b/nixpkgs/nixos/doc/manual/development/settings-options.xml
@@ -0,0 +1,179 @@
+<section xmlns="http://docbook.org/ns/docbook"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ version="5.0"
+ xml:id="sec-settings-options">
+ <title>Options for Program Settings</title>
+
+ <para>
+ Many programs have configuration files where program-specific settings can be declared. File formats can be separated into two categories:
+ <itemizedlist>
+ <listitem>
+ <para>
+ Nix-representable ones: These can trivially be mapped to a subset of Nix syntax. E.g. JSON is an example, since its values like <literal>{"foo":{"bar":10}}</literal> can be mapped directly to Nix: <literal>{ foo = { bar = 10; }; }</literal>. Other examples are INI, YAML and TOML. The following section explains the convention for these settings.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Non-nix-representable ones: These can't be trivially mapped to a subset of Nix syntax. Most generic programming languages are in this group, e.g. bash, since the statement <literal>if true; then echo hi; fi</literal> doesn't have a trivial representation in Nix.
+ </para>
+ <para>
+ Currently there are no fixed conventions for these, but it is common to have a <literal>configFile</literal> option for setting the configuration file path directly. The default value of <literal>configFile</literal> can be an auto-generated file, with convenient options for controlling the contents. For example an option of type <literal>attrsOf str</literal> can be used for representing environment variables which generates a section like <literal>export FOO="foo"</literal>. Often it can also be useful to also include an <literal>extraConfig</literal> option of type <literal>lines</literal> to allow arbitrary text after the autogenerated part of the file.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <section xml:id="sec-settings-nix-representable">
+ <title>Nix-representable Formats (JSON, YAML, TOML, INI, ...)</title>
+ <para>
+ By convention, formats like this are handled with a generic <literal>settings</literal> option, representing the full program configuration as a Nix value. The type of this option should represent the format. The most common formats have a predefined type and string generator already declared under <literal>pkgs.formats</literal>:
+ <variablelist>
+ <varlistentry>
+ <term>
+ <varname>pkgs.formats.json</varname> { }
+ </term>
+ <listitem>
+ <para>
+ A function taking an empty attribute set (for future extensibility) and returning a set with JSON-specific attributes <varname>type</varname> and <varname>generate</varname> as specified <link linkend='pkgs-formats-result'>below</link>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <varname>pkgs.formats.yaml</varname> { }
+ </term>
+ <listitem>
+ <para>
+ A function taking an empty attribute set (for future extensibility) and returning a set with YAML-specific attributes <varname>type</varname> and <varname>generate</varname> as specified <link linkend='pkgs-formats-result'>below</link>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <varname>pkgs.formats.ini</varname> { <replaceable>listsAsDuplicateKeys</replaceable> ? false, ... }
+ </term>
+ <listitem>
+ <para>
+ A function taking an attribute set with values
+ <variablelist>
+ <varlistentry>
+ <term>
+ <varname>listsAsDuplicateKeys</varname>
+ </term>
+ <listitem>
+ <para>
+ A boolean for controlling whether list values can be used to represent duplicate INI keys
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ It returns a set with INI-specific attributes <varname>type</varname> and <varname>generate</varname> as specified <link linkend='pkgs-formats-result'>below</link>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <varname>pkgs.formats.toml</varname> { }
+ </term>
+ <listitem>
+ <para>
+ A function taking an empty attribute set (for future extensibility) and returning a set with TOML-specific attributes <varname>type</varname> and <varname>generate</varname> as specified <link linkend='pkgs-formats-result'>below</link>.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </para>
+ <para xml:id="pkgs-formats-result">
+ These functions all return an attribute set with these values:
+ <variablelist>
+ <varlistentry>
+ <term>
+ <varname>type</varname>
+ </term>
+ <listitem>
+ <para>
+ A module system type representing a value of the format
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <varname>generate</varname> <replaceable>filename</replaceable> <replaceable>jsonValue</replaceable>
+ </term>
+ <listitem>
+ <para>
+ A function that can render a value of the format to a file. Returns a file path.
+ <note>
+ <para>
+ This function puts the value contents in the Nix store. So this should be avoided for secrets.
+ </para>
+ </note>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ <example xml:id="ex-settings-nix-representable">
+ <title>Module with conventional <literal>settings</literal> option</title>
+ <para>
+ The following shows a module for an example program that uses a JSON configuration file. It demonstrates how above values can be used, along with some other related best practices. See the comments for explanations.
+ </para>
+<programlisting>
+{ options, config, lib, pkgs, ... }:
+let
+ cfg = config.services.foo;
+ # Define the settings format used for this program
+ settingsFormat = pkgs.formats.json {};
+in {
+
+ options.services.foo = {
+ enable = lib.mkEnableOption "foo service";
+
+ settings = lib.mkOption {
+ # Setting this type allows for correct merging behavior
+ type = settingsFormat.type;
+ default = {};
+ description = ''
+ Configuration for foo, see
+ &lt;link xlink:href="https://example.com/docs/foo"/&gt;
+ for supported values.
+ '';
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ # We can assign some default settings here to make the service work by just
+ # enabling it. We use `mkDefault` for values that can be changed without
+ # problems
+ services.foo.settings = {
+ # Fails at runtime without any value set
+ log_level = lib.mkDefault "WARN";
+
+ # We assume systemd's `StateDirectory` is used, so we require this value,
+ # therefore no mkDefault
+ data_path = "/var/lib/foo";
+
+ # Since we use this to create a user we need to know the default value at
+ # eval time
+ user = lib.mkDefault "foo";
+ };
+
+ environment.etc."foo.json".source =
+ # The formats generator function takes a filename and the Nix value
+ # representing the format value and produces a filepath with that value
+ # rendered in the format
+ settingsFormat.generate "foo-config.json" cfg.settings;
+
+ # We know that the `user` attribute exists because we set a default value
+ # for it above, allowing us to use it without worries here
+ users.users.${cfg.settings.user} = {}
+
+ # ...
+ };
+}
+</programlisting>
+ </example>
+ </section>
+
+</section>
diff --git a/nixpkgs/nixos/doc/manual/development/writing-modules.xml b/nixpkgs/nixos/doc/manual/development/writing-modules.xml
index bbf793bb0be..602f134f9cb 100644
--- a/nixpkgs/nixos/doc/manual/development/writing-modules.xml
+++ b/nixpkgs/nixos/doc/manual/development/writing-modules.xml
@@ -183,4 +183,5 @@ in {
<xi:include href="meta-attributes.xml" />
<xi:include href="importing-modules.xml" />
<xi:include href="replace-modules.xml" />
+ <xi:include href="settings-options.xml" />
</chapter>
diff --git a/nixpkgs/nixos/doc/manual/development/writing-nixos-tests.xml b/nixpkgs/nixos/doc/manual/development/writing-nixos-tests.xml
index 150bea8c2d8..74ab23605b3 100644
--- a/nixpkgs/nixos/doc/manual/development/writing-nixos-tests.xml
+++ b/nixpkgs/nixos/doc/manual/development/writing-nixos-tests.xml
@@ -216,12 +216,12 @@ start_all()
</varlistentry>
<varlistentry>
<term>
- <methodname>send_keys</methodname>
+ <methodname>send_key</methodname>
</term>
<listitem>
<para>
Simulate pressing keys on the virtual keyboard, e.g.,
- <literal>send_keys("ctrl-alt-delete")</literal>.
+ <literal>send_key("ctrl-alt-delete")</literal>.
</para>
</listitem>
</varlistentry>
@@ -232,7 +232,7 @@ start_all()
<listitem>
<para>
Simulate typing a sequence of characters on the virtual keyboard, e.g.,
- <literal>send_keys("foobar\n")</literal> will type the string
+ <literal>send_chars("foobar\n")</literal> will type the string
<literal>foobar</literal> followed by the Enter key.
</para>
</listitem>
@@ -362,6 +362,18 @@ start_all()
</varlistentry>
<varlistentry>
<term>
+ <methodname>wait_for_console_text</methodname>
+ </term>
+ <listitem>
+ <para>
+ Wait until the supplied regular expressions match a line of the serial
+ console output. This method is useful when OCR is not possibile or
+ accurate enough.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
<methodname>wait_for_window</methodname>
</term>
<listitem>
@@ -378,7 +390,7 @@ start_all()
<listitem>
<para>
Copies a file from host to machine, e.g.,
- <literal>copy_file_from_host("myfile", "/etc/my/important/file")</literal>.
+ <literal>copy_from_host("myfile", "/etc/my/important/file")</literal>.
</para>
<para>
The first argument is the file on the host. The file needs to be
diff --git a/nixpkgs/nixos/doc/manual/installation/installing-from-other-distro.xml b/nixpkgs/nixos/doc/manual/installation/installing-from-other-distro.xml
index 8ed45899fd7..45d68f8787f 100644
--- a/nixpkgs/nixos/doc/manual/installation/installing-from-other-distro.xml
+++ b/nixpkgs/nixos/doc/manual/installation/installing-from-other-distro.xml
@@ -89,7 +89,7 @@ nixpkgs https://nixos.org/channels/nixpkgs-unstable</screen>
NixOS partition. They are installed by default on NixOS, but you don't have
NixOS yet..
</para>
-<screen><prompt>$ </prompt>nix-env -iE "_: with import &lt;nixpkgs/nixos&gt; { configuration = {}; }; with config.system.build; [ nixos-generate-config nixos-install nixos-enter manual.manpages ]"</screen>
+<screen><prompt>$ </prompt>nix-env -f '&lt;nixpkgs/nixos&gt;' --arg configuration {} -iA config.system.build.{nixos-generate-config,nixos-install,nixos-enter,manual.manpages}</screen>
</listitem>
<listitem>
<note>
diff --git a/nixpkgs/nixos/doc/manual/installation/installing-pxe.xml b/nixpkgs/nixos/doc/manual/installation/installing-pxe.xml
index 94199e5e028..ea88fbdad7e 100644
--- a/nixpkgs/nixos/doc/manual/installation/installing-pxe.xml
+++ b/nixpkgs/nixos/doc/manual/installation/installing-pxe.xml
@@ -16,7 +16,7 @@
</para>
<programlisting>
-nix-build -A netboot nixos/release.nix
+nix-build -A netboot.x86_64-linux nixos/release.nix
</programlisting>
<para>
diff --git a/nixpkgs/nixos/doc/manual/installation/installing-virtualbox-guest.xml b/nixpkgs/nixos/doc/manual/installation/installing-virtualbox-guest.xml
index 0ba909fa953..1cffeed4807 100644
--- a/nixpkgs/nixos/doc/manual/installation/installing-virtualbox-guest.xml
+++ b/nixpkgs/nixos/doc/manual/installation/installing-virtualbox-guest.xml
@@ -49,7 +49,7 @@
</listitem>
<listitem>
<para>
- Click on Settings / Display / Screen and select VBoxVGA as Graphics Controller
+ Click on Settings / Display / Screen and select VMSVGA as Graphics Controller
</para>
</listitem>
<listitem>
diff --git a/nixpkgs/nixos/doc/manual/installation/installing.xml b/nixpkgs/nixos/doc/manual/installation/installing.xml
index 673df8f2e4c..5f216df66f8 100644
--- a/nixpkgs/nixos/doc/manual/installation/installing.xml
+++ b/nixpkgs/nixos/doc/manual/installation/installing.xml
@@ -42,7 +42,7 @@
</para>
<para>
- If the text is too small to be legible, try <command>setfont ter-132n</command>
+ If the text is too small to be legible, try <command>setfont ter-v32n</command>
to increase the font size.
</para>
@@ -146,7 +146,7 @@
partition. It uses the initially reserved 512MiB at the start of the
disk.
<screen language="commands"><prompt># </prompt>parted /dev/sda -- mkpart ESP fat32 1MiB 512MiB
-<prompt># </prompt>parted /dev/sda -- set 3 boot on</screen>
+<prompt># </prompt>parted /dev/sda -- set 3 esp on</screen>
</para>
</listitem>
</orderedlist>
@@ -513,7 +513,7 @@ Retype new UNIX password: ***</screen>
<prompt># </prompt>parted /dev/sda -- mkpart primary 512MiB -8GiB
<prompt># </prompt>parted /dev/sda -- mkpart primary linux-swap -8GiB 100%
<prompt># </prompt>parted /dev/sda -- mkpart ESP fat32 1MiB 512MiB
-<prompt># </prompt>parted /dev/sda -- set 3 boot on</screen>
+<prompt># </prompt>parted /dev/sda -- set 3 esp on</screen>
</example>
<example xml:id="ex-install-sequence">
diff --git a/nixpkgs/nixos/doc/manual/man-nixos-build-vms.xml b/nixpkgs/nixos/doc/manual/man-nixos-build-vms.xml
index d114261f53b..fa7c8c0c6d7 100644
--- a/nixpkgs/nixos/doc/manual/man-nixos-build-vms.xml
+++ b/nixpkgs/nixos/doc/manual/man-nixos-build-vms.xml
@@ -13,15 +13,15 @@
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
- <command>nixos-build-vms</command>
+ <command>nixos-build-vms</command>
<arg>
<option>--show-trace</option>
</arg>
-
+
<arg>
<option>--no-out-link</option>
</arg>
-
+
<arg>
<option>--help</option>
</arg>
diff --git a/nixpkgs/nixos/doc/manual/man-nixos-enter.xml b/nixpkgs/nixos/doc/manual/man-nixos-enter.xml
index fe560d3efdd..c32e1c7f8ca 100644
--- a/nixpkgs/nixos/doc/manual/man-nixos-enter.xml
+++ b/nixpkgs/nixos/doc/manual/man-nixos-enter.xml
@@ -13,21 +13,21 @@
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
- <command>nixos-enter</command>
+ <command>nixos-enter</command>
<arg>
<arg choice='plain'>
<option>--root</option>
</arg>
<replaceable>root</replaceable>
</arg>
-
+
<arg>
<arg choice='plain'>
<option>--system</option>
</arg>
<replaceable>system</replaceable>
</arg>
-
+
<arg>
<arg choice='plain'>
<option>-c</option>
@@ -40,13 +40,13 @@
<option>--silent</option>
</arg>
</arg>
-
+
<arg>
<arg choice='plain'>
<option>--help</option>
</arg>
</arg>
-
+
<arg>
<arg choice='plain'>
<option>--</option>
diff --git a/nixpkgs/nixos/doc/manual/man-nixos-rebuild.xml b/nixpkgs/nixos/doc/manual/man-nixos-rebuild.xml
index f4f663b84f0..f70f08a0f8a 100644
--- a/nixpkgs/nixos/doc/manual/man-nixos-rebuild.xml
+++ b/nixpkgs/nixos/doc/manual/man-nixos-rebuild.xml
@@ -315,7 +315,7 @@
switch</command>), because the hardware and boot loader configuration in
the VM are different. The boot loader is installed on an automatically
generated virtual disk containing a <filename>/boot</filename>
- partition, which is mounted read-only in the VM.
+ partition.
</para>
</listitem>
</varlistentry>
diff --git a/nixpkgs/nixos/doc/manual/release-notes/rl-2003.xml b/nixpkgs/nixos/doc/manual/release-notes/rl-2003.xml
index 393a9286ca4..0e9ba027a38 100644
--- a/nixpkgs/nixos/doc/manual/release-notes/rl-2003.xml
+++ b/nixpkgs/nixos/doc/manual/release-notes/rl-2003.xml
@@ -792,7 +792,7 @@ users.users.me =
The <option>services.xserver.displayManager.auto</option> module has been removed.
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 <xref linkend="opt-services.xserver.displayManager.lightdm.autoLogin"/> options instead,
+ Please use the <option>services.xserver.displayManager.lightdm.autoLogin</option> options instead,
or any other display manager in NixOS as they all support auto-login. If you used this module specifically
because it permitted root auto-login you can override the lightdm-autologin pam module like:
<programlisting>
diff --git a/nixpkgs/nixos/doc/manual/release-notes/rl-2009.xml b/nixpkgs/nixos/doc/manual/release-notes/rl-2009.xml
index 115f9ebc565..a14ca76cf9b 100644
--- a/nixpkgs/nixos/doc/manual/release-notes/rl-2009.xml
+++ b/nixpkgs/nixos/doc/manual/release-notes/rl-2009.xml
@@ -44,6 +44,11 @@
</listitem>
<listitem>
<para>
+ Python 3 now defaults to Python 3.8 instead of 3.7.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
Two new options, <link linkend="opt-services.openssh.authorizedKeysCommand">authorizedKeysCommand</link>
and <link linkend="opt-services.openssh.authorizedKeysCommandUser">authorizedKeysCommandUser</link>, have
been added to the <literal>openssh</literal> module. If you have <literal>AuthorizedKeysCommand</literal>
@@ -89,6 +94,52 @@ services.mysql.initialScript = pkgs.writeText "mariadb-init.sql" ''
When MariaDB data directory is just upgraded (not initialized), the users are not created or modified.
</para>
</listitem>
+ <listitem>
+ <para>
+ MySQL server is now started with additional systemd sandbox/hardening options for better security. The PrivateTmp, ProtectHome, and ProtectSystem options
+ may be problematic when MySQL is attempting to read from or write to your filesystem anywhere outside of its own state directory, for example when
+ calling <literal>LOAD DATA INFILE or SELECT * INTO OUTFILE</literal>. In this scenario a variant of the following may be required:
+ - allow MySQL to read from /home and /tmp directories when using <literal>LOAD DATA INFILE</literal>
+<programlisting>
+systemd.services.mysql.serviceConfig.ProtectHome = lib.mkForce "read-only";
+</programlisting>
+ - allow MySQL to write to custom folder <literal>/var/data</literal> when using <literal>SELECT * INTO OUTFILE</literal>, assuming the mysql user has write
+ access to <literal>/var/data</literal>
+<programlisting>
+systemd.services.mysql.serviceConfig.ReadWritePaths = [ "/var/data" ];
+</programlisting>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Two new option <link linkend="opt-documentation.man.generateCaches">documentation.man.generateCaches</link>
+ has been added to automatically generate the <literal>man-db</literal> caches, which are needed by utilities
+ like <command>whatis</command> and <command>apropos</command>. The caches are generated during the build of
+ the NixOS configuration: since this can be expensive when a large number of packages are installed, the
+ feature is disabled by default.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <varname>services.postfix.sslCACert</varname> was replaced by <varname>services.postfix.tlsTrustedAuthorities</varname> which now defaults to system certifcate authorities.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Subordinate GID and UID mappings are now set up automatically for all normal users.
+ This will make container tools like Podman work as non-root users out of the box.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The various documented workarounds to use steam have been converted to a module. <varname>programs.steam.enable</varname> enables steam, controller support and the workarounds.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Support for built-in LCDs in various pieces of Logitech hardware (keyboards and USB speakers). <varname>hardware.logitech.lcd.enable</varname> enables support for all hardware supported by the g15daemon project.
+ </para>
+ </listitem>
</itemizedlist>
</section>
@@ -178,6 +229,12 @@ services.mysql.initialScript = pkgs.writeText "mariadb-init.sql" ''
</listitem>
<listitem>
<para>
+ <literal>vmware</literal> has been removed from the <literal>services.x11.videoDrivers</literal> defaults.
+ For VMWare guests set <literal>virtualisation.vmware.guest.enable</literal> to <literal>true</literal> which will include the appropriate drivers.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
The initrd SSH support now uses OpenSSH rather than Dropbear to
allow the use of Ed25519 keys and other OpenSSH-specific
functionality. Host keys must now be in the OpenSSH format, and at
@@ -455,6 +512,87 @@ systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/www" ];
initrd file has not been deleted.
</para>
</listitem>
+ <listitem>
+ <para>
+ The <link xlink:href="https://github.com/okTurtles/dnschain">DNSChain</link>
+ package and NixOS module have been removed from Nixpkgs as the software is
+ unmaintained and can't be built. For more information see issue
+ <link xlink:href="https://github.com/NixOS/nixpkgs/issues/89205">#89205</link>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ In the <literal>resilio</literal> module, <xref linkend="opt-services.resilio.httpListenAddr"/> has been changed to listen to <literal>[::1]</literal> instead of <literal>0.0.0.0</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Radicale's default package has changed from 2.x to 3.x. An upgrade
+ checklist can be found
+ <link xlink:href="https://github.com/Kozea/Radicale/blob/3.0.x/NEWS.md#upgrade-checklist">here</link>.
+ You can use the newer version in the NixOS service by setting the
+ <literal>package</literal> to <literal>radicale3</literal>, which is done
+ automatically if <literal>stateVersion</literal> is 20.09 or higher.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>udpt</literal> experienced a complete rewrite from C++ to rust. The configuration format changed from ini to toml.
+ The new configuration documentation can be found at
+ <link xlink:href="https://naim94a.github.io/udpt/config.html">the official website</link> and example
+ configuration is packaged in <literal>${udpt}/share/udpt/udpt.toml</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ We now have a unified <xref linkend="opt-services.xserver.displayManager.autoLogin"/> option interface
+ to be used for every display-manager in NixOS.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The <literal>bitcoind</literal> module has changed to multi-instance, using submodules.
+ Therefore, it is now mandatory to name each instance.
+ To use this new multi-instance config with an existing bitcoind data directory and user,
+ you have to adjust the original config, e.g.:
+<programlisting>
+ services.bitcoind = {
+ enable = true;
+ extraConfig = "...";
+ ...
+ };
+</programlisting>
+ To something similar:
+<programlisting>
+ services.bitcoind.mainnet = {
+ enable = true;
+ dataDir = "/var/lib/bitcoind";
+ user = "bitcoin";
+ extraConfig = "...";
+ ...
+ };
+</programlisting>
+ The key settings are:
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>dataDir</literal> - to continue using the same data directory.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>user</literal> - to continue using the same user so that bitcoind maintains access to its files.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Graylog introduced a change in the LDAP server certificate validation behaviour for version 3.3.3 which might break existing setups.
+ When updating Graylog from a version before 3.3.3 make sure to check the Graylog <link xlink:href="https://www.graylog.org/post/announcing-graylog-v3-3-3">release info</link> for information on how to avoid the issue.
+ </para>
+ </listitem>
</itemizedlist>
</section>
@@ -467,6 +605,9 @@ systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/www" ];
<itemizedlist>
<listitem>
+ <para>SD images are now compressed by default using <literal>zstd</literal>. The compression for ISO images has also been changed to <literal>zstd</literal>, but ISO images are still not compressed by default.</para>
+ </listitem>
+ <listitem>
<para>
<option>services.journald.rateLimitBurst</option> was updated from
<literal>1000</literal> to <literal>10000</literal> to follow the new
@@ -483,8 +624,31 @@ systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/www" ];
</para>
</listitem>
<listitem>
+ <para>
+ The default output of <literal>buildGoPackage</literal> is now <literal>$out</literal> instead of <literal>$bin</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Packages built using <literal>buildRustPackage</literal> now use <literal>release</literal>
+ mode for the <literal>checkPhase</literal> by default.
+ </para>
+ <para>
+ Please note that Rust packages utilizing a custom build/install procedure
+ (e.g. by using a <filename>Makefile</filename>) or test suites that rely on the
+ structure of the <filename>target/</filename> directory may break due to those assumptions.
+ For further information, please read the Rust section in the Nixpkgs manual.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The cc- and binutils-wrapper's "infix salt" and <literal>_BUILD_</literal> and <literal>_TARGET_</literal> user infixes have been replaced with with a "suffix salt" and suffixes and <literal>_FOR_BUILD</literal> and <literal>_FOR_TARGET</literal>.
+ This matches the autotools convention for env vars which standard for these things, making interfacing with other tools easier.
+ </para>
+ </listitem>
+ <listitem>
<para>
- The default output of <literal>buildGoPackage</literal> is now <literal>$out</literal> instead of <literal>$bin</literal>.
+ Additional Git documentation (HTML and text files) is now available via the <literal>git-doc</literal> package.
</para>
</listitem>
<listitem>
@@ -515,6 +679,94 @@ systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/www" ];
<link xlink:href="https://grafana.com/docs/grafana/latest/installation/upgrading/#upgrading-to-v7-0">in the Grafana documentation</link>.
</para>
</listitem>
+ <listitem>
+ <para>
+ The <literal>hardware.u2f</literal> module, which was installing udev rules
+ was removed, as udev gained native support to handle FIDO security tokens.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ With this release <literal>systemd-networkd</literal> (when enabled through <xref linkend="opt-networking.useNetworkd"/>)
+ has it's netlink socket created through a <literal>systemd.socket</literal> unit. This gives us control over
+ socket buffer sizes and other parameters. For larger setups where networkd has to create a lot of (virtual)
+ devices the default buffer size (currently 128MB) is not enough.
+ </para>
+ <para>
+ On a machine with &gt;100 virtual interfaces (e.g., wireguard tunnels, VLANs, …), that all have to
+ be brought up during system startup, the receive buffer size will spike for a brief period.
+ Eventually some of the message will be dropped since there is not enough (permitted) buffer
+ space available.
+ </para>
+ <para>
+ By having <literal>systemd-networkd</literal> start with a netlink socket created by
+ <literal>systemd</literal> we can configure the <literal>ReceiveBufferSize=</literal> parameter
+ in the socket options (i.e. <literal>systemd.sockets.systemd-networkd.socketOptions.ReceiveBufferSize</literal>)
+ without recompiling <literal>systemd-networkd</literal>.
+ </para>
+ <para>
+ Since the actual memory requirements depend on hardware, timing, exact
+ configurations etc. it isn't currently possible to infer a good default
+ from within the NixOS module system. Administrators are advised to
+ monitor the logs of <literal>systemd-networkd</literal> for <literal>rtnl: kernel receive buffer
+ overrun</literal> spam and increase the memory limit as they see fit.
+ </para>
+ <para>
+ Note: Increasing the <literal>ReceiveBufferSize=</literal> doesn't allocate any memory. It just increases
+ the upper bound on the kernel side. The memory allocation depends on the amount of messages that are
+ queued on the kernel side of the netlink socket.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Specifying <link linkend="opt-services.dovecot2.mailboxes">mailboxes</link> in the <package>dovecot2</package> module
+ as a list is deprecated and will break eval in 21.03. Instead, an attribute-set should be specified where the <literal>name</literal>
+ should be the key of the attribute.
+ </para>
+ <para>
+ This means that a configuration like this
+<programlisting>{
+ <link linkend="opt-services.dovecot2.mailboxes">services.dovecot2.mailboxes</link> = [
+ { name = "Junk";
+ auto = "create";
+ }
+ ];
+}</programlisting>
+ should now look like this:
+<programlisting>{
+ <link linkend="opt-services.dovecot2.mailboxes">services.dovecot2.mailboxes</link> = {
+ Junk.auto = "create";
+ };
+}</programlisting>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <package>netbeans</package> was upgraded to 12.0 and now defaults to OpenJDK 11. This might cause problems if your projects depend on packages that were removed in Java 11.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <package>nextcloud</package> has been updated to <link xlink:href="https://nextcloud.com/blog/nextcloud-hub-brings-productivity-to-home-office/">v19</link>.
+ </para>
+ <para>
+ If you have an existing installation, please make sure that you're on
+ <package>nextcloud18</package> before upgrading to <package>nextcloud19</package>
+ since Nextcloud doesn't support upgrades across multiple major versions.
+ </para>
+ <para>
+ The <literal>nixos-run-vms</literal> script now deletes the
+ previous run machines states on test startup. You can use the
+ <literal>--keep-vm-state</literal> flag to match the previous
+ behaviour and keep the same VM state between different test runs.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The <link linkend="opt-nix.buildMachines">nix.buildMachines</link> option is now type-checked.
+ There are no functional changes, however this may require updating some configurations to use correct types for all attributes.
+ </para>
+ </listitem>
</itemizedlist>
</section>
</section>
diff --git a/nixpkgs/nixos/lib/make-disk-image.nix b/nixpkgs/nixos/lib/make-disk-image.nix
index 5e86ea479d5..8aa606a56af 100644
--- a/nixpkgs/nixos/lib/make-disk-image.nix
+++ b/nixpkgs/nixos/lib/make-disk-image.nix
@@ -5,21 +5,32 @@
config
, # The size of the disk, in megabytes.
- diskSize
+ # if "auto" size is calculated based on the contents copied to it and
+ # additionalSpace is taken into account.
+ diskSize ? "auto"
- # The files and directories to be placed in the target file system.
+, # additional disk space to be added to the image if diskSize "auto"
+ # is used
+ additionalSpace ? "512M"
+
+, # size of the boot partition, is only used if partitionTableType is
+ # either "efi" or "hybrid"
+ bootSize ? "256M"
+
+, # The files and directories to be placed in the target file system.
# This is a list of attribute sets {source, target} where `source'
# is the file system object (regular file or directory) to be
# grafted in the file system at path `target'.
-, contents ? []
+ contents ? []
, # Type of partition table to use; either "legacy", "efi", or "none".
# For "efi" images, the GPT partition table is used and a mandatory ESP
# partition of reasonable size is created in addition to the root partition.
- # If `installBootLoader` is true, GRUB will be installed in EFI mode.
# For "legacy", the msdos partition table is used and a single large root
- # partition is created. If `installBootLoader` is true, GRUB will be
- # installed in legacy mode.
+ # partition is created.
+ # For "hybrid", the GPT partition table is used and a mandatory ESP
+ # partition of reasonable size is created in addition to the root partition.
+ # Also a legacy MBR will be present.
# For "none", no partition table is created. Enabling `installBootLoader`
# most likely fails as GRUB will probably refuse to install.
partitionTableType ? "legacy"
@@ -39,11 +50,11 @@
, name ? "nixos-disk-image"
-, # Disk image format, one of qcow2, qcow2-compressed, vpc, raw.
+, # Disk image format, one of qcow2, qcow2-compressed, vdi, vpc, raw.
format ? "raw"
}:
-assert partitionTableType == "legacy" || partitionTableType == "efi" || partitionTableType == "none";
+assert partitionTableType == "legacy" || partitionTableType == "efi" || partitionTableType == "hybrid" || partitionTableType == "none";
# We use -E offset=X below, which is only supported by e2fsprogs
assert partitionTableType != "none" -> fsType == "ext4";
@@ -57,13 +68,15 @@ let format' = format; in let
filename = "nixos." + {
qcow2 = "qcow2";
+ vdi = "vdi";
vpc = "vhd";
raw = "img";
- }.${format};
+ }.${format} or format;
rootPartition = { # switch-case
legacy = "1";
efi = "2";
+ hybrid = "3";
}.${partitionTableType};
partitionDiskScript = { # switch-case
@@ -75,9 +88,18 @@ let format' = format; in let
efi = ''
parted --script $diskImage -- \
mklabel gpt \
- mkpart ESP fat32 8MiB 256MiB \
+ mkpart ESP fat32 8MiB ${bootSize} \
set 1 boot on \
- mkpart primary ext4 256MiB -1
+ mkpart primary ext4 ${bootSize} -1
+ '';
+ hybrid = ''
+ parted --script $diskImage -- \
+ mklabel gpt \
+ mkpart ESP fat32 8MiB ${bootSize} \
+ set 1 boot on \
+ mkpart no-fs 0 1024KiB \
+ set 2 bios_grub on \
+ mkpart primary ext4 ${bootSize} -1
'';
none = "";
}.${partitionTableType};
@@ -128,19 +150,6 @@ let format' = format; in let
}
mkdir $out
- diskImage=nixos.raw
- truncate -s ${toString diskSize}M $diskImage
-
- ${partitionDiskScript}
-
- ${if partitionTableType != "none" then ''
- # Get start & length of the root partition in sectors to $START and $SECTORS.
- eval $(partx $diskImage -o START,SECTORS --nr ${rootPartition} --pairs)
-
- mkfs.${fsType} -F -L ${label} $diskImage -E offset=$(sectorsToBytes $START) $(sectorsToKilobytes $SECTORS)K
- '' else ''
- mkfs.${fsType} -F -L ${label} $diskImage
- ''}
root="$PWD/root"
mkdir -p $root
@@ -180,10 +189,36 @@ let format' = format; in let
export NIX_STATE_DIR=$TMPDIR/state
nix-store --load-db < ${closureInfo}/registration
+ chmod 755 "$TMPDIR"
echo "running nixos-install..."
nixos-install --root $root --no-bootloader --no-root-passwd \
--system ${config.system.build.toplevel} --channel ${channelSources} --substituters ""
+ diskImage=nixos.raw
+
+ ${if diskSize == "auto" then ''
+ ${if partitionTableType == "efi" || partitionTableType == "hybrid" then ''
+ additionalSpace=$(( ($(numfmt --from=iec '${additionalSpace}') + $(numfmt --from=iec '${bootSize}')) / 1000 ))
+ '' else ''
+ additionalSpace=$(( $(numfmt --from=iec '${additionalSpace}') / 1000 ))
+ ''}
+ diskSize=$(( $(set -- $(du -d0 $root); echo "$1") + $additionalSpace ))
+ truncate -s "$diskSize"K $diskImage
+ '' else ''
+ truncate -s ${toString diskSize}M $diskImage
+ ''}
+
+ ${partitionDiskScript}
+
+ ${if partitionTableType != "none" then ''
+ # Get start & length of the root partition in sectors to $START and $SECTORS.
+ eval $(partx $diskImage -o START,SECTORS --nr ${rootPartition} --pairs)
+
+ mkfs.${fsType} -F -L ${label} $diskImage -E offset=$(sectorsToBytes $START) $(sectorsToKilobytes $SECTORS)K
+ '' else ''
+ mkfs.${fsType} -F -L ${label} $diskImage
+ ''}
+
echo "copying staging root to image..."
cptofs -p ${optionalString (partitionTableType != "none") "-P ${rootPartition}"} -t ${fsType} -i $diskImage $root/* /
'';
@@ -217,7 +252,7 @@ in pkgs.vmTools.runInLinuxVM (
# Create the ESP and mount it. Unlike e2fsprogs, mkfs.vfat doesn't support an
# '-E offset=X' option, so we can't do this outside the VM.
- ${optionalString (partitionTableType == "efi") ''
+ ${optionalString (partitionTableType == "efi" || partitionTableType == "hybrid") ''
mkdir -p /mnt/boot
mkfs.vfat -n ESP /dev/vda1
mount /dev/vda1 /mnt/boot
diff --git a/nixpkgs/nixos/lib/make-ext4-fs.nix b/nixpkgs/nixos/lib/make-ext4-fs.nix
index 627ac324cf5..74a6c134e64 100644
--- a/nixpkgs/nixos/lib/make-ext4-fs.nix
+++ b/nixpkgs/nixos/lib/make-ext4-fs.nix
@@ -17,7 +17,7 @@
, e2fsprogs
, libfaketime
, perl
-, lkl
+, fakeroot
}:
let
@@ -26,7 +26,7 @@ in
pkgs.stdenv.mkDerivation {
name = "ext4-fs.img${lib.optionalString compressImage ".zst"}";
- nativeBuildInputs = [ e2fsprogs.bin libfaketime perl lkl ]
+ nativeBuildInputs = [ e2fsprogs.bin libfaketime perl fakeroot ]
++ lib.optional compressImage zstd;
buildCommand =
@@ -37,32 +37,31 @@ pkgs.stdenv.mkDerivation {
${populateImageCommands}
)
- # Add the closures of the top-level store objects.
- storePaths=$(cat ${sdClosureInfo}/store-paths)
+ echo "Preparing store paths for image..."
+
+ # Create nix/store before copying path
+ mkdir -p ./rootImage/nix/store
+
+ xargs -I % cp -a --reflink=auto % -t ./rootImage/nix/store/ < ${sdClosureInfo}/store-paths
+ (
+ GLOBIGNORE=".:.."
+ shopt -u dotglob
+ cp -a --reflink=auto ./files/* -t ./rootImage/
+ )
+
+ # Also include a manifest of the closures in a format suitable for nix-store --load-db
+ cp ${sdClosureInfo}/registration ./rootImage/nix-path-registration
# Make a crude approximation of the size of the target image.
# If the script starts failing, increase the fudge factors here.
- numInodes=$(find $storePaths ./files | wc -l)
- numDataBlocks=$(du -s -c -B 4096 --apparent-size $storePaths ./files | tail -1 | awk '{ print int($1 * 1.03) }')
+ numInodes=$(find ./rootImage | wc -l)
+ numDataBlocks=$(du -s -c -B 4096 --apparent-size ./rootImage | tail -1 | awk '{ print int($1 * 1.10) }')
bytes=$((2 * 4096 * $numInodes + 4096 * $numDataBlocks))
echo "Creating an EXT4 image of $bytes bytes (numInodes=$numInodes, numDataBlocks=$numDataBlocks)"
truncate -s $bytes $img
- faketime -f "1970-01-01 00:00:01" mkfs.ext4 -L ${volumeLabel} -U ${uuid} $img
-
- # Also include a manifest of the closures in a format suitable for nix-store --load-db.
- cp ${sdClosureInfo}/registration nix-path-registration
- cptofs -t ext4 -i $img nix-path-registration /
-
- # Create nix/store before copying paths
- faketime -f "1970-01-01 00:00:01" mkdir -p nix/store
- cptofs -t ext4 -i $img nix /
-
- echo "copying store paths to image..."
- cptofs -t ext4 -i $img $storePaths /nix/store/
- echo "copying files to image..."
- cptofs -t ext4 -i $img ./files/* /
+ faketime -f "1970-01-01 00:00:01" fakeroot mkfs.ext4 -L ${volumeLabel} -U ${uuid} -d ./rootImage $img
export EXT2FS_NO_MTAB_OK=yes
# I have ended up with corrupted images sometimes, I suspect that happens when the build machine's disk gets full during the build.
diff --git a/nixpkgs/nixos/lib/make-iso9660-image.nix b/nixpkgs/nixos/lib/make-iso9660-image.nix
index 0f3f2b5b523..6a0e0e7c635 100644
--- a/nixpkgs/nixos/lib/make-iso9660-image.nix
+++ b/nixpkgs/nixos/lib/make-iso9660-image.nix
@@ -1,4 +1,4 @@
-{ stdenv, closureInfo, xorriso, syslinux
+{ stdenv, closureInfo, xorriso, syslinux, libossp_uuid
, # The file name of the resulting ISO image.
isoName ? "cd.iso"
@@ -34,8 +34,8 @@
, # The path (outside the ISO file system) of the isohybrid-mbr image.
isohybridMbrImage ? ""
-, # Whether to compress the resulting ISO image with bzip2.
- compressImage ? false
+, # Whether to compress the resulting ISO image with zstd.
+ compressImage ? false, zstd
, # The volume ID.
volumeID ? ""
@@ -48,7 +48,7 @@ assert usbBootable -> isohybridMbrImage != "";
stdenv.mkDerivation {
name = isoName;
builder = ./make-iso9660-image.sh;
- buildInputs = [ xorriso syslinux ];
+ buildInputs = [ xorriso syslinux zstd libossp_uuid ];
inherit isoName bootable bootImage compressImage volumeID efiBootImage efiBootable isohybridMbrImage usbBootable;
diff --git a/nixpkgs/nixos/lib/make-iso9660-image.sh b/nixpkgs/nixos/lib/make-iso9660-image.sh
index d4633d2c8d1..4740b05f955 100644
--- a/nixpkgs/nixos/lib/make-iso9660-image.sh
+++ b/nixpkgs/nixos/lib/make-iso9660-image.sh
@@ -99,7 +99,12 @@ done
mkdir -p $out/iso
+# daed2280-b91e-42c0-aed6-82c825ca41f3 is an arbitrary namespace, to prevent
+# independent applications from generating the same UUID for the same value.
+# (the chance of that being problematic seem pretty slim here, but that's how
+# version-5 UUID's work)
xorriso="xorriso
+ -boot_image any gpt_disk_guid=$(uuid -v 5 daed2280-b91e-42c0-aed6-82c825ca41f3 $out | tr -d -)
-as mkisofs
-iso-level 3
-volid ${volumeID}
@@ -118,20 +123,16 @@ xorriso="xorriso
$xorriso -output $out/iso/$isoName
-if test -n "$usbBootable"; then
- echo "Making image hybrid..."
- if test -n "$efiBootable"; then
- isohybrid --uefi $out/iso/$isoName
- else
- isohybrid $out/iso/$isoName
- fi
-fi
-
if test -n "$compressImage"; then
echo "Compressing image..."
- bzip2 $out/iso/$isoName
+ zstd -T$NIX_BUILD_CORES --rm $out/iso/$isoName
fi
mkdir -p $out/nix-support
echo $system > $out/nix-support/system
-echo "file iso $out/iso/$isoName" >> $out/nix-support/hydra-build-products
+
+if test -n "$compressImage"; then
+ echo "file iso $out/iso/$isoName.zst" >> $out/nix-support/hydra-build-products
+else
+ echo "file iso $out/iso/$isoName" >> $out/nix-support/hydra-build-products
+fi
diff --git a/nixpkgs/nixos/lib/make-options-doc/default.nix b/nixpkgs/nixos/lib/make-options-doc/default.nix
index 772b7d3add9..a1161621f0d 100644
--- a/nixpkgs/nixos/lib/make-options-doc/default.nix
+++ b/nixpkgs/nixos/lib/make-options-doc/default.nix
@@ -36,7 +36,7 @@ let
// lib.optionalAttrs (opt ? example) { example = substFunction opt.example; }
// lib.optionalAttrs (opt ? default) { default = substFunction opt.default; }
// lib.optionalAttrs (opt ? type) { type = substFunction opt.type; }
- // lib.optionalAttrs (opt ? relatedPackages && opt.relatedPackages != []) { relatedPackages = genRelatedPackages opt.relatedPackages; }
+ // lib.optionalAttrs (opt ? relatedPackages && opt.relatedPackages != []) { relatedPackages = genRelatedPackages opt.relatedPackages opt.name; }
);
# Generate DocBook documentation for a list of packages. This is
@@ -48,7 +48,7 @@ let
# - a list: that will be interpreted as an attribute path from `pkgs`,
# - an attrset: that can specify `name`, `path`, `package`, `comment`
# (either of `name`, `path` is required, the rest are optional).
- genRelatedPackages = packages:
+ genRelatedPackages = packages: optName:
let
unpack = p: if lib.isString p then { name = p; }
else if lib.isList p then { path = p; }
@@ -58,7 +58,7 @@ let
title = args.title or null;
name = args.name or (lib.concatStringsSep "." args.path);
path = args.path or [ args.name ];
- package = args.package or (lib.attrByPath path (throw "Invalid package attribute path `${toString path}'") pkgs);
+ package = args.package or (lib.attrByPath path (throw "Invalid package attribute path `${toString path}' found while evaluating `relatedPackages' of option `${optName}'") pkgs);
in "<listitem>"
+ "<para><literal>${lib.optionalString (title != null) "${title} aka "}pkgs.${name} (${package.meta.name})</literal>"
+ lib.optionalString (!package.meta.available) " <emphasis>[UNAVAILABLE]</emphasis>"
diff --git a/nixpkgs/nixos/lib/qemu-flags.nix b/nixpkgs/nixos/lib/qemu-flags.nix
index 859d9e975fe..0cf6977af4b 100644
--- a/nixpkgs/nixos/lib/qemu-flags.nix
+++ b/nixpkgs/nixos/lib/qemu-flags.nix
@@ -2,13 +2,18 @@
{ pkgs }:
let
- zeroPad = n: if n < 10 then "0${toString n}" else toString n;
+ zeroPad = n:
+ pkgs.lib.optionalString (n < 16) "0" +
+ (if n > 255
+ then throw "Can't have more than 255 nets or nodes!"
+ else pkgs.lib.toHexString n);
in
-{
+rec {
+ qemuNicMac = net: machine: "52:54:00:12:${zeroPad net}:${zeroPad machine}";
qemuNICFlags = nic: net: machine:
- [ "-device virtio-net-pci,netdev=vlan${toString nic},mac=52:54:00:12:${zeroPad net}:${zeroPad machine}"
+ [ "-device virtio-net-pci,netdev=vlan${toString nic},mac=${qemuNicMac net machine}"
"-netdev vde,id=vlan${toString nic},sock=$QEMU_VDE_SOCKET_${toString net}"
];
diff --git a/nixpkgs/nixos/lib/test-driver/Logger.pm b/nixpkgs/nixos/lib/test-driver/Logger.pm
index 080310ea34e..a3384084a0e 100644
--- a/nixpkgs/nixos/lib/test-driver/Logger.pm
+++ b/nixpkgs/nixos/lib/test-driver/Logger.pm
@@ -8,17 +8,17 @@ use Time::HiRes qw(clock_gettime CLOCK_MONOTONIC);
sub new {
my ($class) = @_;
-
+
my $logFile = defined $ENV{LOGFILE} ? "$ENV{LOGFILE}" : "/dev/null";
my $log = new XML::Writer(OUTPUT => new IO::File(">$logFile"));
-
+
my $self = {
log => $log,
logQueue => Thread::Queue->new()
};
-
+
$self->{log}->startTag("logfile");
-
+
bless $self, $class;
return $self;
}
diff --git a/nixpkgs/nixos/lib/test-driver/test-driver.py b/nixpkgs/nixos/lib/test-driver/test-driver.py
index e7b05968b07..7b8d5803aa5 100644
--- a/nixpkgs/nixos/lib/test-driver/test-driver.py
+++ b/nixpkgs/nixos/lib/test-driver/test-driver.py
@@ -3,7 +3,10 @@ from contextlib import contextmanager, _GeneratorContextManager
from queue import Queue, Empty
from typing import Tuple, Any, Callable, Dict, Iterator, Optional, List
from xml.sax.saxutils import XMLGenerator
+import queue
+import io
import _thread
+import argparse
import atexit
import base64
import codecs
@@ -19,6 +22,7 @@ import subprocess
import sys
import tempfile
import time
+import traceback
import unicodedata
CHAR_TO_KEY = {
@@ -671,6 +675,22 @@ class Machine:
with self.nested("waiting for {} to appear on screen".format(regex)):
retry(screen_matches)
+ def wait_for_console_text(self, regex: str) -> None:
+ self.log("waiting for {} to appear on console".format(regex))
+ # Buffer the console output, this is needed
+ # to match multiline regexes.
+ console = io.StringIO()
+ while True:
+ try:
+ console.write(self.last_lines.get())
+ except queue.Empty:
+ self.sleep(1)
+ continue
+ console.seek(0)
+ matches = re.search(regex, console.read())
+ if matches is not None:
+ return
+
def send_key(self, key: str) -> None:
key = CHAR_TO_KEY.get(key, key)
self.send_monitor_command("sendkey {}".format(key))
@@ -734,11 +754,16 @@ class Machine:
self.monitor, _ = self.monitor_socket.accept()
self.shell, _ = self.shell_socket.accept()
+ # Store last serial console lines for use
+ # of wait_for_console_text
+ self.last_lines: Queue = Queue()
+
def process_serial_output() -> None:
assert self.process.stdout is not None
for _line in self.process.stdout:
# Ignore undecodable bytes that may occur in boot menus
line = _line.decode(errors="ignore").replace("\r", "").rstrip()
+ self.last_lines.put(line)
eprint("{} # {}".format(self.name, line))
self.logger.enqueue({"msg": line, "machine": self.name})
@@ -751,6 +776,11 @@ class Machine:
self.log("QEMU running (pid {})".format(self.pid))
+ def cleanup_statedir(self) -> None:
+ self.log("delete the VM state directory")
+ if os.path.isfile(self.state_dir):
+ shutil.rmtree(self.state_dir)
+
def shutdown(self) -> None:
if not self.booted:
return
@@ -863,7 +893,8 @@ def run_tests() -> None:
try:
exec(tests, globals())
except Exception as e:
- eprint("error: {}".format(str(e)))
+ eprint("error: ")
+ traceback.print_exc()
sys.exit(1)
else:
ptpython.repl.embed(locals(), globals())
@@ -889,6 +920,15 @@ def subtest(name: str) -> Iterator[None]:
if __name__ == "__main__":
+ arg_parser = argparse.ArgumentParser()
+ arg_parser.add_argument(
+ "-K",
+ "--keep-vm-state",
+ help="re-use a VM state coming from a previous run",
+ action="store_true",
+ )
+ (cli_args, vm_scripts) = arg_parser.parse_known_args()
+
log = Logger()
vlan_nrs = list(dict.fromkeys(os.environ.get("VLANS", "").split()))
@@ -896,8 +936,10 @@ if __name__ == "__main__":
for nr, vde_socket, _, _ in vde_sockets:
os.environ["QEMU_VDE_SOCKET_{}".format(nr)] = vde_socket
- vm_scripts = sys.argv[1:]
machines = [create_machine({"startCommand": s}) for s in vm_scripts]
+ for machine in machines:
+ if not cli_args.keep_vm_state:
+ machine.cleanup_statedir()
machine_eval = [
"{0} = machines[{1}]".format(m.name, idx) for idx, m in enumerate(machines)
]
@@ -911,7 +953,6 @@ if __name__ == "__main__":
continue
log.log("killing {} (pid {})".format(machine.name, machine.pid))
machine.process.kill()
-
for _, _, process, _ in vde_sockets:
process.terminate()
log.close()
diff --git a/nixpkgs/nixos/lib/testing-python.nix b/nixpkgs/nixos/lib/testing-python.nix
index 123323711a7..c6939c7d698 100644
--- a/nixpkgs/nixos/lib/testing-python.nix
+++ b/nixpkgs/nixos/lib/testing-python.nix
@@ -114,7 +114,7 @@ rec {
imagemagick_tiff = imagemagick_light.override { inherit libtiff; };
- # Generate onvenience wrappers for running the test driver
+ # Generate convenience wrappers for running the test driver
# interactively with the specified network, and for starting the
# VMs from the command line.
driver = let warn = if skipLint then lib.warn "Linting is disabled!" else lib.id; in warn (runCommand testDriverName
diff --git a/nixpkgs/nixos/lib/utils.nix b/nixpkgs/nixos/lib/utils.nix
index 21f4c7c6988..543c8a8882e 100644
--- a/nixpkgs/nixos/lib/utils.nix
+++ b/nixpkgs/nixos/lib/utils.nix
@@ -2,9 +2,11 @@ pkgs: with pkgs.lib;
rec {
- # Check whenever fileSystem is needed for boot
- fsNeededForBoot = fs: fs.neededForBoot
- || elem fs.mountPoint [ "/" "/nix" "/nix/store" "/var" "/var/log" "/var/lib" "/etc" ];
+ # Check whenever fileSystem is needed for boot. NOTE: Make sure
+ # pathsNeededForBoot is closed under the parent relationship, i.e. if /a/b/c
+ # is in the list, put /a and /a/b in as well.
+ pathsNeededForBoot = [ "/" "/nix" "/nix/store" "/var" "/var/log" "/var/lib" "/etc" ];
+ fsNeededForBoot = fs: fs.neededForBoot || elem fs.mountPoint pathsNeededForBoot;
# Check whenever `b` depends on `a` as a fileSystem
fsBefore = a: b: a.mountPoint == b.device
diff --git a/nixpkgs/nixos/maintainers/scripts/azure-new/.gitignore b/nixpkgs/nixos/maintainers/scripts/azure-new/.gitignore
index 26905a86234..9271abf14a0 100644
--- a/nixpkgs/nixos/maintainers/scripts/azure-new/.gitignore
+++ b/nixpkgs/nixos/maintainers/scripts/azure-new/.gitignore
@@ -1 +1 @@
-azure \ No newline at end of file
+azure
diff --git a/nixpkgs/nixos/maintainers/scripts/azure-new/README.md b/nixpkgs/nixos/maintainers/scripts/azure-new/README.md
index 20e81c44ce5..e5b69dacec0 100644
--- a/nixpkgs/nixos/maintainers/scripts/azure-new/README.md
+++ b/nixpkgs/nixos/maintainers/scripts/azure-new/README.md
@@ -20,7 +20,7 @@ $ ./upload-image.sh ./examples/basic/image.nix
+ nix-build ./examples/basic/image.nix --out-link azure
/nix/store/qdpzknpskzw30vba92mb24xzll1dqsmd-azure-image
...
-95.5 %, 0 Done, 0 Failed, 1 Pending, 0 Skipped, 1 Total, 2-sec Throughput (Mb/s): 932.9565
+95.5 %, 0 Done, 0 Failed, 1 Pending, 0 Skipped, 1 Total, 2-sec Throughput (Mb/s): 932.9565
...
/subscriptions/aff271ee-e9be-4441-b9bb-42f5af4cbaeb/resourceGroups/nixos-images/providers/Microsoft.Compute/images/azure-image-todo-makethisbetter
```
diff --git a/nixpkgs/nixos/maintainers/scripts/azure-new/upload-image.sh b/nixpkgs/nixos/maintainers/scripts/azure-new/upload-image.sh
index 1466dcd1f0a..143afbd7f96 100755
--- a/nixpkgs/nixos/maintainers/scripts/azure-new/upload-image.sh
+++ b/nixpkgs/nixos/maintainers/scripts/azure-new/upload-image.sh
@@ -37,8 +37,8 @@ if ! az disk show -g "${group}" -n "${img_name}" &>/dev/null; then
)"
azcopy copy "${img_file}" "${sasurl}" \
- --blob-type PageBlob
-
+ --blob-type PageBlob
+
az disk revoke-access \
--resource-group "${group}" \
--name "${img_name}"
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";
diff --git a/nixpkgs/nixos/release.nix b/nixpkgs/nixos/release.nix
index cf16986b213..1f5c1581269 100644
--- a/nixpkgs/nixos/release.nix
+++ b/nixpkgs/nixos/release.nix
@@ -310,6 +310,11 @@ in rec {
services.xserver.desktopManager.gnome3.enable = true;
});
+ pantheon = makeClosure ({ ... }:
+ { services.xserver.enable = true;
+ services.xserver.desktopManager.pantheon.enable = true;
+ });
+
# Linux/Apache/PostgreSQL/PHP stack.
lapp = makeClosure ({ pkgs, ... }:
{ services.httpd.enable = true;
diff --git a/nixpkgs/nixos/tests/acme.nix b/nixpkgs/nixos/tests/acme.nix
index fc41dc1eb5f..a8188473721 100644
--- a/nixpkgs/nixos/tests/acme.nix
+++ b/nixpkgs/nixos/tests/acme.nix
@@ -48,10 +48,9 @@ in import ./make-test-python.nix ({ lib, ... }: {
security.acme.certs."standalone.test" = {
webroot = "/var/lib/acme/acme-challenges";
};
- systemd.targets."acme-finished-standalone.test" = {};
- systemd.services."acme-standalone.test" = {
- wants = [ "acme-finished-standalone.test.target" ];
- before = [ "acme-finished-standalone.test.target" ];
+ systemd.targets."acme-finished-standalone.test" = {
+ after = [ "acme-standalone.test.service" ];
+ wantedBy = [ "acme-standalone.test.service" ];
};
services.nginx.enable = true;
services.nginx.virtualHosts."standalone.test" = {
@@ -68,11 +67,9 @@ in import ./make-test-python.nix ({ lib, ... }: {
# A target remains active. Use this to probe the fact that
# a service fired eventhough it is not RemainAfterExit
- systemd.targets."acme-finished-a.example.test" = {};
- systemd.services."acme-a.example.test" = {
- wants = [ "acme-finished-a.example.test.target" ];
- before = [ "acme-finished-a.example.test.target" ];
- after = [ "nginx.service" ];
+ systemd.targets."acme-finished-a.example.test" = {
+ after = [ "acme-a.example.test.service" ];
+ wantedBy = [ "acme-a.example.test.service" ];
};
services.nginx.enable = true;
@@ -89,11 +86,9 @@ in import ./make-test-python.nix ({ lib, ... }: {
security.acme.server = "https://acme.test/dir";
specialisation.second-cert.configuration = {pkgs, ...}: {
- systemd.targets."acme-finished-b.example.test" = {};
- systemd.services."acme-b.example.test" = {
- wants = [ "acme-finished-b.example.test.target" ];
- before = [ "acme-finished-b.example.test.target" ];
- after = [ "nginx.service" ];
+ systemd.targets."acme-finished-b.example.test" = {
+ after = [ "acme-b.example.test.service" ];
+ wantedBy = [ "acme-b.example.test.service" ];
};
services.nginx.virtualHosts."b.example.test" = {
enableACME = true;
@@ -104,6 +99,7 @@ in import ./make-test-python.nix ({ lib, ... }: {
'';
};
};
+
specialisation.dns-01.configuration = {pkgs, config, nodes, lib, ...}: {
security.acme.certs."example.test" = {
domain = "*.example.test";
@@ -115,10 +111,12 @@ in import ./make-test-python.nix ({ lib, ... }: {
user = config.services.nginx.user;
group = config.services.nginx.group;
};
- systemd.targets."acme-finished-example.test" = {};
+ systemd.targets."acme-finished-example.test" = {
+ after = [ "acme-example.test.service" ];
+ wantedBy = [ "acme-example.test.service" ];
+ };
systemd.services."acme-example.test" = {
- wants = [ "acme-finished-example.test.target" ];
- before = [ "acme-finished-example.test.target" "nginx.service" ];
+ before = [ "nginx.service" ];
wantedBy = [ "nginx.service" ];
};
services.nginx.virtualHosts."c.example.test" = {
@@ -132,6 +130,26 @@ in import ./make-test-python.nix ({ lib, ... }: {
'';
};
};
+
+ # When nginx depends on a service that is slow to start up, requesting used to fail
+ # certificates fail. Reproducer for https://github.com/NixOS/nixpkgs/issues/81842
+ specialisation.slow-startup.configuration = { pkgs, config, nodes, lib, ...}: {
+ systemd.services.my-slow-service = {
+ wantedBy = [ "multi-user.target" "nginx.service" ];
+ before = [ "nginx.service" ];
+ preStart = "sleep 5";
+ script = "${pkgs.python3}/bin/python -m http.server";
+ };
+ systemd.targets."acme-finished-d.example.com" = {
+ after = [ "acme-d.example.com.service" ];
+ wantedBy = [ "acme-d.example.com.service" ];
+ };
+ services.nginx.virtualHosts."d.example.com" = {
+ forceSSL = true;
+ enableACME = true;
+ locations."/".proxyPass = "http://localhost:8000";
+ };
+ };
};
client = {nodes, lib, ...}: {
@@ -207,5 +225,15 @@ in import ./make-test-python.nix ({ lib, ... }: {
client.succeed(
"curl --cacert /tmp/ca.crt https://c.example.test/ | grep -qF 'hello world'"
)
+
+ with subtest("Can request certificate of nginx when startup is delayed"):
+ webserver.succeed(
+ "${switchToNewServer}"
+ )
+ webserver.succeed(
+ "/run/current-system/specialisation/slow-startup/bin/switch-to-configuration test"
+ )
+ webserver.wait_for_unit("acme-finished-d.example.com.target")
+ client.succeed("curl --cacert /tmp/ca.crt https://d.example.com/")
'';
})
diff --git a/nixpkgs/nixos/tests/all-tests.nix b/nixpkgs/nixos/tests/all-tests.nix
index 796c626f3dd..31dad3be814 100644
--- a/nixpkgs/nixos/tests/all-tests.nix
+++ b/nixpkgs/nixos/tests/all-tests.nix
@@ -32,7 +32,9 @@ in
beanstalkd = handleTest ./beanstalkd.nix {};
bees = handleTest ./bees.nix {};
bind = handleTest ./bind.nix {};
+ bitcoind = handleTest ./bitcoind.nix {};
bittorrent = handleTest ./bittorrent.nix {};
+ blockbook-frontend = handleTest ./blockbook-frontend.nix {};
buildkite-agents = handleTest ./buildkite-agents.nix {};
boot = handleTestOn ["x86_64-linux"] ./boot.nix {}; # syslinux is unsupported on aarch64
boot-stage1 = handleTest ./boot-stage1.nix {};
@@ -65,6 +67,7 @@ in
containers-portforward = handleTest ./containers-portforward.nix {};
containers-restart_networking = handleTest ./containers-restart_networking.nix {};
containers-tmpfs = handleTest ./containers-tmpfs.nix {};
+ convos = handleTest ./convos.nix {};
corerad = handleTest ./corerad.nix {};
couchdb = handleTest ./couchdb.nix {};
deluge = handleTest ./deluge.nix {};
@@ -119,10 +122,12 @@ in
installed-tests = pkgs.recurseIntoAttrs (handleTest ./installed-tests {});
gocd-agent = handleTest ./gocd-agent.nix {};
gocd-server = handleTest ./gocd-server.nix {};
+ go-neb = handleTest ./go-neb.nix {};
google-oslogin = handleTest ./google-oslogin {};
grafana = handleTest ./grafana.nix {};
graphite = handleTest ./graphite.nix {};
graylog = handleTest ./graylog.nix {};
+ grub = handleTest ./grub.nix {};
gvisor = handleTest ./gvisor.nix {};
hadoop.hdfs = handleTestOn [ "x86_64-linux" ] ./hadoop/hdfs.nix {};
hadoop.yarn = handleTestOn [ "x86_64-linux" ] ./hadoop/yarn.nix {};
@@ -147,6 +152,7 @@ in
incron = handleTest ./incron.nix {};
influxdb = handleTest ./influxdb.nix {};
initrd-network-ssh = handleTest ./initrd-network-ssh {};
+ initrd-network-openvpn = handleTest ./initrd-network-openvpn {};
initrdNetwork = handleTest ./initrd-network.nix {};
installer = handleTest ./installer.nix {};
iodine = handleTest ./iodine.nix {};
@@ -156,6 +162,7 @@ in
jellyfin = handleTest ./jellyfin.nix {};
jenkins = handleTest ./jenkins.nix {};
jirafeau = handleTest ./jirafeau.nix {};
+ jitsi-meet = handleTest ./jitsi-meet.nix {};
k3s = handleTest ./k3s.nix {};
kafka = handleTest ./kafka.nix {};
keepalived = handleTest ./keepalived.nix {};
@@ -178,6 +185,8 @@ in
limesurvey = handleTest ./limesurvey.nix {};
login = handleTest ./login.nix {};
loki = handleTest ./loki.nix {};
+ lxd = handleTest ./lxd.nix {};
+ lxd-nftables = handleTest ./lxd-nftables.nix {};
#logstash = handleTest ./logstash.nix {};
lorri = handleTest ./lorri/default.nix {};
magnetico = handleTest ./magnetico.nix {};
@@ -214,6 +223,7 @@ in
nat.firewall = handleTest ./nat.nix { withFirewall = true; };
nat.firewall-conntrack = handleTest ./nat.nix { withFirewall = true; withConntrackHelpers = true; };
nat.standalone = handleTest ./nat.nix { withFirewall = false; };
+ ncdns = handleTest ./ncdns.nix {};
ndppd = handleTest ./ndppd.nix {};
neo4j = handleTest ./neo4j.nix {};
specialisation = handleTest ./specialisation.nix {};
@@ -233,6 +243,7 @@ in
nginx-pubhtml = handleTest ./nginx-pubhtml.nix {};
nginx-sandbox = handleTestOn ["x86_64-linux"] ./nginx-sandbox.nix {};
nginx-sso = handleTest ./nginx-sso.nix {};
+ nginx-variants = handleTest ./nginx-variants.nix {};
nix-ssh-serve = handleTest ./nix-ssh-serve.nix {};
nixos-generate-config = handleTest ./nixos-generate-config.nix {};
novacomd = handleTestOn ["x86_64-linux"] ./novacomd.nix {};
@@ -259,7 +270,9 @@ in
php = handleTest ./php {};
plasma5 = handleTest ./plasma5.nix {};
plotinus = handleTest ./plotinus.nix {};
- podman = handleTest ./podman.nix {};
+ podman = handleTestOn ["x86_64-linux"] ./podman.nix {};
+ postfix = handleTest ./postfix.nix {};
+ postfix-raise-smtpd-tls-security-level = handleTest ./postfix-raise-smtpd-tls-security-level.nix {};
postgis = handleTest ./postgis.nix {};
postgresql = handleTest ./postgresql.nix {};
postgresql-wal-receiver = handleTest ./postgresql-wal-receiver.nix {};
@@ -273,6 +286,8 @@ in
prosody = handleTest ./xmpp/prosody.nix {};
prosodyMysql = handleTest ./xmpp/prosody-mysql.nix {};
proxy = handleTest ./proxy.nix {};
+ pt2-clone = handleTest ./pt2-clone.nix {};
+ qboot = handleTestOn ["x86_64-linux" "i686-linux"] ./qboot.nix {};
quagga = handleTest ./quagga.nix {};
quorum = handleTest ./quorum.nix {};
rabbitmq = handleTest ./rabbitmq.nix {};
@@ -296,22 +311,25 @@ in
simple = handleTest ./simple.nix {};
slurm = handleTest ./slurm.nix {};
smokeping = handleTest ./smokeping.nix {};
+ snapcast = handleTest ./snapcast.nix {};
snapper = handleTest ./snapper.nix {};
sogo = handleTest ./sogo.nix {};
solr = handleTest ./solr.nix {};
spacecookie = handleTest ./spacecookie.nix {};
spike = handleTest ./spike.nix {};
sonarr = handleTest ./sonarr.nix {};
+ sslh = handleTest ./sslh.nix {};
strongswan-swanctl = handleTest ./strongswan-swanctl.nix {};
sudo = handleTest ./sudo.nix {};
switchTest = handleTest ./switch-test.nix {};
sympa = handleTest ./sympa.nix {};
+ syncthing = handleTest ./syncthing.nix {};
syncthing-init = handleTest ./syncthing-init.nix {};
syncthing-relay = handleTest ./syncthing-relay.nix {};
systemd = handleTest ./systemd.nix {};
systemd-analyze = handleTest ./systemd-analyze.nix {};
systemd-binfmt = handleTestOn ["x86_64-linux"] ./systemd-binfmt.nix {};
- systemd-boot = handleTestOn ["x86_64-linux"] ./systemd-boot.nix {};
+ systemd-boot = handleTest ./systemd-boot.nix {};
systemd-confinement = handleTest ./systemd-confinement.nix {};
systemd-timesyncd = handleTest ./systemd-timesyncd.nix {};
systemd-networkd-vrf = handleTest ./systemd-networkd-vrf.nix {};
@@ -341,6 +359,7 @@ in
vault = handleTest ./vault.nix {};
victoriametrics = handleTest ./victoriametrics.nix {};
virtualbox = handleTestOn ["x86_64-linux"] ./virtualbox.nix {};
+ wasabibackend = handleTest ./wasabibackend.nix {};
wireguard = handleTest ./wireguard {};
wordpress = handleTest ./wordpress.nix {};
xandikos = handleTest ./xandikos.nix {};
@@ -352,6 +371,7 @@ in
yabar = handleTest ./yabar.nix {};
yggdrasil = handleTest ./yggdrasil.nix {};
zfs = handleTest ./zfs.nix {};
+ zigbee2mqtt = handleTest ./zigbee2mqtt.nix {};
zoneminder = handleTest ./zoneminder.nix {};
zookeeper = handleTest ./zookeeper.nix {};
zsh-history = handleTest ./zsh-history.nix {};
diff --git a/nixpkgs/nixos/tests/bcachefs.nix b/nixpkgs/nixos/tests/bcachefs.nix
index 0541e580322..3f116d7df92 100644
--- a/nixpkgs/nixos/tests/bcachefs.nix
+++ b/nixpkgs/nixos/tests/bcachefs.nix
@@ -13,7 +13,7 @@ import ./make-test-python.nix ({ pkgs, ... }: {
machine.succeed("modprobe bcachefs")
machine.succeed("bcachefs version")
machine.succeed("ls /dev")
-
+
machine.succeed(
"mkdir /tmp/mnt",
"udevadm settle",
diff --git a/nixpkgs/nixos/tests/bitcoind.nix b/nixpkgs/nixos/tests/bitcoind.nix
new file mode 100644
index 00000000000..95c6a5b91bc
--- /dev/null
+++ b/nixpkgs/nixos/tests/bitcoind.nix
@@ -0,0 +1,46 @@
+import ./make-test-python.nix ({ pkgs, ... }: {
+ name = "bitcoind";
+ meta = with pkgs.stdenv.lib; {
+ maintainers = with maintainers; [ maintainers."1000101" ];
+ };
+
+ machine = { ... }: {
+ services.bitcoind."mainnet" = {
+ enable = true;
+ rpc = {
+ port = 8332;
+ users.rpc.passwordHMAC = "acc2374e5f9ba9e62a5204d3686616cf$53abdba5e67a9005be6a27ca03a93ce09e58854bc2b871523a0d239a72968033";
+ users.rpc2.passwordHMAC = "1495e4a3ad108187576c68f7f9b5ddc5$accce0881c74aa01bb8960ff3bdbd39f607fd33178147679e055a4ac35f53225";
+ };
+ };
+ services.bitcoind."testnet" = {
+ enable = true;
+ configFile = "/test.blank";
+ testnet = true;
+ rpc = {
+ port = 18332;
+ };
+ extraCmdlineOptions = [ "-rpcuser=rpc" "-rpcpassword=rpc" "-rpcauth=rpc2:1495e4a3ad108187576c68f7f9b5ddc5$accce0881c74aa01bb8960ff3bdbd39f607fd33178147679e055a4ac35f53225" ];
+ };
+ };
+
+ testScript = ''
+ start_all()
+
+ machine.wait_for_unit("bitcoind-mainnet.service")
+ machine.wait_for_unit("bitcoind-testnet.service")
+
+ machine.wait_until_succeeds(
+ 'curl --user rpc:rpc --data-binary \'{"jsonrpc": "1.0", "id":"curltest", "method": "getblockchaininfo", "params": [] }\' -H \'content-type: text/plain;\' localhost:8332 | grep \'"chain":"main"\' '
+ )
+ machine.wait_until_succeeds(
+ 'curl --user rpc2:rpc2 --data-binary \'{"jsonrpc": "1.0", "id":"curltest", "method": "getblockchaininfo", "params": [] }\' -H \'content-type: text/plain;\' localhost:8332 | grep \'"chain":"main"\' '
+ )
+ machine.wait_until_succeeds(
+ 'curl --user rpc:rpc --data-binary \'{"jsonrpc": "1.0", "id":"curltest", "method": "getblockchaininfo", "params": [] }\' -H \'content-type: text/plain;\' localhost:18332 | grep \'"chain":"test"\' '
+ )
+ machine.wait_until_succeeds(
+ 'curl --user rpc2:rpc2 --data-binary \'{"jsonrpc": "1.0", "id":"curltest", "method": "getblockchaininfo", "params": [] }\' -H \'content-type: text/plain;\' localhost:18332 | grep \'"chain":"test"\' '
+ )
+ '';
+})
diff --git a/nixpkgs/nixos/tests/blockbook-frontend.nix b/nixpkgs/nixos/tests/blockbook-frontend.nix
new file mode 100644
index 00000000000..5fbfc6c30c1
--- /dev/null
+++ b/nixpkgs/nixos/tests/blockbook-frontend.nix
@@ -0,0 +1,28 @@
+import ./make-test-python.nix ({ pkgs, ... }: {
+ name = "blockbook-frontend";
+ meta = with pkgs.stdenv.lib; {
+ maintainers = with maintainers; [ maintainers."1000101" ];
+ };
+
+ machine = { ... }: {
+ services.blockbook-frontend."test" = {
+ enable = true;
+ };
+ services.bitcoind.mainnet = {
+ enable = true;
+ rpc = {
+ port = 8030;
+ users.rpc.passwordHMAC = "acc2374e5f9ba9e62a5204d3686616cf$53abdba5e67a9005be6a27ca03a93ce09e58854bc2b871523a0d239a72968033";
+ };
+ };
+ };
+
+ testScript = ''
+ start_all()
+ machine.wait_for_unit("blockbook-frontend-test.service")
+
+ machine.wait_for_open_port(9030)
+
+ machine.succeed("curl -sSfL http://localhost:9030 | grep 'Blockbook'")
+ '';
+})
diff --git a/nixpkgs/nixos/tests/borgbackup.nix b/nixpkgs/nixos/tests/borgbackup.nix
index d97471e293e..bf37eb8607b 100644
--- a/nixpkgs/nixos/tests/borgbackup.nix
+++ b/nixpkgs/nixos/tests/borgbackup.nix
@@ -43,7 +43,7 @@ in {
nodes = {
client = { ... }: {
services.borgbackup.jobs = {
-
+
local = {
paths = dataDir;
repo = localRepo;
diff --git a/nixpkgs/nixos/tests/ceph-multi-node.nix b/nixpkgs/nixos/tests/ceph-multi-node.nix
index 22fe5cada48..e26c6d5d670 100644
--- a/nixpkgs/nixos/tests/ceph-multi-node.nix
+++ b/nixpkgs/nixos/tests/ceph-multi-node.nix
@@ -183,15 +183,15 @@ let
monA.wait_until_succeeds("ceph -s | grep 'HEALTH_OK'")
monA.succeed(
- "ceph osd pool create multi-node-test 128 128",
+ "ceph osd pool create multi-node-test 32 32",
"ceph osd pool ls | grep 'multi-node-test'",
"ceph osd pool rename multi-node-test multi-node-other-test",
"ceph osd pool ls | grep 'multi-node-other-test'",
)
- monA.wait_until_succeeds("ceph -s | grep '1 pools, 128 pgs'")
+ monA.wait_until_succeeds("ceph -s | grep '2 pools, 33 pgs'")
monA.succeed("ceph osd pool set multi-node-other-test size 2")
monA.wait_until_succeeds("ceph -s | grep 'HEALTH_OK'")
- monA.wait_until_succeeds("ceph -s | grep '128 active+clean'")
+ monA.wait_until_succeeds("ceph -s | grep '33 active+clean'")
monA.fail(
"ceph osd pool ls | grep 'multi-node-test'",
"ceph osd pool delete multi-node-other-test multi-node-other-test --yes-i-really-really-mean-it",
diff --git a/nixpkgs/nixos/tests/ceph-single-node.nix b/nixpkgs/nixos/tests/ceph-single-node.nix
index 01c4b413845..98528f6317b 100644
--- a/nixpkgs/nixos/tests/ceph-single-node.nix
+++ b/nixpkgs/nixos/tests/ceph-single-node.nix
@@ -143,12 +143,12 @@ let
monA.wait_until_succeeds("ceph -s | grep 'HEALTH_OK'")
monA.succeed(
- "ceph osd pool create single-node-test 128 128",
+ "ceph osd pool create single-node-test 32 32",
"ceph osd pool ls | grep 'single-node-test'",
"ceph osd pool rename single-node-test single-node-other-test",
"ceph osd pool ls | grep 'single-node-other-test'",
)
- monA.wait_until_succeeds("ceph -s | grep '1 pools, 128 pgs'")
+ monA.wait_until_succeeds("ceph -s | grep '2 pools, 33 pgs'")
monA.succeed(
"ceph osd getcrushmap -o crush",
"crushtool -d crush -o decrushed",
@@ -158,7 +158,7 @@ let
"ceph osd pool set single-node-other-test size 2",
)
monA.wait_until_succeeds("ceph -s | grep 'HEALTH_OK'")
- monA.wait_until_succeeds("ceph -s | grep '128 active+clean'")
+ monA.wait_until_succeeds("ceph -s | grep '33 active+clean'")
monA.fail(
"ceph osd pool ls | grep 'multi-node-test'",
"ceph osd pool delete single-node-other-test single-node-other-test --yes-i-really-really-mean-it",
diff --git a/nixpkgs/nixos/tests/common/auto.nix b/nixpkgs/nixos/tests/common/auto.nix
index 2c21a8d5167..da6b14e9f16 100644
--- a/nixpkgs/nixos/tests/common/auto.nix
+++ b/nixpkgs/nixos/tests/common/auto.nix
@@ -41,8 +41,8 @@ in
config = mkIf cfg.enable {
- services.xserver.displayManager.lightdm = {
- enable = true;
+ services.xserver.displayManager = {
+ lightdm.enable = true;
autoLogin = {
enable = true;
user = cfg.user;
diff --git a/nixpkgs/nixos/tests/consul.nix b/nixpkgs/nixos/tests/consul.nix
index 6600dae4770..ee85f1d0b91 100644
--- a/nixpkgs/nixos/tests/consul.nix
+++ b/nixpkgs/nixos/tests/consul.nix
@@ -55,30 +55,33 @@ let
server = index: { pkgs, ... }:
let
- ip = builtins.elemAt allConsensusServerHosts index;
+ numConsensusServers = builtins.length allConsensusServerHosts;
+ thisConsensusServerHost = builtins.elemAt allConsensusServerHosts index;
+ ip = thisConsensusServerHost; # since we already use IPs to identify servers
in
{
networking.interfaces.eth1.ipv4.addresses = pkgs.lib.mkOverride 0 [
- { address = builtins.elemAt allConsensusServerHosts index; prefixLength = 16; }
+ { address = ip; prefixLength = 16; }
];
networking.firewall = firewallSettings;
services.consul =
- let
- thisConsensusServerHost = builtins.elemAt allConsensusServerHosts index;
- in
assert builtins.elem thisConsensusServerHost allConsensusServerHosts;
{
enable = true;
inherit webUi;
extraConfig = defaultExtraConfig // {
server = true;
- bootstrap_expect = builtins.length allConsensusServerHosts;
+ bootstrap_expect = numConsensusServers;
+ # Tell Consul that we never intend to drop below this many servers.
+ # Ensures to not permanently lose consensus after temporary loss.
+ # See https://github.com/hashicorp/consul/issues/8118#issuecomment-645330040
+ autopilot.min_quorum = numConsensusServers;
retry_join =
# If there's only 1 node in the network, we allow self-join;
# otherwise, the node must not try to join itself, and join only the other servers.
# See https://github.com/hashicorp/consul/issues/2868
- if builtins.length allConsensusServerHosts == 1
+ if numConsensusServers == 1
then allConsensusServerHosts
else builtins.filter (h: h != thisConsensusServerHost) allConsensusServerHosts;
bind_addr = ip;
@@ -104,40 +107,123 @@ in {
for m in machines:
m.wait_for_unit("consul.service")
- for m in machines:
- m.wait_until_succeeds("[ $(consul members | grep -o alive | wc -l) == 5 ]")
+
+ def wait_for_healthy_servers():
+ # See https://github.com/hashicorp/consul/issues/8118#issuecomment-645330040
+ # for why the `Voter` column of `list-peers` has that info.
+ # TODO: The `grep true` relies on the fact that currently in
+ # the output like
+ # # consul operator raft list-peers
+ # Node ID Address State Voter RaftProtocol
+ # server3 ... 192.168.1.3:8300 leader true 3
+ # server2 ... 192.168.1.2:8300 follower true 3
+ # server1 ... 192.168.1.1:8300 follower false 3
+ # `Voter`is the only boolean column.
+ # Change this to the more reliable way to be defined by
+ # https://github.com/hashicorp/consul/issues/8118
+ # once that ticket is closed.
+ for m in machines:
+ m.wait_until_succeeds(
+ "[ $(consul operator raft list-peers | grep true | wc -l) == 3 ]"
+ )
+
+
+ def wait_for_all_machines_alive():
+ """
+ Note that Serf-"alive" does not mean "Raft"-healthy;
+ see `wait_for_healthy_servers()` for that instead.
+ """
+ for m in machines:
+ m.wait_until_succeeds("[ $(consul members | grep -o alive | wc -l) == 5 ]")
+
+
+ wait_for_healthy_servers()
+ # Also wait for clients to be alive.
+ wait_for_all_machines_alive()
client1.succeed("consul kv put testkey 42")
client2.succeed("[ $(consul kv get testkey) == 42 ]")
- # Test that the cluster can tolearate failures of any single server:
- for server in servers:
- server.crash()
- # For each client, wait until they have connection again
- # using `kv get -recurse` before issuing commands.
- client1.wait_until_succeeds("consul kv get -recurse")
- client2.wait_until_succeeds("consul kv get -recurse")
+ def rolling_reboot_test(proper_rolling_procedure=True):
+ """
+ Tests that the cluster can tolearate failures of any single server,
+ following the recommended rolling upgrade procedure from
+ https://www.consul.io/docs/upgrading#standard-upgrades.
- # Do some consul actions while one server is down.
- client1.succeed("consul kv put testkey 43")
- client2.succeed("[ $(consul kv get testkey) == 43 ]")
- client2.succeed("consul kv delete testkey")
+ Optionally, `proper_rolling_procedure=False` can be given
+ to wait only for each server to be back `Healthy`, not `Stable`
+ in the Raft consensus, see Consul setting `ServerStabilizationTime` and
+ https://github.com/hashicorp/consul/issues/8118#issuecomment-645330040.
+ """
+
+ for server in servers:
+ server.crash()
+
+ # For each client, wait until they have connection again
+ # using `kv get -recurse` before issuing commands.
+ client1.wait_until_succeeds("consul kv get -recurse")
+ client2.wait_until_succeeds("consul kv get -recurse")
- # Restart crashed machine.
- server.start()
+ # Do some consul actions while one server is down.
+ client1.succeed("consul kv put testkey 43")
+ client2.succeed("[ $(consul kv get testkey) == 43 ]")
+ client2.succeed("consul kv delete testkey")
+
+ # Restart crashed machine.
+ server.start()
+
+ if proper_rolling_procedure:
+ # Wait for recovery.
+ wait_for_healthy_servers()
+ else:
+ # NOT proper rolling upgrade procedure, see above.
+ wait_for_all_machines_alive()
+
+ # Wait for client connections.
+ client1.wait_until_succeeds("consul kv get -recurse")
+ client2.wait_until_succeeds("consul kv get -recurse")
+
+ # Do some consul actions with server back up.
+ client1.succeed("consul kv put testkey 44")
+ client2.succeed("[ $(consul kv get testkey) == 44 ]")
+ client2.succeed("consul kv delete testkey")
+
+
+ def all_servers_crash_simultaneously_test():
+ """
+ Tests that the cluster will eventually come back after all
+ servers crash simultaneously.
+ """
+
+ for server in servers:
+ server.crash()
+
+ for server in servers:
+ server.start()
# Wait for recovery.
- for m in machines:
- m.wait_until_succeeds("[ $(consul members | grep -o alive | wc -l) == 5 ]")
+ wait_for_healthy_servers()
# Wait for client connections.
client1.wait_until_succeeds("consul kv get -recurse")
client2.wait_until_succeeds("consul kv get -recurse")
- # Do some consul actions with server back up.
+ # Do some consul actions with servers back up.
client1.succeed("consul kv put testkey 44")
client2.succeed("[ $(consul kv get testkey) == 44 ]")
client2.succeed("consul kv delete testkey")
+
+
+ # Run the tests.
+
+ print("rolling_reboot_test()")
+ rolling_reboot_test()
+
+ print("all_servers_crash_simultaneously_test()")
+ all_servers_crash_simultaneously_test()
+
+ print("rolling_reboot_test(proper_rolling_procedure=False)")
+ rolling_reboot_test(proper_rolling_procedure=False)
'';
})
diff --git a/nixpkgs/nixos/tests/containers-portforward.nix b/nixpkgs/nixos/tests/containers-portforward.nix
index fc90e151bd9..1e2c2c6c374 100644
--- a/nixpkgs/nixos/tests/containers-portforward.nix
+++ b/nixpkgs/nixos/tests/containers-portforward.nix
@@ -5,7 +5,7 @@ let
hostPort = 10080;
containerIp = "192.168.0.100";
containerPort = 80;
-in
+in
import ./make-test-python.nix ({ pkgs, ...} : {
name = "containers-portforward";
diff --git a/nixpkgs/nixos/tests/convos.nix b/nixpkgs/nixos/tests/convos.nix
new file mode 100644
index 00000000000..b4ff1188fd8
--- /dev/null
+++ b/nixpkgs/nixos/tests/convos.nix
@@ -0,0 +1,30 @@
+import ./make-test-python.nix ({ lib, pkgs, ... }:
+
+with lib;
+let
+ port = 3333;
+in
+{
+ name = "convos";
+ meta = with pkgs.stdenv.lib.maintainers; {
+ maintainers = [ sgo ];
+ };
+
+ nodes = {
+ machine =
+ { pkgs, ... }:
+ {
+ services.convos = {
+ enable = true;
+ listenPort = port;
+ };
+ };
+ };
+
+ testScript = ''
+ machine.wait_for_unit("convos")
+ machine.wait_for_open_port("${toString port}")
+ machine.succeed("journalctl -u convos | grep -q 'Listening at.*${toString port}'")
+ machine.succeed("curl http://localhost:${toString port}/")
+ '';
+})
diff --git a/nixpkgs/nixos/tests/corerad.nix b/nixpkgs/nixos/tests/corerad.nix
index 741fa448f68..37a1e90477a 100644
--- a/nixpkgs/nixos/tests/corerad.nix
+++ b/nixpkgs/nixos/tests/corerad.nix
@@ -1,9 +1,9 @@
import ./make-test-python.nix (
{
nodes = {
- router = {config, pkgs, ...}: {
+ router = {config, pkgs, ...}: {
config = {
- # This machines simulates a router with IPv6 forwarding and a static IPv6 address.
+ # This machine simulates a router with IPv6 forwarding and a static IPv6 address.
boot.kernel.sysctl = {
"net.ipv6.conf.all.forwarding" = true;
};
@@ -14,13 +14,25 @@ import ./make-test-python.nix (
enable = true;
# Serve router advertisements to the client machine with prefix information matching
# any IPv6 /64 prefixes configured on this interface.
- configFile = pkgs.writeText "corerad.toml" ''
- [[interfaces]]
- name = "eth1"
- advertise = true
- [[interfaces.prefix]]
- prefix = "::/64"
- '';
+ #
+ # This configuration is identical to the example in the CoreRAD NixOS module.
+ settings = {
+ interfaces = [
+ {
+ name = "eth0";
+ monitor = true;
+ }
+ {
+ name = "eth1";
+ advertise = true;
+ prefix = [{ prefix = "::/64"; }];
+ }
+ ];
+ debug = {
+ address = "localhost:9430";
+ prometheus = true;
+ };
+ };
};
};
};
@@ -66,5 +78,12 @@ import ./make-test-python.nix (
assert (
"/64 scope global temporary" in addrs
), "SLAAC temporary address was not configured on client after router advertisement"
+
+ with subtest("Verify HTTP debug server is configured"):
+ out = router.succeed("curl localhost:9430/metrics")
+
+ assert (
+ "corerad_build_info" in out
+ ), "Build info metric was not found in Prometheus output"
'';
})
diff --git a/nixpkgs/nixos/tests/docker-preloader.nix b/nixpkgs/nixos/tests/docker-preloader.nix
index eeedec9a392..c3e8aced351 100644
--- a/nixpkgs/nixos/tests/docker-preloader.nix
+++ b/nixpkgs/nixos/tests/docker-preloader.nix
@@ -16,10 +16,10 @@ import ./make-test.nix ({ pkgs, ...} : {
services.openssh.extraConfig = "PermitEmptyPasswords yes";
users.extraUsers.root.password = "";
};
- };
+ };
testScript = ''
startAll;
-
+
$docker->waitForUnit("sockets.target");
$docker->succeed("docker run nix nix-store --version");
$docker->succeed("docker run bash bash --version");
diff --git a/nixpkgs/nixos/tests/docker-tools.nix b/nixpkgs/nixos/tests/docker-tools.nix
index 2375d15b381..2543801ae8b 100644
--- a/nixpkgs/nixos/tests/docker-tools.nix
+++ b/nixpkgs/nixos/tests/docker-tools.nix
@@ -30,8 +30,45 @@ import ./make-test-python.nix ({ pkgs, ... }: {
)
docker.succeed("docker run --rm ${examples.bash.imageName} bash --version")
+ # Check imageTag attribute matches image
+ docker.succeed("docker images --format '{{.Tag}}' | grep -F '${examples.bash.imageTag}'")
docker.succeed("docker rmi ${examples.bash.imageName}")
+ # The remaining combinations
+ with subtest("Ensure imageTag attribute matches image"):
+ docker.succeed(
+ "docker load --input='${examples.bashNoTag}'"
+ )
+ docker.succeed(
+ "docker images --format '{{.Tag}}' | grep -F '${examples.bashNoTag.imageTag}'"
+ )
+ docker.succeed("docker rmi ${examples.bashNoTag.imageName}:${examples.bashNoTag.imageTag}")
+
+ docker.succeed(
+ "docker load --input='${examples.bashNoTagLayered}'"
+ )
+ docker.succeed(
+ "docker images --format '{{.Tag}}' | grep -F '${examples.bashNoTagLayered.imageTag}'"
+ )
+ docker.succeed("docker rmi ${examples.bashNoTagLayered.imageName}:${examples.bashNoTagLayered.imageTag}")
+
+ docker.succeed(
+ "${examples.bashNoTagStreamLayered} | docker load"
+ )
+ docker.succeed(
+ "docker images --format '{{.Tag}}' | grep -F '${examples.bashNoTagStreamLayered.imageTag}'"
+ )
+ docker.succeed(
+ "docker rmi ${examples.bashNoTagStreamLayered.imageName}:${examples.bashNoTagStreamLayered.imageTag}"
+ )
+
+ docker.succeed(
+ "docker load --input='${examples.nixLayered}'"
+ )
+ docker.succeed("docker images --format '{{.Tag}}' | grep -F '${examples.nixLayered.imageTag}'")
+ docker.succeed("docker rmi ${examples.nixLayered.imageName}")
+
+
with subtest(
"Check if the nix store is correctly initialized by listing "
"dependencies of the installed Nix binary"
@@ -42,6 +79,30 @@ import ./make-test-python.nix ({ pkgs, ... }: {
"docker rmi ${examples.nix.imageName}",
)
+ with subtest(
+ "Ensure (layered) nix store has correct permissions "
+ "and that the container starts when its process does not have uid 0"
+ ):
+ docker.succeed(
+ "docker load --input='${examples.bashLayeredWithUser}'",
+ "docker run -u somebody --rm ${examples.bashLayeredWithUser.imageName} ${pkgs.bash}/bin/bash -c 'test 555 == $(stat --format=%a /nix) && test 555 == $(stat --format=%a /nix/store)'",
+ "docker rmi ${examples.bashLayeredWithUser.imageName}",
+ )
+
+ with subtest("The nix binary symlinks are intact"):
+ docker.succeed(
+ "docker load --input='${examples.nix}'",
+ "docker run --rm ${examples.nix.imageName} ${pkgs.bash}/bin/bash -c 'test nix == $(readlink ${pkgs.nix}/bin/nix-daemon)'",
+ "docker rmi ${examples.nix.imageName}",
+ )
+
+ with subtest("The nix binary symlinks are intact when the image is layered"):
+ docker.succeed(
+ "docker load --input='${examples.nixLayered}'",
+ "docker run --rm ${examples.nixLayered.imageName} ${pkgs.bash}/bin/bash -c 'test nix == $(readlink ${pkgs.nix}/bin/nix-daemon)'",
+ "docker rmi ${examples.nixLayered.imageName}",
+ )
+
with subtest("The pullImage tool works"):
docker.succeed(
"docker load --input='${examples.nixFromDockerHub}'",
@@ -76,13 +137,22 @@ import ./make-test-python.nix ({ pkgs, ... }: {
with subtest("Ensure Docker images can use an unstable date"):
docker.succeed(
- "docker load --input='${examples.bash}'"
+ "docker load --input='${examples.unstableDate}'"
)
assert unix_time_second1 not in docker.succeed(
"docker inspect ${examples.unstableDate.imageName} "
+ "| ${pkgs.jq}/bin/jq -r .[].Created"
)
+ with subtest("Ensure Layered Docker images can use an unstable date"):
+ docker.succeed(
+ "docker load --input='${examples.unstableDateLayered}'"
+ )
+ assert unix_time_second1 not in docker.succeed(
+ "docker inspect ${examples.unstableDateLayered.imageName} "
+ + "| ${pkgs.jq}/bin/jq -r .[].Created"
+ )
+
with subtest("Ensure Layered Docker images work"):
docker.succeed(
"docker load --input='${examples.layered-image}'",
@@ -164,5 +234,12 @@ import ./make-test-python.nix ({ pkgs, ... }: {
# This check may be loosened to allow an *empty* store rather than *no* store.
docker.succeed("docker run --rm no-store-paths ls /")
docker.fail("docker run --rm no-store-paths ls /nix/store")
+
+ with subtest("Ensure buildLayeredImage does not change store path contents."):
+ docker.succeed(
+ "docker load --input='${pkgs.dockerTools.examples.filesInStore}'",
+ "docker run --rm file-in-store nix-store --verify --check-contents",
+ "docker run --rm file-in-store |& grep 'some data'",
+ )
'';
})
diff --git a/nixpkgs/nixos/tests/docker.nix b/nixpkgs/nixos/tests/docker.nix
index 8fda7c1395e..a4a61468f33 100644
--- a/nixpkgs/nixos/tests/docker.nix
+++ b/nixpkgs/nixos/tests/docker.nix
@@ -43,7 +43,7 @@ import ./make-test-python.nix ({ pkgs, ...} : {
docker.fail("sudo -u noprivs docker ps")
docker.succeed("docker stop sleeping")
- # Must match version twice to ensure client and server versions are correct
- docker.succeed('[ $(docker version | grep ${pkgs.docker.version} | wc -l) = "2" ]')
+ # Must match version 4 times to ensure client and server git commits and versions are correct
+ docker.succeed('[ $(docker version | grep ${pkgs.docker.version} | wc -l) = "4" ]')
'';
})
diff --git a/nixpkgs/nixos/tests/dokuwiki.nix b/nixpkgs/nixos/tests/dokuwiki.nix
index 05271919eff..4f00521c202 100644
--- a/nixpkgs/nixos/tests/dokuwiki.nix
+++ b/nixpkgs/nixos/tests/dokuwiki.nix
@@ -32,8 +32,9 @@ let
in {
name = "dokuwiki";
- meta.maintainers = with pkgs.lib.maintainers; [ "1000101" ];
-
+ meta = with pkgs.stdenv.lib; {
+ maintainers = with maintainers; [ maintainers."1000101" ];
+ };
machine = { ... }: {
services.dokuwiki."site1.local" = {
aclUse = false;
diff --git a/nixpkgs/nixos/tests/gnome3-xorg.nix b/nixpkgs/nixos/tests/gnome3-xorg.nix
index b59badcd5de..0d05c12384f 100644
--- a/nixpkgs/nixos/tests/gnome3-xorg.nix
+++ b/nixpkgs/nixos/tests/gnome3-xorg.nix
@@ -12,8 +12,9 @@ import ./make-test-python.nix ({ pkgs, lib, ...} : {
services.xserver.enable = true;
- services.xserver.displayManager.gdm = {
- enable = true;
+ services.xserver.displayManager = {
+ gdm.enable = true;
+ gdm.debug = true;
autoLogin = {
enable = true;
user = user.name;
@@ -21,6 +22,7 @@ import ./make-test-python.nix ({ pkgs, lib, ...} : {
};
services.xserver.desktopManager.gnome3.enable = true;
+ services.xserver.desktopManager.gnome3.debug = true;
services.xserver.displayManager.defaultSession = "gnome-xorg";
virtualisation.memorySize = 1024;
diff --git a/nixpkgs/nixos/tests/gnome3.nix b/nixpkgs/nixos/tests/gnome3.nix
index 17e72c5f651..b3d7aff8bd7 100644
--- a/nixpkgs/nixos/tests/gnome3.nix
+++ b/nixpkgs/nixos/tests/gnome3.nix
@@ -11,8 +11,9 @@ import ./make-test-python.nix ({ pkgs, lib, ...} : {
services.xserver.enable = true;
- services.xserver.displayManager.gdm = {
- enable = true;
+ services.xserver.displayManager = {
+ gdm.enable = true;
+ gdm.debug = true;
autoLogin = {
enable = true;
user = "alice";
@@ -20,6 +21,7 @@ import ./make-test-python.nix ({ pkgs, lib, ...} : {
};
services.xserver.desktopManager.gnome3.enable = true;
+ services.xserver.desktopManager.gnome3.debug = true;
virtualisation.memorySize = 1024;
};
diff --git a/nixpkgs/nixos/tests/go-neb.nix b/nixpkgs/nixos/tests/go-neb.nix
new file mode 100644
index 00000000000..d9e5db0b4a5
--- /dev/null
+++ b/nixpkgs/nixos/tests/go-neb.nix
@@ -0,0 +1,44 @@
+import ./make-test-python.nix ({ pkgs, ... }:
+{
+ name = "go-neb";
+ meta = with pkgs.stdenv.lib.maintainers; {
+ maintainers = [ hexa maralorn ];
+ };
+
+ nodes = {
+ server = {
+ services.go-neb = {
+ enable = true;
+ baseUrl = "http://localhost";
+ config = {
+ clients = [ {
+ UserId = "@test:localhost";
+ AccessToken = "changeme";
+ HomeServerUrl = "http://localhost";
+ Sync = false;
+ AutoJoinRooms = false;
+ DisplayName = "neverbeseen";
+ } ];
+ services = [ {
+ ID = "wikipedia_service";
+ Type = "wikipedia";
+ UserID = "@test:localhost";
+ Config = { };
+ } ];
+ };
+ };
+ };
+ };
+
+ testScript = ''
+ start_all()
+ server.wait_for_unit("go-neb.service")
+ server.wait_until_succeeds(
+ "curl -L http://localhost:4050/services/hooks/d2lraXBlZGlhX3NlcnZpY2U"
+ )
+ server.wait_until_succeeds(
+ "journalctl -eu go-neb -o cat | grep -q service_id=wikipedia_service"
+ )
+ '';
+
+})
diff --git a/nixpkgs/nixos/tests/graphite.nix b/nixpkgs/nixos/tests/graphite.nix
index 71776a94cbd..137be2d89c8 100644
--- a/nixpkgs/nixos/tests/graphite.nix
+++ b/nixpkgs/nixos/tests/graphite.nix
@@ -1,11 +1,6 @@
import ./make-test-python.nix ({ pkgs, ... } :
{
name = "graphite";
- meta = {
- # Fails on dependency `python-2.7-Twisted`'s test suite
- # complaining `ImportError: No module named zope.interface`.
- broken = true;
- };
nodes = {
one =
{ ... }: {
@@ -21,7 +16,7 @@ import ./make-test-python.nix ({ pkgs, ... } :
api = {
enable = true;
port = 8082;
- finders = [ pkgs.python3Packages.influxgraph ];
+ finders = [ ];
};
carbon.enableCache = true;
seyren.enable = false; # Implicitely requires openssl-1.0.2u which is marked insecure
@@ -41,10 +36,14 @@ import ./make-test-python.nix ({ pkgs, ... } :
# even if they're still in preStart (which takes quite long for graphiteWeb).
# Wait for ports to open so we're sure the services are up and listening.
one.wait_for_open_port(8080)
+ one.wait_for_open_port(8082)
one.wait_for_open_port(2003)
one.succeed('echo "foo 1 `date +%s`" | nc -N localhost 2003')
one.wait_until_succeeds(
"curl 'http://localhost:8080/metrics/find/?query=foo&format=treejson' --silent | grep foo >&2"
)
+ one.wait_until_succeeds(
+ "curl 'http://localhost:8082/metrics/find/?query=foo&format=treejson' --silent | grep foo >&2"
+ )
'';
})
diff --git a/nixpkgs/nixos/tests/grub.nix b/nixpkgs/nixos/tests/grub.nix
new file mode 100644
index 00000000000..84bfc90955b
--- /dev/null
+++ b/nixpkgs/nixos/tests/grub.nix
@@ -0,0 +1,60 @@
+import ./make-test-python.nix ({ lib, ... }: {
+ name = "grub";
+
+ meta = with lib.maintainers; {
+ maintainers = [ rnhmjoj ];
+ };
+
+ machine = { ... }: {
+ virtualisation.useBootLoader = true;
+
+ boot.loader.timeout = null;
+ boot.loader.grub = {
+ enable = true;
+ users.alice.password = "supersecret";
+
+ # OCR is not accurate enough
+ extraConfig = "serial; terminal_output serial";
+ };
+ };
+
+ testScript = ''
+ def grub_login_as(user, password):
+ """
+ Enters user and password to log into GRUB
+ """
+ machine.wait_for_console_text("Enter username:")
+ machine.send_chars(user + "\n")
+ machine.wait_for_console_text("Enter password:")
+ machine.send_chars(password + "\n")
+
+
+ def grub_select_all_configurations():
+ """
+ Selects "All configurations" from the GRUB menu
+ to trigger a login request.
+ """
+ machine.send_monitor_command("sendkey down")
+ machine.send_monitor_command("sendkey ret")
+
+
+ machine.start()
+
+ # wait for grub screen
+ machine.wait_for_console_text("GNU GRUB")
+
+ grub_select_all_configurations()
+ with subtest("Invalid credentials are rejected"):
+ grub_login_as("wronguser", "wrongsecret")
+ machine.wait_for_console_text("error: access denied.")
+
+ grub_select_all_configurations()
+ with subtest("Valid credentials are accepted"):
+ grub_login_as("alice", "supersecret")
+ machine.send_chars("\n") # press enter to boot
+ machine.wait_for_console_text("Linux version")
+
+ with subtest("Machine boots correctly"):
+ machine.wait_for_unit("multi-user.target")
+ '';
+})
diff --git a/nixpkgs/nixos/tests/home-assistant.nix b/nixpkgs/nixos/tests/home-assistant.nix
index 3365e74ba83..a93a28d877a 100644
--- a/nixpkgs/nixos/tests/home-assistant.nix
+++ b/nixpkgs/nixos/tests/home-assistant.nix
@@ -2,69 +2,66 @@ import ./make-test-python.nix ({ pkgs, ... }:
let
configDir = "/var/lib/foobar";
- apiPassword = "some_secret";
- mqttPassword = "another_secret";
- hassCli = "hass-cli --server http://hass:8123 --password '${apiPassword}'";
+ mqttUsername = "homeassistant";
+ mqttPassword = "secret";
in {
name = "home-assistant";
meta = with pkgs.stdenv.lib; {
maintainers = with maintainers; [ dotlambda ];
};
- nodes = {
- hass =
- { pkgs, ... }:
- {
- environment.systemPackages = with pkgs; [
- mosquitto home-assistant-cli
- ];
- services.home-assistant = {
- inherit configDir;
- enable = true;
- package = pkgs.home-assistant.override {
- extraPackages = ps: with ps; [ hbmqtt ];
- };
- config = {
- homeassistant = {
- name = "Home";
- time_zone = "UTC";
- latitude = "0.0";
- longitude = "0.0";
- elevation = 0;
- auth_providers = [
- {
- type = "legacy_api_password";
- api_password = apiPassword;
- }
- ];
- };
- frontend = { };
- mqtt = { # Use hbmqtt as broker
- password = mqttPassword;
- };
- binary_sensor = [
- {
- platform = "mqtt";
- state_topic = "home-assistant/test";
- payload_on = "let_there_be_light";
- payload_off = "off";
- }
- ];
- };
- lovelaceConfig = {
- title = "My Awesome Home";
- views = [ {
- title = "Example";
- cards = [ {
- type = "markdown";
- title = "Lovelace";
- content = "Welcome to your **Lovelace UI**.";
- } ];
- } ];
- };
- lovelaceConfigWritable = true;
+ nodes.hass = { pkgs, ... }: {
+ environment.systemPackages = with pkgs; [ mosquitto ];
+ services.mosquitto = {
+ enable = true;
+ users = {
+ "${mqttUsername}" = {
+ acl = [ "pattern readwrite #" ];
+ password = mqttPassword;
};
};
+ };
+ services.home-assistant = {
+ inherit configDir;
+ enable = true;
+ config = {
+ homeassistant = {
+ name = "Home";
+ time_zone = "UTC";
+ latitude = "0.0";
+ longitude = "0.0";
+ elevation = 0;
+ };
+ frontend = {};
+ mqtt = {
+ broker = "127.0.0.1";
+ username = mqttUsername;
+ password = mqttPassword;
+ };
+ binary_sensor = [{
+ platform = "mqtt";
+ state_topic = "home-assistant/test";
+ payload_on = "let_there_be_light";
+ payload_off = "off";
+ }];
+ logger = {
+ default = "info";
+ logs."homeassistant.components.mqtt" = "debug";
+ };
+ };
+ lovelaceConfig = {
+ title = "My Awesome Home";
+ views = [{
+ title = "Example";
+ cards = [{
+ type = "markdown";
+ title = "Lovelace";
+ content = "Welcome to your **Lovelace UI**.";
+ }];
+ }];
+ };
+ lovelaceConfigWritable = true;
+ };
};
testScript = ''
@@ -77,28 +74,13 @@ in {
with subtest("Check that Home Assistant's web interface and API can be reached"):
hass.wait_for_open_port(8123)
hass.succeed("curl --fail http://localhost:8123/lovelace")
- assert "API running" in hass.succeed(
- "curl --fail -H 'x-ha-access: ${apiPassword}' http://localhost:8123/api/"
- )
with subtest("Toggle a binary sensor using MQTT"):
- assert '"state": "off"' in hass.succeed(
- "curl http://localhost:8123/api/states/binary_sensor.mqtt_binary_sensor -H 'x-ha-access: ${apiPassword}'"
- )
+ # wait for broker to become available
hass.wait_until_succeeds(
- "mosquitto_pub -V mqttv311 -t home-assistant/test -u homeassistant -P '${mqttPassword}' -m let_there_be_light"
- )
- assert '"state": "on"' in hass.succeed(
- "curl http://localhost:8123/api/states/binary_sensor.mqtt_binary_sensor -H 'x-ha-access: ${apiPassword}'"
- )
- with subtest("Toggle a binary sensor using hass-cli"):
- assert '"state": "on"' in hass.succeed(
- "${hassCli} --output json state get binary_sensor.mqtt_binary_sensor"
+ "mosquitto_sub -V mqttv311 -t home-assistant/test -u ${mqttUsername} -P '${mqttPassword}' -W 1 -t '*'"
)
hass.succeed(
- "${hassCli} state edit binary_sensor.mqtt_binary_sensor --json='{\"state\": \"off\"}'"
- )
- assert '"state": "off"' in hass.succeed(
- "curl http://localhost:8123/api/states/binary_sensor.mqtt_binary_sensor -H 'x-ha-access: ${apiPassword}'"
+ "mosquitto_pub -V mqttv311 -t home-assistant/test -u ${mqttUsername} -P '${mqttPassword}' -m let_there_be_light"
)
with subtest("Print log to ease debugging"):
output_log = hass.succeed("cat ${configDir}/home-assistant.log")
@@ -107,5 +89,9 @@ in {
with subtest("Check that no errors were logged"):
assert "ERROR" not in output_log
+
+ # example line: 2020-06-20 10:01:32 DEBUG (MainThread) [homeassistant.components.mqtt] Received message on home-assistant/test: b'let_there_be_light'
+ with subtest("Check we received the mosquitto message"):
+ assert "let_there_be_light" in output_log
'';
})
diff --git a/nixpkgs/nixos/tests/hydra/common.nix b/nixpkgs/nixos/tests/hydra/common.nix
index f612717dc96..312c52e889a 100644
--- a/nixpkgs/nixos/tests/hydra/common.nix
+++ b/nixpkgs/nixos/tests/hydra/common.nix
@@ -37,6 +37,7 @@
};
services.postfix.enable = true;
nix = {
+ distributedBuilds = true;
buildMachines = [{
hostName = "localhost";
systems = [ system ];
diff --git a/nixpkgs/nixos/tests/hydra/db-migration.nix b/nixpkgs/nixos/tests/hydra/db-migration.nix
index cf74acfd67a..ca65e2e66aa 100644
--- a/nixpkgs/nixos/tests/hydra/db-migration.nix
+++ b/nixpkgs/nixos/tests/hydra/db-migration.nix
@@ -61,7 +61,7 @@ with pkgs.lib;
'curl -L -s http://localhost:3000/build/1 -H "Accept: application/json" | jq .buildstatus | xargs test 0 -eq'
)
- out = original.succeed("su -l postgres -c 'psql -d hydra <<< \"\\d+ jobs\" -A'")
+ out = original.succeed("su -l postgres -c 'psql -d hydra <<< \"\\d+ builds\" -A'")
assert "jobset_id" not in out
original.succeed(
@@ -69,7 +69,7 @@ with pkgs.lib;
)
original.wait_for_unit("hydra-init.service")
- out = original.succeed("su -l postgres -c 'psql -d hydra <<< \"\\d+ jobs\" -A'")
+ out = original.succeed("su -l postgres -c 'psql -d hydra <<< \"\\d+ builds\" -A'")
assert "jobset_id|integer|||" in out
original.succeed("hydra-backfill-ids")
@@ -79,7 +79,7 @@ with pkgs.lib;
)
original.wait_for_unit("hydra-init.service")
- out = original.succeed("su -l postgres -c 'psql -d hydra <<< \"\\d+ jobs\" -A'")
+ out = original.succeed("su -l postgres -c 'psql -d hydra <<< \"\\d+ builds\" -A'")
assert "jobset_id|integer||not null|" in out
original.wait_until_succeeds(
diff --git a/nixpkgs/nixos/tests/ihatemoney.nix b/nixpkgs/nixos/tests/ihatemoney.nix
index 7df0ea0b691..0451a450580 100644
--- a/nixpkgs/nixos/tests/ihatemoney.nix
+++ b/nixpkgs/nixos/tests/ihatemoney.nix
@@ -1,5 +1,11 @@
+{ system ? builtins.currentSystem,
+ config ? {},
+ pkgs ? import ../.. { inherit system config; }
+}:
+
let
- f = backend: import ./make-test-python.nix ({ pkgs, ... }: {
+ inherit (import ../lib/testing-python.nix { inherit system pkgs; }) makeTest;
+ f = backend: makeTest {
name = "ihatemoney-${backend}";
machine = { lib, ... }: {
services.ihatemoney = {
@@ -24,9 +30,10 @@ let
testScript = ''
machine.wait_for_open_port(8000)
machine.wait_for_unit("uwsgi.service")
+ machine.wait_until_succeeds("curl http://localhost:8000")
assert '"yay"' in machine.succeed(
- "curl -X POST http://localhost:8000/api/projects -d 'name=yay&id=yay&password=yay&contact_email=yay\@example.com'"
+ "curl -X POST http://localhost:8000/api/projects -d 'name=yay&id=yay&password=yay&contact_email=yay@example.com'"
)
owner, timestamp = machine.succeed(
"stat --printf %U:%G___%Y /var/lib/ihatemoney/secret_key"
@@ -48,7 +55,7 @@ let
assert "ihatemoney" in machine.succeed("curl http://localhost:8000")
'';
- });
+ };
in {
ihatemoney-sqlite = f "sqlite";
ihatemoney-postgresql = f "postgresql";
diff --git a/nixpkgs/nixos/tests/initrd-network-openvpn/default.nix b/nixpkgs/nixos/tests/initrd-network-openvpn/default.nix
new file mode 100644
index 00000000000..bb4c41e6d70
--- /dev/null
+++ b/nixpkgs/nixos/tests/initrd-network-openvpn/default.nix
@@ -0,0 +1,145 @@
+import ../make-test-python.nix ({ lib, ...}:
+
+{
+ name = "initrd-network-openvpn";
+
+ nodes =
+ let
+
+ # Inlining of the shared secret for the
+ # OpenVPN server and client
+ secretblock = ''
+ secret [inline]
+ <secret>
+ ${lib.readFile ./shared.key}
+ </secret>
+ '';
+
+ in
+ {
+
+ # Minimal test case to check a successful boot, even with invalid config
+ minimalboot =
+ { ... }:
+ {
+ boot.initrd.network = {
+ enable = true;
+ openvpn = {
+ enable = true;
+ configuration = "/dev/null";
+ };
+ };
+ };
+
+ # initrd VPN client
+ ovpnclient =
+ { ... }:
+ {
+ virtualisation.useBootLoader = true;
+ virtualisation.vlans = [ 1 ];
+
+ boot.initrd = {
+ # This command does not fork to keep the VM in the state where
+ # only the initramfs is loaded
+ preLVMCommands =
+ ''
+ /bin/nc -p 1234 -lke /bin/echo TESTVALUE
+ '';
+
+ network = {
+ enable = true;
+
+ # Work around udhcpc only getting a lease on eth0
+ postCommands = ''
+ /bin/ip addr add 192.168.1.2/24 dev eth1
+ '';
+
+ # Example configuration for OpenVPN
+ # This is the main reason for this test
+ openvpn = {
+ enable = true;
+ configuration = "${./initrd.ovpn}";
+ };
+ };
+ };
+ };
+
+ # VPN server and gateway for ovpnclient between vlan 1 and 2
+ ovpnserver =
+ { ... }:
+ {
+ virtualisation.vlans = [ 1 2 ];
+
+ # Enable NAT and forward port 12345 to port 1234
+ networking.nat = {
+ enable = true;
+ internalInterfaces = [ "tun0" ];
+ externalInterface = "eth2";
+ forwardPorts = [ { destination = "10.8.0.2:1234";
+ sourcePort = 12345; } ];
+ };
+
+ # Trust tun0 and allow the VPN Server to be reached
+ networking.firewall = {
+ trustedInterfaces = [ "tun0" ];
+ allowedUDPPorts = [ 1194 ];
+ };
+
+ # Minimal OpenVPN server configuration
+ services.openvpn.servers.testserver =
+ {
+ config = ''
+ dev tun0
+ ifconfig 10.8.0.1 10.8.0.2
+ ${secretblock}
+ '';
+ };
+ };
+
+ # Client that resides in the "external" VLAN
+ testclient =
+ { ... }:
+ {
+ virtualisation.vlans = [ 2 ];
+ };
+ };
+
+
+ testScript =
+ ''
+ # Minimal test case, checks whether enabling (with invalid config) harms
+ # the boot process
+ with subtest("Check for successful boot with broken openvpn config"):
+ minimalboot.start()
+ # If we get to multi-user.target, we booted successfully
+ minimalboot.wait_for_unit("multi-user.target")
+ minimalboot.shutdown()
+
+ # Elaborated test case where the ovpnclient (where this module is used)
+ # can be reached by testclient only over ovpnserver.
+ # This is an indirect test for success.
+ with subtest("Check for connection from initrd VPN client, config as file"):
+ ovpnserver.start()
+ testclient.start()
+ ovpnclient.start()
+
+ # Wait until the OpenVPN Server is available
+ ovpnserver.wait_for_unit("openvpn-testserver.service")
+ ovpnserver.succeed("ping -c 1 10.8.0.1")
+
+ # Wait for the client to connect
+ ovpnserver.wait_until_succeeds("ping -c 1 10.8.0.2")
+
+ # Wait until the testclient has network
+ testclient.wait_for_unit("network.target")
+
+ # Check that ovpnclient is reachable over vlan 1
+ ovpnserver.succeed("nc -w 2 192.168.1.2 1234 | grep -q TESTVALUE")
+
+ # Check that ovpnclient is reachable over tun0
+ ovpnserver.succeed("nc -w 2 10.8.0.2 1234 | grep -q TESTVALUE")
+
+ # Check that ovpnclient is reachable from testclient over the gateway
+ testclient.succeed("nc -w 2 192.168.2.3 12345 | grep -q TESTVALUE")
+ '';
+})
diff --git a/nixpkgs/nixos/tests/initrd-network-openvpn/initrd.ovpn b/nixpkgs/nixos/tests/initrd-network-openvpn/initrd.ovpn
new file mode 100644
index 00000000000..5926a48af00
--- /dev/null
+++ b/nixpkgs/nixos/tests/initrd-network-openvpn/initrd.ovpn
@@ -0,0 +1,29 @@
+remote 192.168.1.3
+dev tun
+ifconfig 10.8.0.2 10.8.0.1
+# Only force VLAN 2 through the VPN
+route 192.168.2.0 255.255.255.0 10.8.0.1
+secret [inline]
+<secret>
+#
+# 2048 bit OpenVPN static key
+#
+-----BEGIN OpenVPN Static key V1-----
+553aabe853acdfe51cd6fcfea93dcbb0
+c8797deadd1187606b1ea8f2315eb5e6
+67c0d7e830f50df45686063b189d6c6b
+aab8bb3430cc78f7bb1f78628d5c3742
+0cef4f53a5acab2894905f4499f95d8e
+e69b7b6748b17016f89e19e91481a9fd
+bf8c10651f41a1d4fdf5f438925a6733
+13cec8f04701eb47b8f7ffc48bc3d7af
+65f07bce766015b87c3db4d668c655ff
+be5a69522a8e60ccb217f8521681b45d
+27c0b70bdfbfbb426c7646d80adf7482
+3ddac58b25cb1c1bb100de974478b4c6
+8b45a94261a2405e99810cb2b3abd49f
+21b3198ada87ff3c4e656a008e540a8d
+e7811584363597599cce2040a68ac00e
+f2125540e0f7f4adc37cb3f0d922eeb7
+-----END OpenVPN Static key V1-----
+</secret> \ No newline at end of file
diff --git a/nixpkgs/nixos/tests/initrd-network-openvpn/shared.key b/nixpkgs/nixos/tests/initrd-network-openvpn/shared.key
new file mode 100644
index 00000000000..248a91a3e3d
--- /dev/null
+++ b/nixpkgs/nixos/tests/initrd-network-openvpn/shared.key
@@ -0,0 +1,21 @@
+#
+# 2048 bit OpenVPN static key
+#
+-----BEGIN OpenVPN Static key V1-----
+553aabe853acdfe51cd6fcfea93dcbb0
+c8797deadd1187606b1ea8f2315eb5e6
+67c0d7e830f50df45686063b189d6c6b
+aab8bb3430cc78f7bb1f78628d5c3742
+0cef4f53a5acab2894905f4499f95d8e
+e69b7b6748b17016f89e19e91481a9fd
+bf8c10651f41a1d4fdf5f438925a6733
+13cec8f04701eb47b8f7ffc48bc3d7af
+65f07bce766015b87c3db4d668c655ff
+be5a69522a8e60ccb217f8521681b45d
+27c0b70bdfbfbb426c7646d80adf7482
+3ddac58b25cb1c1bb100de974478b4c6
+8b45a94261a2405e99810cb2b3abd49f
+21b3198ada87ff3c4e656a008e540a8d
+e7811584363597599cce2040a68ac00e
+f2125540e0f7f4adc37cb3f0d922eeb7
+-----END OpenVPN Static key V1-----
diff --git a/nixpkgs/nixos/tests/installed-tests/default.nix b/nixpkgs/nixos/tests/installed-tests/default.nix
index b6bdfea2277..889a00d4b56 100644
--- a/nixpkgs/nixos/tests/installed-tests/default.nix
+++ b/nixpkgs/nixos/tests/installed-tests/default.nix
@@ -50,6 +50,12 @@ let
environment.systemPackages = with pkgs; [ gnome-desktop-testing ];
+ # The installed tests need to be added to the test VM’s closure.
+ # Otherwise, their dependencies might not actually be registered
+ # as valid paths in the VM’s Nix store database,
+ # and `nix-store --query` commands run as part of the tests
+ # (for example when building Flatpak runtimes) will fail.
+ environment.variables.TESTED_PACKAGE_INSTALLED_TESTS = "${tested.installedTests}/share";
};
testScript =
diff --git a/nixpkgs/nixos/tests/installed-tests/flatpak.nix b/nixpkgs/nixos/tests/installed-tests/flatpak.nix
index 091c9932662..8aeeaca90f6 100644
--- a/nixpkgs/nixos/tests/installed-tests/flatpak.nix
+++ b/nixpkgs/nixos/tests/installed-tests/flatpak.nix
@@ -5,14 +5,11 @@ makeInstalledTest {
withX11 = true;
testConfig = {
- services.xserver.desktopManager.gnome3.enable = true; # TODO: figure out minimal environment where the tests work
- # common/x11.nix enables the auto display manager (lightdm)
- services.xserver.displayManager.gdm.enable = false;
- services.gnome3.core-utilities.enable = false;
+ xdg.portal.enable = true;
services.flatpak.enable = true;
- environment.systemPackages = with pkgs; [ gnupg ostree python2 ];
+ environment.systemPackages = with pkgs; [ gnupg ostree python3 ];
virtualisation.memorySize = 2047;
- virtualisation.diskSize = 1024;
+ virtualisation.diskSize = 3072;
};
testRunnerFlags = "--timeout 3600";
diff --git a/nixpkgs/nixos/tests/installed-tests/ibus.nix b/nixpkgs/nixos/tests/installed-tests/ibus.nix
index af54b612b50..a4bc2a7d7de 100644
--- a/nixpkgs/nixos/tests/installed-tests/ibus.nix
+++ b/nixpkgs/nixos/tests/installed-tests/ibus.nix
@@ -5,16 +5,12 @@ makeInstalledTest {
testConfig = {
i18n.inputMethod.enabled = "ibus";
+ systemd.user.services.ibus-daemon = {
+ serviceConfig.ExecStart = "${pkgs.ibus}/bin/ibus-daemon --xim --verbose";
+ wantedBy = [ "graphical-session.target" ];
+ partOf = [ "graphical-session.target" ];
+ };
};
- preTestScript = ''
- # ibus has ibus-desktop-testing-runner but it tries to manage desktop session so we just spawn ibus-daemon ourselves
- machine.succeed("ibus-daemon --daemonize --verbose")
- '';
-
withX11 = true;
-
- # TODO: ibus-daemon is currently crashing or something
- # maybe make ibus systemd service that auto-restarts?
- meta.broken = true;
}
diff --git a/nixpkgs/nixos/tests/installed-tests/ostree.nix b/nixpkgs/nixos/tests/installed-tests/ostree.nix
index eef7cace54c..90e09ad4ddf 100644
--- a/nixpkgs/nixos/tests/installed-tests/ostree.nix
+++ b/nixpkgs/nixos/tests/installed-tests/ostree.nix
@@ -3,21 +3,10 @@
makeInstalledTest {
tested = pkgs.ostree;
- # TODO: Wrap/patch the tests directly in the package
testConfig = {
environment.systemPackages = with pkgs; [
- (python3.withPackages (p: with p; [ pyyaml ]))
gnupg
ostree
];
-
- # for GJS tests
- environment.variables.GI_TYPELIB_PATH = lib.makeSearchPath "lib/girepository-1.0" (with pkgs; [
- gtk3
- pango.out
- ostree
- gdk-pixbuf
- atk
- ]);
};
}
diff --git a/nixpkgs/nixos/tests/installer.nix b/nixpkgs/nixos/tests/installer.nix
index eef9abebf9f..02b839fee3f 100644
--- a/nixpkgs/nixos/tests/installer.nix
+++ b/nixpkgs/nixos/tests/installer.nix
@@ -64,7 +64,7 @@ let
# a test script fragment `createPartitions', which must create
# partitions and filesystems.
testScriptFun = { bootLoader, createPartitions, grubVersion, grubDevice, grubUseEfi
- , grubIdentifier, preBootCommands, extraConfig
+ , grubIdentifier, preBootCommands, postBootCommands, extraConfig
, testSpecialisationConfig
}:
let iface = if grubVersion == 1 then "ide" else "virtio";
@@ -216,6 +216,7 @@ let
machine = create_machine_named("boot-after-rebuild-switch")
${preBootCommands}
machine.wait_for_unit("network.target")
+ ${postBootCommands}
machine.shutdown()
# Tests for validating clone configuration entries in grub menu
@@ -238,6 +239,7 @@ let
with subtest("Set grub to boot the second configuration"):
machine.succeed("grub-reboot 1")
+ ${postBootCommands}
machine.shutdown()
# Reboot Machine
@@ -252,12 +254,13 @@ let
with subtest("We should find a file named /etc/gitconfig"):
machine.succeed("test -e /etc/gitconfig")
+ ${postBootCommands}
machine.shutdown()
'';
makeInstallerTest = name:
- { createPartitions, preBootCommands ? "", extraConfig ? ""
+ { createPartitions, preBootCommands ? "", postBootCommands ? "", extraConfig ? ""
, extraInstallerConfig ? {}
, bootLoader ? "grub" # either "grub" or "systemd-boot"
, grubVersion ? 2, grubDevice ? "/dev/vda", grubIdentifier ? "uuid", grubUseEfi ? false
@@ -335,7 +338,7 @@ let
};
testScript = testScriptFun {
- inherit bootLoader createPartitions preBootCommands
+ inherit bootLoader createPartitions preBootCommands postBootCommands
grubVersion grubDevice grubIdentifier grubUseEfi extraConfig
testSpecialisationConfig;
};
@@ -552,16 +555,26 @@ in {
+ " mkpart primary 2048M -1s" # PV2
+ " set 2 lvm on",
"udevadm settle",
+ "sleep 1",
"pvcreate /dev/vda1 /dev/vda2",
+ "sleep 1",
"vgcreate MyVolGroup /dev/vda1 /dev/vda2",
+ "sleep 1",
"lvcreate --size 1G --name swap MyVolGroup",
- "lvcreate --size 2G --name nixos MyVolGroup",
+ "sleep 1",
+ "lvcreate --size 3G --name nixos MyVolGroup",
+ "sleep 1",
"mkswap -f /dev/MyVolGroup/swap -L swap",
"swapon -L swap",
"mkfs.xfs -L nixos /dev/MyVolGroup/nixos",
"mount LABEL=nixos /mnt",
)
'';
+ postBootCommands = ''
+ assert "loaded active" in machine.succeed(
+ "systemctl list-units 'lvm2-pvscan@*' -ql --no-legend | tee /dev/stderr"
+ )
+ '';
};
# Boot off an encrypted root partition with the default LUKS header format
diff --git a/nixpkgs/nixos/tests/ipfs.nix b/nixpkgs/nixos/tests/ipfs.nix
index 4d721aec0c7..9c0ff5306e0 100644
--- a/nixpkgs/nixos/tests/ipfs.nix
+++ b/nixpkgs/nixos/tests/ipfs.nix
@@ -7,19 +7,33 @@ import ./make-test-python.nix ({ pkgs, ...} : {
nodes.machine = { ... }: {
services.ipfs = {
enable = true;
+ # Also will add a unix domain socket socket API address, see module.
+ startWhenNeeded = true;
apiAddress = "/ip4/127.0.0.1/tcp/2324";
};
};
testScript = ''
start_all()
- machine.wait_for_unit("ipfs")
- machine.wait_until_succeeds("ipfs --api /ip4/127.0.0.1/tcp/2324 id")
+ # IPv4 activation
+
+ machine.succeed("ipfs --api /ip4/127.0.0.1/tcp/2324 id")
ipfs_hash = machine.succeed(
"echo fnord | ipfs --api /ip4/127.0.0.1/tcp/2324 add | awk '{ print $2 }'"
)
machine.succeed(f"ipfs cat /ipfs/{ipfs_hash.strip()} | grep fnord")
+
+ # Unix domain socket activation
+
+ machine.stop_job("ipfs")
+
+ ipfs_hash = machine.succeed(
+ "echo fnord2 | ipfs --api /unix/run/ipfs.sock add | awk '{ print $2 }'"
+ )
+ machine.succeed(
+ f"ipfs --api /unix/run/ipfs.sock cat /ipfs/{ipfs_hash.strip()} | grep fnord2"
+ )
'';
})
diff --git a/nixpkgs/nixos/tests/jitsi-meet.nix b/nixpkgs/nixos/tests/jitsi-meet.nix
new file mode 100644
index 00000000000..42762dfdad8
--- /dev/null
+++ b/nixpkgs/nixos/tests/jitsi-meet.nix
@@ -0,0 +1,55 @@
+import ./make-test-python.nix ({ pkgs, ... }: {
+ name = "jitsi-meet";
+ meta = with pkgs.stdenv.lib; {
+ maintainers = teams.jitsi.members;
+ };
+
+ nodes = {
+ client = { nodes, pkgs, ... }: {
+ };
+ server = { config, pkgs, ... }: {
+ services.jitsi-meet = {
+ enable = true;
+ hostName = "server";
+ };
+ services.jitsi-videobridge.openFirewall = true;
+
+ networking.firewall.allowedTCPPorts = [ 80 443 ];
+
+ services.nginx.virtualHosts.server = {
+ enableACME = true;
+ forceSSL = true;
+ };
+
+ security.acme.email = "me@example.org";
+ security.acme.acceptTerms = true;
+ security.acme.server = "https://example.com"; # self-signed only
+ };
+ };
+
+ testScript = ''
+ server.wait_for_unit("jitsi-videobridge2.service")
+ server.wait_for_unit("jicofo.service")
+ server.wait_for_unit("nginx.service")
+ server.wait_for_unit("prosody.service")
+
+ server.wait_until_succeeds(
+ "journalctl -b -u jitsi-videobridge2 -o cat | grep -q 'Performed a successful health check'"
+ )
+ server.wait_until_succeeds(
+ "journalctl -b -u jicofo -o cat | grep -q 'connected .JID: focus@auth.server'"
+ )
+ server.wait_until_succeeds(
+ "journalctl -b -u prosody -o cat | grep -q 'Authenticated as focus@auth.server'"
+ )
+ server.wait_until_succeeds(
+ "journalctl -b -u prosody -o cat | grep -q 'focus.server:component: External component successfully authenticated'"
+ )
+ server.wait_until_succeeds(
+ "journalctl -b -u prosody -o cat | grep -q 'Authenticated as jvb@auth.server'"
+ )
+
+ client.wait_for_unit("network.target")
+ assert "<title>Jitsi Meet</title>" in client.succeed("curl -sSfkL http://server/")
+ '';
+})
diff --git a/nixpkgs/nixos/tests/kubernetes/base.nix b/nixpkgs/nixos/tests/kubernetes/base.nix
index 86de9455e73..8cfac10b6dc 100644
--- a/nixpkgs/nixos/tests/kubernetes/base.nix
+++ b/nixpkgs/nixos/tests/kubernetes/base.nix
@@ -9,7 +9,6 @@ with pkgs.lib;
let
mkKubernetesBaseTest =
{ name, domain ? "my.zyx", test, machines
- , pkgs ? import <nixpkgs> { inherit system; }
, extraConfiguration ? null }:
let
masterName = head (filter (machineName: any (role: role == "master") machines.${machineName}.roles) (attrNames machines));
diff --git a/nixpkgs/nixos/tests/leaps.nix b/nixpkgs/nixos/tests/leaps.nix
index 65b475d734e..ac0c602d445 100644
--- a/nixpkgs/nixos/tests/leaps.nix
+++ b/nixpkgs/nixos/tests/leaps.nix
@@ -7,7 +7,7 @@ import ./make-test-python.nix ({ pkgs, ... }:
};
nodes =
- {
+ {
client = { };
server =
diff --git a/nixpkgs/nixos/tests/lorri/default.nix b/nixpkgs/nixos/tests/lorri/default.nix
index 198171082d8..c33c7503993 100644
--- a/nixpkgs/nixos/tests/lorri/default.nix
+++ b/nixpkgs/nixos/tests/lorri/default.nix
@@ -18,7 +18,7 @@ import ../make-test-python.nix {
machine.wait_until_succeeds("grep --fixed-strings 'ready' lorri.stdout")
# Ping the daemon
- machine.succeed("lorri internal__ping shell.nix")
+ machine.succeed("lorri internal ping shell.nix")
# Wait for the daemon to finish the build
machine.wait_until_succeeds("grep --fixed-strings 'Completed' lorri.stdout")
diff --git a/nixpkgs/nixos/tests/lxd-nftables.nix b/nixpkgs/nixos/tests/lxd-nftables.nix
new file mode 100644
index 00000000000..25517914db8
--- /dev/null
+++ b/nixpkgs/nixos/tests/lxd-nftables.nix
@@ -0,0 +1,50 @@
+# This test makes sure that lxd stops implicitly depending on iptables when
+# user enabled nftables.
+#
+# It has been extracted from `lxd.nix` for clarity, and because switching from
+# iptables to nftables requires a full reboot, which is a bit hard inside NixOS
+# tests.
+
+import ./make-test-python.nix ({ pkgs, ...} : {
+ name = "lxd-nftables";
+ meta = with pkgs.stdenv.lib.maintainers; {
+ maintainers = [ patryk27 ];
+ };
+
+ machine = { lib, ... }: {
+ virtualisation = {
+ lxd.enable = true;
+ };
+
+ networking = {
+ firewall.enable = false;
+ nftables.enable = true;
+ nftables.ruleset = ''
+ table inet filter {
+ chain incoming {
+ type filter hook input priority 0;
+ policy accept;
+ }
+
+ chain forward {
+ type filter hook forward priority 0;
+ policy accept;
+ }
+
+ chain output {
+ type filter hook output priority 0;
+ policy accept;
+ }
+ }
+ '';
+ };
+ };
+
+ testScript = ''
+ machine.wait_for_unit("network.target")
+
+ with subtest("When nftables are enabled, lxd doesn't depend on iptables anymore"):
+ machine.succeed("lsmod | grep nf_tables")
+ machine.fail("lsmod | grep ip_tables")
+ '';
+})
diff --git a/nixpkgs/nixos/tests/lxd.nix b/nixpkgs/nixos/tests/lxd.nix
new file mode 100644
index 00000000000..db2d44dff55
--- /dev/null
+++ b/nixpkgs/nixos/tests/lxd.nix
@@ -0,0 +1,135 @@
+import ./make-test-python.nix ({ pkgs, ...} :
+
+let
+ # Since we don't have access to the internet during the tests, we have to
+ # pre-fetch lxd containers beforehand.
+ #
+ # I've chosen to import Alpine Linux, because its image is turbo-tiny and,
+ # generally, sufficient for our tests.
+
+ alpine-meta = pkgs.fetchurl {
+ url = "https://uk.images.linuxcontainers.org/images/alpine/3.11/i386/default/20200608_13:00/lxd.tar.xz";
+ sha256 = "1hkvaj3rr333zmx1759njy435lps33gl4ks8zfm7m4nqvipm26a0";
+ };
+
+ alpine-rootfs = pkgs.fetchurl {
+ url = "https://uk.images.linuxcontainers.org/images/alpine/3.11/i386/default/20200608_13:00/rootfs.tar.xz";
+ sha256 = "1v82zdra4j5xwsff09qlp7h5vbsg54s0j7rdg4rynichfid3r347";
+ };
+
+ lxd-config = pkgs.writeText "config.yaml" ''
+ storage_pools:
+ - name: default
+ driver: dir
+ config:
+ source: /var/lxd-pool
+
+ networks:
+ - name: lxdbr0
+ type: bridge
+ config:
+ ipv4.address: auto
+ ipv6.address: none
+
+ profiles:
+ - name: default
+ devices:
+ eth0:
+ name: eth0
+ network: lxdbr0
+ type: nic
+ root:
+ path: /
+ pool: default
+ type: disk
+ '';
+
+in {
+ name = "lxd";
+ meta = with pkgs.stdenv.lib.maintainers; {
+ maintainers = [ patryk27 ];
+ };
+
+ machine = { lib, ... }: {
+ virtualisation = {
+ # Since we're testing `limits.cpu`, we've gotta have a known number of
+ # cores to lay on
+ cores = 2;
+
+ # Ditto, for `limits.memory`
+ memorySize = 512;
+
+ lxc.lxcfs.enable = true;
+ lxd.enable = true;
+ };
+ };
+
+ testScript = ''
+ machine.wait_for_unit("sockets.target")
+ machine.wait_for_unit("lxd.service")
+
+ # It takes additional second for lxd to settle
+ machine.sleep(1)
+
+ # lxd expects the pool's directory to already exist
+ machine.succeed("mkdir /var/lxd-pool")
+
+ machine.succeed(
+ "cat ${lxd-config} | lxd init --preseed"
+ )
+
+ machine.succeed(
+ "lxc image import ${alpine-meta} ${alpine-rootfs} --alias alpine"
+ )
+
+ with subtest("Containers can be launched and destroyed"):
+ machine.succeed("lxc launch alpine test")
+ machine.succeed("lxc exec test true")
+ machine.succeed("lxc delete -f test")
+
+ with subtest("Containers are being mounted with lxcfs inside"):
+ machine.succeed("lxc launch alpine test")
+
+ ## ---------- ##
+ ## limits.cpu ##
+
+ machine.succeed("lxc config set test limits.cpu 1")
+
+ # Since Alpine doesn't have `nproc` pre-installed, we've gotta resort
+ # to the primal methods
+ assert (
+ "1"
+ == machine.succeed("lxc exec test grep -- -c ^processor /proc/cpuinfo").strip()
+ )
+
+ machine.succeed("lxc config set test limits.cpu 2")
+
+ assert (
+ "2"
+ == machine.succeed("lxc exec test grep -- -c ^processor /proc/cpuinfo").strip()
+ )
+
+ ## ------------- ##
+ ## limits.memory ##
+
+ machine.succeed("lxc config set test limits.memory 64MB")
+
+ assert (
+ "MemTotal: 62500 kB"
+ == machine.succeed("lxc exec test grep -- MemTotal /proc/meminfo").strip()
+ )
+
+ machine.succeed("lxc config set test limits.memory 128MB")
+
+ assert (
+ "MemTotal: 125000 kB"
+ == machine.succeed("lxc exec test grep -- MemTotal /proc/meminfo").strip()
+ )
+
+ machine.succeed("lxc delete -f test")
+
+ with subtest("Unless explicitly changed, lxd leans on iptables"):
+ machine.succeed("lsmod | grep ip_tables")
+ machine.fail("lsmod | grep nf_tables")
+ '';
+})
diff --git a/nixpkgs/nixos/tests/matrix-synapse.nix b/nixpkgs/nixos/tests/matrix-synapse.nix
index f3623aa3c09..9ca80872176 100644
--- a/nixpkgs/nixos/tests/matrix-synapse.nix
+++ b/nixpkgs/nixos/tests/matrix-synapse.nix
@@ -29,8 +29,8 @@ import ./make-test-python.nix ({ pkgs, ... } : let
in {
name = "matrix-synapse";
- meta = with pkgs.stdenv.lib.maintainers; {
- maintainers = [ corngood ];
+ meta = with pkgs.stdenv.lib; {
+ maintainers = teams.matrix.members;
};
nodes = {
diff --git a/nixpkgs/nixos/tests/molly-brown.nix b/nixpkgs/nixos/tests/molly-brown.nix
new file mode 100644
index 00000000000..09ce42726ca
--- /dev/null
+++ b/nixpkgs/nixos/tests/molly-brown.nix
@@ -0,0 +1,71 @@
+import ./make-test-python.nix ({ pkgs, ... }:
+
+ let testString = "NixOS Gemini test successful";
+ in {
+
+ name = "molly-brown";
+ meta = with pkgs.stdenv.lib.maintainers; { maintainers = [ ehmry ]; };
+
+ nodes = {
+
+ geminiServer = { config, pkgs, ... }:
+ let
+ inherit (config.networking) hostName;
+ cfg = config.services.molly-brown;
+ in {
+
+ environment.systemPackages = [
+ (pkgs.writeScriptBin "test-gemini" ''
+ #!${pkgs.python3}/bin/python
+
+ import socket
+ import ssl
+ import tempfile
+ import textwrap
+ import urllib.parse
+
+ url = "gemini://geminiServer/init.gmi"
+ parsed_url = urllib.parse.urlparse(url)
+
+ s = socket.create_connection((parsed_url.netloc, 1965))
+ context = ssl.SSLContext()
+ context.check_hostname = False
+ context.verify_mode = ssl.CERT_NONE
+ s = context.wrap_socket(s, server_hostname=parsed_url.netloc)
+ s.sendall((url + "\r\n").encode("UTF-8"))
+ fp = s.makefile("rb")
+ print(fp.readline().strip())
+ print(fp.readline().strip())
+ print(fp.readline().strip())
+ '')
+ ];
+
+ networking.firewall.allowedTCPPorts = [ cfg.settings.Port ];
+
+ services.molly-brown = {
+ enable = true;
+ docBase = "/tmp/docs";
+ certPath = "/tmp/cert.pem";
+ keyPath = "/tmp/key.pem";
+ };
+
+ systemd.services.molly-brown.preStart = ''
+ ${pkgs.openssl}/bin/openssl genrsa -out "/tmp/key.pem"
+ ${pkgs.openssl}/bin/openssl req -new \
+ -subj "/CN=${config.networking.hostName}" \
+ -key "/tmp/key.pem" -out /tmp/request.pem
+ ${pkgs.openssl}/bin/openssl x509 -req -days 3650 \
+ -in /tmp/request.pem -signkey "/tmp/key.pem" -out "/tmp/cert.pem"
+
+ mkdir -p "${cfg.settings.DocBase}"
+ echo "${testString}" > "${cfg.settings.DocBase}/test.gmi"
+ '';
+ };
+ };
+ testScript = ''
+ geminiServer.wait_for_unit("molly-brown")
+ geminiServer.wait_for_open_port(1965)
+ geminiServer.succeed("test-gemini")
+ '';
+
+ })
diff --git a/nixpkgs/nixos/tests/mongodb.nix b/nixpkgs/nixos/tests/mongodb.nix
index a637ec4bfc0..1a712388301 100644
--- a/nixpkgs/nixos/tests/mongodb.nix
+++ b/nixpkgs/nixos/tests/mongodb.nix
@@ -15,7 +15,7 @@ import ./make-test-python.nix ({ pkgs, ... }:
node.wait_for_open_port(27017)
assert "hello" in node.succeed(
- "mongo ${testQuery}"
+ "${pkg}/bin/mongo ${testQuery}"
)
node.execute(
@@ -36,6 +36,7 @@ import ./make-test-python.nix ({ pkgs, ... }:
mongodb-3_4
mongodb-3_6
mongodb-4_0
+ mongodb-4_2
];
};
};
@@ -44,8 +45,9 @@ import ./make-test-python.nix ({ pkgs, ... }:
node.start()
''
+ runMongoDBTest pkgs.mongodb-3_4
- + runMongoDBTest pkgs.mongodb-3_6
+ + runMongoDBTest pkgs.mongodb-3_6
+ runMongoDBTest pkgs.mongodb-4_0
+ + runMongoDBTest pkgs.mongodb-4_2
+ ''
node.shutdown()
'';
diff --git a/nixpkgs/nixos/tests/ncdns.nix b/nixpkgs/nixos/tests/ncdns.nix
new file mode 100644
index 00000000000..507e20fe7cc
--- /dev/null
+++ b/nixpkgs/nixos/tests/ncdns.nix
@@ -0,0 +1,77 @@
+import ./make-test-python.nix ({ pkgs, ... }:
+let
+ fakeReply = pkgs.writeText "namecoin-reply.json" ''
+ { "error": null,
+ "id": 1,
+ "result": {
+ "address": "T31q8ucJ4dI1xzhxQ5QispfECld5c7Xw",
+ "expired": false,
+ "expires_in": 2248,
+ "height": 438155,
+ "name": "d/test",
+ "txid": "db61c0b2540ba0c1a2c8cc92af703a37002e7566ecea4dbf8727c7191421edfb",
+ "value": "{\"ip\": \"1.2.3.4\", \"email\": \"root@test.bit\",\"info\": \"Fake record\"}",
+ "vout": 0
+ }
+ }
+ '';
+in
+
+{
+ name = "ncdns";
+
+ nodes.server = { ... }: {
+ networking.nameservers = [ "127.0.0.1" ];
+
+ services.namecoind.rpc = {
+ address = "127.0.0.1";
+ user = "namecoin";
+ password = "secret";
+ port = 8332;
+ };
+
+ # Fake namecoin RPC server because we can't
+ # run a full node in a test.
+ systemd.services.namecoind = {
+ wantedBy = [ "multi-user.target" ];
+ script = ''
+ while true; do
+ echo -e "HTTP/1.1 200 OK\n\n $(<${fakeReply})\n" \
+ | ${pkgs.netcat}/bin/nc -N -l 127.0.0.1 8332
+ done
+ '';
+ };
+
+ services.ncdns = {
+ enable = true;
+ dnssec.enable = true;
+ };
+
+ services.pdns-recursor = {
+ enable = true;
+ dns.allowFrom = [ "127.0.0.0/8" ];
+ settings.loglevel = 8;
+ resolveNamecoin = true;
+ };
+
+ environment.systemPackages = [ pkgs.dnsutils ];
+
+ };
+
+ testScript = ''
+ with subtest("DNSSEC keys have been generated"):
+ server.wait_for_unit("ncdns")
+ server.wait_for_file("/var/lib/ncdns/bit.key")
+ server.wait_for_file("/var/lib/ncdns/bit-zone.key")
+
+ with subtest("DNSKEY bit record is present"):
+ server.wait_for_unit("pdns-recursor")
+ server.wait_for_open_port("53")
+ server.succeed("host -t DNSKEY bit")
+
+ with subtest("can resolve a .bit name"):
+ server.wait_for_unit("namecoind")
+ server.wait_for_open_port("8332")
+ assert "1.2.3.4" in server.succeed("host -t A test.bit")
+ '';
+})
diff --git a/nixpkgs/nixos/tests/networking.nix b/nixpkgs/nixos/tests/networking.nix
index 3d8ab761a44..83d4f6465b6 100644
--- a/nixpkgs/nixos/tests/networking.nix
+++ b/nixpkgs/nixos/tests/networking.nix
@@ -8,7 +8,9 @@ with import ../lib/testing-python.nix { inherit system pkgs; };
with pkgs.lib;
let
- router = { config, pkgs, ... }:
+ qemu-flags = import ../lib/qemu-flags.nix { inherit pkgs; };
+
+ router = { config, pkgs, lib, ... }:
with pkgs.lib;
let
vlanIfs = range 1 (length config.virtualisation.vlans);
@@ -30,17 +32,20 @@ let
services.dhcpd4 = {
enable = true;
interfaces = map (n: "eth${toString n}") vlanIfs;
- extraConfig = ''
- authoritative;
- '' + flip concatMapStrings vlanIfs (n: ''
+ extraConfig = flip concatMapStrings vlanIfs (n: ''
subnet 192.168.${toString n}.0 netmask 255.255.255.0 {
option routers 192.168.${toString n}.1;
- # XXX: technically it's _not guaranteed_ that IP addresses will be
- # issued from the first item in range onwards! We assume that in
- # our tests however.
range 192.168.${toString n}.2 192.168.${toString n}.254;
}
- '');
+ '')
+ ;
+ machines = flip map vlanIfs (vlan:
+ {
+ hostName = "client${toString vlan}";
+ ethernetAddress = qemu-flags.qemuNicMac vlan 1;
+ ipAddress = "192.168.${toString vlan}.2";
+ }
+ );
};
services.radvd = {
enable = true;
diff --git a/nixpkgs/nixos/tests/nextcloud/basic.nix b/nixpkgs/nixos/tests/nextcloud/basic.nix
index 9cbecf01f57..a8fa0cae6f0 100644
--- a/nixpkgs/nixos/tests/nextcloud/basic.nix
+++ b/nixpkgs/nixos/tests/nextcloud/basic.nix
@@ -26,7 +26,9 @@ in {
};
};
- nextcloud = { config, pkgs, ... }: {
+ nextcloud = { config, pkgs, ... }: let
+ cfg = config;
+ in {
networking.firewall.allowedTCPPorts = [ 80 ];
services.nextcloud = {
@@ -42,6 +44,8 @@ in {
startAt = "20:00";
};
};
+
+ environment.systemPackages = [ cfg.services.nextcloud.occ ];
};
};
@@ -67,6 +71,8 @@ in {
in ''
start_all()
nextcloud.wait_for_unit("multi-user.target")
+ # This is just to ensure the nextcloud-occ program is working
+ nextcloud.succeed("nextcloud-occ status")
nextcloud.succeed("curl -sSf http://nextcloud/login")
nextcloud.succeed(
"${withRcloneEnv} ${copySharedFile}"
diff --git a/nixpkgs/nixos/tests/nfs/kerberos.nix b/nixpkgs/nixos/tests/nfs/kerberos.nix
index 1f2d0d453ea..078f0b7814c 100644
--- a/nixpkgs/nixos/tests/nfs/kerberos.nix
+++ b/nixpkgs/nixos/tests/nfs/kerberos.nix
@@ -3,7 +3,7 @@ import ../make-test-python.nix ({ pkgs, lib, ... }:
with lib;
let
- krb5 =
+ krb5 =
{ enable = true;
domain_realm."nfs.test" = "NFS.TEST";
libdefaults.default_realm = "NFS.TEST";
@@ -31,7 +31,7 @@ in
{
name = "nfsv4-with-kerberos";
-
+
nodes = {
client = { lib, ... }:
{ inherit krb5 users;
diff --git a/nixpkgs/nixos/tests/nginx-variants.nix b/nixpkgs/nixos/tests/nginx-variants.nix
new file mode 100644
index 00000000000..ca4655391bc
--- /dev/null
+++ b/nixpkgs/nixos/tests/nginx-variants.nix
@@ -0,0 +1,33 @@
+{ system ? builtins.currentSystem,
+ config ? {},
+ pkgs ? import ../.. { inherit system config; }
+}:
+
+with import ../lib/testing-python.nix { inherit system pkgs; };
+
+builtins.listToAttrs (
+ builtins.map
+ (nginxName:
+ {
+ name = nginxName;
+ value = makeTest {
+ name = "nginx-variant-${nginxName}";
+
+ machine = { pkgs, ... }: {
+ services.nginx = {
+ enable = true;
+ virtualHosts.localhost.locations."/".return = "200 'foo'";
+ package = pkgs."${nginxName}";
+ };
+ };
+
+ testScript = ''
+ machine.wait_for_unit("nginx")
+ machine.wait_for_open_port(80)
+ machine.succeed('test "$(curl -fvvv http://localhost/)" = foo')
+ '';
+ };
+ }
+ )
+ [ "nginxStable" "nginxUnstable" "nginxShibboleth" "openresty" "tengine" ]
+)
diff --git a/nixpkgs/nixos/tests/plasma5.nix b/nixpkgs/nixos/tests/plasma5.nix
index 2eccfdf47f5..5a603f8cbfb 100644
--- a/nixpkgs/nixos/tests/plasma5.nix
+++ b/nixpkgs/nixos/tests/plasma5.nix
@@ -14,7 +14,7 @@ import ./make-test-python.nix ({ pkgs, ...} :
services.xserver.displayManager.sddm.enable = true;
services.xserver.displayManager.defaultSession = "plasma5";
services.xserver.desktopManager.plasma5.enable = true;
- services.xserver.displayManager.sddm.autoLogin = {
+ services.xserver.displayManager.autoLogin = {
enable = true;
user = "alice";
};
diff --git a/nixpkgs/nixos/tests/podman.nix b/nixpkgs/nixos/tests/podman.nix
index 9134a68ff38..cd8c2b4308c 100644
--- a/nixpkgs/nixos/tests/podman.nix
+++ b/nixpkgs/nixos/tests/podman.nix
@@ -12,9 +12,6 @@ import ./make-test-python.nix (
{ pkgs, ... }:
{
virtualisation.podman.enable = true;
- virtualisation.containers.users = [
- "alice"
- ];
users.users.alice = {
isNormalUser = true;
diff --git a/nixpkgs/nixos/tests/postfix-raise-smtpd-tls-security-level.nix b/nixpkgs/nixos/tests/postfix-raise-smtpd-tls-security-level.nix
new file mode 100644
index 00000000000..b3c2156122d
--- /dev/null
+++ b/nixpkgs/nixos/tests/postfix-raise-smtpd-tls-security-level.nix
@@ -0,0 +1,44 @@
+let
+ certs = import ./common/acme/server/snakeoil-certs.nix;
+in
+import ./make-test-python.nix {
+ name = "postfix";
+
+ machine = { pkgs, ... }: {
+ imports = [ common/user-account.nix ];
+ services.postfix = {
+ enable = true;
+ enableSubmissions = true;
+ submissionsOptions = {
+ smtpd_tls_security_level = "none";
+ };
+ };
+
+ environment.systemPackages = let
+ checkConfig = pkgs.writeScriptBin "check-config" ''
+ #!${pkgs.python3.interpreter}
+ import sys
+
+ state = 1
+ success = False
+
+ with open("/etc/postfix/master.cf") as masterCf:
+ for line in masterCf:
+ if state == 1 and line.startswith("submissions"):
+ state = 2
+ elif state == 2 and line.startswith(" ") and "smtpd_tls_security_level=encrypt" in line:
+ success = True
+ elif state == 2 and not line.startswith(" "):
+ state == 3
+ if not success:
+ sys.exit(1)
+ '';
+
+ in [ checkConfig ];
+ };
+
+ testScript = ''
+ machine.wait_for_unit("postfix.service")
+ machine.succeed("check-config")
+ '';
+}
diff --git a/nixpkgs/nixos/tests/postfix.nix b/nixpkgs/nixos/tests/postfix.nix
new file mode 100644
index 00000000000..b0674ca3a0d
--- /dev/null
+++ b/nixpkgs/nixos/tests/postfix.nix
@@ -0,0 +1,76 @@
+let
+ certs = import ./common/acme/server/snakeoil-certs.nix;
+in
+import ./make-test-python.nix {
+ name = "postfix";
+
+ machine = { pkgs, ... }: {
+ imports = [ common/user-account.nix ];
+ services.postfix = {
+ enable = true;
+ enableSubmission = true;
+ enableSubmissions = true;
+ sslCACert = certs.ca.cert;
+ sslCert = certs."acme.test".cert;
+ sslKey = certs."acme.test".key;
+ submissionsOptions = {
+ smtpd_sasl_auth_enable = "yes";
+ smtpd_client_restrictions = "permit";
+ milter_macro_daemon_name = "ORIGINATING";
+ };
+ };
+
+ security.pki.certificateFiles = [
+ certs.ca.cert
+ ];
+
+ networking.extraHosts = ''
+ 127.0.0.1 acme.test
+ '';
+
+ environment.systemPackages = let
+ sendTestMail = pkgs.writeScriptBin "send-testmail" ''
+ #!${pkgs.python3.interpreter}
+ import smtplib
+
+ with smtplib.SMTP('acme.test') as smtp:
+ smtp.sendmail('root@localhost', 'alice@localhost', 'Subject: Test\n\nTest data.')
+ smtp.quit()
+ '';
+
+ sendTestMailStarttls = pkgs.writeScriptBin "send-testmail-starttls" ''
+ #!${pkgs.python3.interpreter}
+ import smtplib
+ import ssl
+
+ ctx = ssl.create_default_context()
+
+ with smtplib.SMTP('acme.test') as smtp:
+ smtp.ehlo()
+ smtp.starttls(context=ctx)
+ smtp.ehlo()
+ smtp.sendmail('root@localhost', 'alice@localhost', 'Subject: Test STARTTLS\n\nTest data.')
+ smtp.quit()
+ '';
+
+ sendTestMailSmtps = pkgs.writeScriptBin "send-testmail-smtps" ''
+ #!${pkgs.python3.interpreter}
+ import smtplib
+ import ssl
+
+ ctx = ssl.create_default_context()
+
+ with smtplib.SMTP_SSL(host='acme.test', context=ctx) as smtp:
+ smtp.sendmail('root@localhost', 'alice@localhost', 'Subject: Test SMTPS\n\nTest data.')
+ smtp.quit()
+ '';
+ in [ sendTestMail sendTestMailStarttls sendTestMailSmtps ];
+ };
+
+ testScript = ''
+ machine.wait_for_unit("postfix.service")
+ machine.succeed("send-testmail")
+ machine.succeed("send-testmail-starttls")
+ machine.succeed("send-testmail-smtps")
+ '';
+}
diff --git a/nixpkgs/nixos/tests/prometheus-exporters.nix b/nixpkgs/nixos/tests/prometheus-exporters.nix
index 4fc3668cfaf..b912e3425e0 100644
--- a/nixpkgs/nixos/tests/prometheus-exporters.nix
+++ b/nixpkgs/nixos/tests/prometheus-exporters.nix
@@ -56,6 +56,21 @@ let
*/
exporterTests = {
+ apcupsd = {
+ exporterConfig = {
+ enable = true;
+ };
+ metricProvider = {
+ services.apcupsd.enable = true;
+ };
+ exporterTest = ''
+ wait_for_unit("apcupsd.service")
+ wait_for_open_port(3551)
+ wait_for_unit("prometheus-apcupsd-exporter.service")
+ wait_for_open_port(9162)
+ succeed("curl -sSf http://localhost:9162/metrics | grep -q 'apcupsd_info'")
+ '';
+ };
bind = {
exporterConfig = {
@@ -202,6 +217,69 @@ let
'';
};
+ keylight = {
+ # A hardware device is required to properly test this exporter, so just
+ # perform a couple of basic sanity checks that the exporter is running
+ # and requires a target, but cannot reach a specified target.
+ exporterConfig = {
+ enable = true;
+ };
+ exporterTest = ''
+ wait_for_unit("prometheus-keylight-exporter.service")
+ wait_for_open_port(9288)
+ succeed(
+ "curl -sS --write-out '%{http_code}' -o /dev/null http://localhost:9288/metrics | grep -q '400'"
+ )
+ succeed(
+ "curl -sS --write-out '%{http_code}' -o /dev/null http://localhost:9288/metrics?target=nosuchdevice | grep -q '500'"
+ )
+ '';
+ };
+
+ lnd = {
+ exporterConfig = {
+ enable = true;
+ lndTlsPath = "/var/lib/lnd/tls.cert";
+ lndMacaroonDir = "/var/lib/lnd";
+ };
+ metricProvider = {
+ systemd.services.prometheus-lnd-exporter.serviceConfig.DynamicUser = false;
+ services.bitcoind.enable = true;
+ services.bitcoind.extraConfig = ''
+ rpcauth=bitcoinrpc:e8fe33f797e698ac258c16c8d7aadfbe$872bdb8f4d787367c26bcfd75e6c23c4f19d44a69f5d1ad329e5adf3f82710f7
+ bitcoind.zmqpubrawblock=tcp://127.0.0.1:28332
+ bitcoind.zmqpubrawtx=tcp://127.0.0.1:28333
+ '';
+ systemd.services.lnd = {
+ serviceConfig.ExecStart = ''
+ ${pkgs.lnd}/bin/lnd \
+ --datadir=/var/lib/lnd \
+ --tlscertpath=/var/lib/lnd/tls.cert \
+ --tlskeypath=/var/lib/lnd/tls.key \
+ --logdir=/var/log/lnd \
+ --bitcoin.active \
+ --bitcoin.mainnet \
+ --bitcoin.node=bitcoind \
+ --bitcoind.rpcuser=bitcoinrpc \
+ --bitcoind.rpcpass=hunter2 \
+ --bitcoind.zmqpubrawblock=tcp://127.0.0.1:28332 \
+ --bitcoind.zmqpubrawtx=tcp://127.0.0.1:28333 \
+ --readonlymacaroonpath=/var/lib/lnd/readonly.macaroon
+ '';
+ serviceConfig.StateDirectory = "lnd";
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network.target" ];
+ };
+ };
+ exporterTest = ''
+ wait_for_unit("lnd.service")
+ wait_for_open_port(10009)
+ wait_for_unit("prometheus-lnd-exporter.service")
+ wait_for_open_port(9092)
+ succeed("curl -sSf localhost:9092/metrics | grep -q '^promhttp_metric_handler'")
+ '';
+ };
+
mail = {
exporterConfig = {
enable = true;
@@ -285,6 +363,31 @@ let
'';
};
+ modemmanager = {
+ exporterConfig = {
+ enable = true;
+ refreshRate = "10s";
+ };
+ metricProvider = {
+ # ModemManager is installed when NetworkManager is enabled. Ensure it is
+ # started and is wanted by NM and the exporter to start everything up
+ # in the right order.
+ networking.networkmanager.enable = true;
+ systemd.services.ModemManager = {
+ enable = true;
+ wantedBy = [ "NetworkManager.service" "prometheus-modemmanager-exporter.service" ];
+ };
+ };
+ exporterTest = ''
+ wait_for_unit("ModemManager.service")
+ wait_for_unit("prometheus-modemmanager-exporter.service")
+ wait_for_open_port(9539)
+ succeed(
+ "curl -sSf http://localhost:9539/metrics | grep -q 'modemmanager_info'"
+ )
+ '';
+ };
+
nextcloud = {
exporterConfig = {
enable = true;
@@ -397,6 +500,20 @@ let
'';
};
+ redis = {
+ exporterConfig = {
+ enable = true;
+ };
+ metricProvider.services.redis.enable = true;
+ exporterTest = ''
+ wait_for_unit("redis.service")
+ wait_for_unit("prometheus-redis-exporter.service")
+ wait_for_open_port(6379)
+ wait_for_open_port(9121)
+ wait_until_succeeds("curl -sSf localhost:9121/metrics | grep -q 'redis_up 1'")
+ '';
+ };
+
rspamd = {
exporterConfig = {
enable = true;
diff --git a/nixpkgs/nixos/tests/pt2-clone.nix b/nixpkgs/nixos/tests/pt2-clone.nix
new file mode 100644
index 00000000000..b502172e2ee
--- /dev/null
+++ b/nixpkgs/nixos/tests/pt2-clone.nix
@@ -0,0 +1,35 @@
+import ./make-test-python.nix ({ pkgs, ... }: {
+ name = "pt2-clone";
+ meta = with pkgs.stdenv.lib.maintainers; {
+ maintainers = [ fgaz ];
+ };
+
+ machine = { config, pkgs, ... }: {
+ imports = [
+ ./common/x11.nix
+ ];
+
+ services.xserver.enable = true;
+ sound.enable = true;
+ environment.systemPackages = [ pkgs.pt2-clone ];
+ };
+
+ enableOCR = true;
+
+ testScript =
+ ''
+ machine.wait_for_x()
+ # Add a dummy sound card, or the program won't start
+ machine.execute("modprobe snd-dummy")
+
+ machine.execute("pt2-clone &")
+
+ machine.wait_for_window(r"ProTracker")
+ machine.sleep(5)
+ # One of the few words that actually get recognized
+ if "LENGTH" not in machine.get_screen_text():
+ raise Exception("Program did not start successfully")
+ machine.screenshot("screen")
+ '';
+})
+
diff --git a/nixpkgs/nixos/tests/qboot.nix b/nixpkgs/nixos/tests/qboot.nix
new file mode 100644
index 00000000000..12aef6decfa
--- /dev/null
+++ b/nixpkgs/nixos/tests/qboot.nix
@@ -0,0 +1,13 @@
+import ./make-test-python.nix ({ pkgs, ...} : {
+ name = "qboot";
+
+ machine = { ... }: {
+ virtualisation.bios = pkgs.qboot;
+ };
+
+ testScript =
+ ''
+ start_all()
+ machine.wait_for_unit("multi-user.target")
+ '';
+})
diff --git a/nixpkgs/nixos/tests/radicale.nix b/nixpkgs/nixos/tests/radicale.nix
index c81e78a8f99..1d3679c82a2 100644
--- a/nixpkgs/nixos/tests/radicale.nix
+++ b/nixpkgs/nixos/tests/radicale.nix
@@ -14,9 +14,6 @@ let
[storage]
filesystem_folder = /tmp/collections
-
- [logging]
- debug = True
'';
};
# WARNING: DON'T DO THIS IN PRODUCTION!
@@ -49,13 +46,18 @@ in
services.radicale.extraArgs = [
"--export-storage" "/tmp/collections-new"
];
+ system.stateVersion = "17.03";
};
radicale2_verify = lib.recursiveUpdate radicale2 {
- services.radicale.extraArgs = [ "--verify-storage" ];
+ services.radicale.extraArgs = [ "--debug" "--verify-storage" ];
+ system.stateVersion = "17.09";
};
radicale2 = lib.recursiveUpdate (common args) {
system.stateVersion = "17.09";
};
+ radicale3 = lib.recursiveUpdate (common args) {
+ system.stateVersion = "20.09";
+ };
};
# This tests whether the web interface is accessible to an authenticated user
@@ -117,6 +119,22 @@ in
retcode == 0 and "VCALENDAR" in output
), "Could not read calendar from Radicale 2"
- radicale.succeed("curl --fail http://${user}:${password}@localhost:${port}/.web/")
+ radicale.succeed("curl --fail http://${user}:${password}@localhost:${port}/.web/")
+
+ with subtest("Check Radicale 3 functionality"):
+ radicale.succeed(
+ "${switchToConfig "radicale3"} >&2"
+ )
+ radicale.wait_for_unit("radicale.service")
+ radicale.wait_for_open_port(${port})
+
+ (retcode, output) = radicale.execute(
+ "curl --fail http://${user}:${password}@localhost:${port}/someuser/calendar.ics/"
+ )
+ assert (
+ retcode == 0 and "VCALENDAR" in output
+ ), "Could not read calendar from Radicale 3"
+
+ radicale.succeed("curl --fail http://${user}:${password}@localhost:${port}/.web/")
'';
})
diff --git a/nixpkgs/nixos/tests/restic.nix b/nixpkgs/nixos/tests/restic.nix
index 67bb7f1933d..dad5bdfff27 100644
--- a/nixpkgs/nixos/tests/restic.nix
+++ b/nixpkgs/nixos/tests/restic.nix
@@ -4,33 +4,50 @@ import ./make-test-python.nix (
let
password = "some_password";
repository = "/tmp/restic-backup";
- passwordFile = pkgs.writeText "password" "correcthorsebatterystaple";
+ rcloneRepository = "rclone:local:/tmp/restic-rclone-backup";
+
+ passwordFile = "${pkgs.writeText "password" "correcthorsebatterystaple"}";
+ initialize = true;
+ paths = [ "/opt" ];
+ pruneOpts = [
+ "--keep-daily 2"
+ "--keep-weekly 1"
+ "--keep-monthly 1"
+ "--keep-yearly 99"
+ ];
in
{
name = "restic";
meta = with pkgs.stdenv.lib.maintainers; {
- maintainers = [ bbigras ];
+ maintainers = [ bbigras i077 ];
};
nodes = {
server =
- { ... }:
+ { pkgs, ... }:
{
services.restic.backups = {
remotebackup = {
- inherit repository;
- passwordFile = "${passwordFile}";
- initialize = true;
- paths = [ "/opt" ];
- pruneOpts = [
- "--keep-daily 2"
- "--keep-weekly 1"
- "--keep-monthly 1"
- "--keep-yearly 99"
- ];
+ inherit repository passwordFile initialize paths pruneOpts;
+ };
+ rclonebackup = {
+ repository = rcloneRepository;
+ rcloneConfig = {
+ type = "local";
+ one_file_system = true;
+ };
+
+ # This gets overridden by rcloneConfig.type
+ rcloneConfigFile = pkgs.writeText "rclone.conf" ''
+ [local]
+ type=ftp
+ '';
+ inherit passwordFile initialize paths pruneOpts;
};
};
+
+ environment.sessionVariables.RCLONE_CONFIG_LOCAL_TYPE = "local";
};
};
@@ -38,25 +55,35 @@ import ./make-test-python.nix (
server.start()
server.wait_for_unit("dbus.socket")
server.fail(
- "${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots"
+ "${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots",
+ "${pkgs.restic}/bin/restic -r ${rcloneRepository} -p ${passwordFile} snapshots",
)
server.succeed(
"mkdir -p /opt",
"touch /opt/some_file",
+ "mkdir -p /tmp/restic-rclone-backup",
"timedatectl set-time '2016-12-13 13:45'",
"systemctl start restic-backups-remotebackup.service",
+ "systemctl start restic-backups-rclonebackup.service",
'${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots -c | grep -e "^1 snapshot"',
+ '${pkgs.restic}/bin/restic -r ${rcloneRepository} -p ${passwordFile} snapshots -c | grep -e "^1 snapshot"',
"timedatectl set-time '2017-12-13 13:45'",
"systemctl start restic-backups-remotebackup.service",
+ "systemctl start restic-backups-rclonebackup.service",
"timedatectl set-time '2018-12-13 13:45'",
"systemctl start restic-backups-remotebackup.service",
+ "systemctl start restic-backups-rclonebackup.service",
"timedatectl set-time '2018-12-14 13:45'",
"systemctl start restic-backups-remotebackup.service",
+ "systemctl start restic-backups-rclonebackup.service",
"timedatectl set-time '2018-12-15 13:45'",
"systemctl start restic-backups-remotebackup.service",
+ "systemctl start restic-backups-rclonebackup.service",
"timedatectl set-time '2018-12-16 13:45'",
"systemctl start restic-backups-remotebackup.service",
+ "systemctl start restic-backups-rclonebackup.service",
'${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots -c | grep -e "^4 snapshot"',
+ '${pkgs.restic}/bin/restic -r ${rcloneRepository} -p ${passwordFile} snapshots -c | grep -e "^4 snapshot"',
)
'';
}
diff --git a/nixpkgs/nixos/tests/sddm.nix b/nixpkgs/nixos/tests/sddm.nix
index a145705250f..f9b961163c3 100644
--- a/nixpkgs/nixos/tests/sddm.nix
+++ b/nixpkgs/nixos/tests/sddm.nix
@@ -44,8 +44,8 @@ let
machine = { ... }: {
imports = [ ./common/user-account.nix ];
services.xserver.enable = true;
- services.xserver.displayManager.sddm = {
- enable = true;
+ services.xserver.displayManager = {
+ sddm.enable = true;
autoLogin = {
enable = true;
user = "alice";
diff --git a/nixpkgs/nixos/tests/slurm.nix b/nixpkgs/nixos/tests/slurm.nix
index d0e62d15437..a54c5d9db48 100644
--- a/nixpkgs/nixos/tests/slurm.nix
+++ b/nixpkgs/nixos/tests/slurm.nix
@@ -1,16 +1,52 @@
-import ./make-test-python.nix ({ lib, ... }:
+import ./make-test-python.nix ({ lib, pkgs, ... }:
let
- mungekey = "mungeverryweakkeybuteasytointegratoinatest";
-
slurmconfig = {
- controlMachine = "control";
- nodeName = [ "node[1-3] CPUs=1 State=UNKNOWN" ];
- partitionName = [ "debug Nodes=node[1-3] Default=YES MaxTime=INFINITE State=UP" ];
- extraConfig = ''
- AccountingStorageHost=dbd
- AccountingStorageType=accounting_storage/slurmdbd
- '';
+ services.slurm = {
+ controlMachine = "control";
+ nodeName = [ "node[1-3] CPUs=1 State=UNKNOWN" ];
+ partitionName = [ "debug Nodes=node[1-3] Default=YES MaxTime=INFINITE State=UP" ];
+ extraConfig = ''
+ AccountingStorageHost=dbd
+ AccountingStorageType=accounting_storage/slurmdbd
+ '';
+ };
+ environment.systemPackages = [ mpitest ];
+ networking.firewall.enable = false;
+ systemd.tmpfiles.rules = [
+ "f /etc/munge/munge.key 0400 munge munge - mungeverryweakkeybuteasytointegratoinatest"
+ ];
};
+
+ mpitest = let
+ mpitestC = pkgs.writeText "mpitest.c" ''
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <mpi.h>
+
+ int
+ main (int argc, char *argv[])
+ {
+ int rank, size, length;
+ char name[512];
+
+ MPI_Init (&argc, &argv);
+ MPI_Comm_rank (MPI_COMM_WORLD, &rank);
+ MPI_Comm_size (MPI_COMM_WORLD, &size);
+ MPI_Get_processor_name (name, &length);
+
+ if ( rank == 0 ) printf("size=%d\n", size);
+
+ printf ("%s: hello world from process %d of %d\n", name, rank, size);
+
+ MPI_Finalize ();
+
+ return EXIT_SUCCESS;
+ }
+ '';
+ in pkgs.runCommandNoCC "mpitest" {} ''
+ mkdir -p $out/bin
+ ${pkgs.openmpi}/bin/mpicc ${mpitestC} -o $out/bin/mpitest
+ '';
in {
name = "slurm";
@@ -21,37 +57,40 @@ in {
computeNode =
{ ...}:
{
+ imports = [ slurmconfig ];
# TODO slurmd port and slurmctld port should be configurations and
# automatically allowed by the firewall.
- networking.firewall.enable = false;
services.slurm = {
client.enable = true;
- } // slurmconfig;
+ };
};
in {
control =
{ ...}:
{
- networking.firewall.enable = false;
+ imports = [ slurmconfig ];
services.slurm = {
server.enable = true;
- } // slurmconfig;
+ };
};
submit =
{ ...}:
{
- networking.firewall.enable = false;
+ imports = [ slurmconfig ];
services.slurm = {
enableStools = true;
- } // slurmconfig;
+ };
};
dbd =
{ pkgs, ... } :
{
networking.firewall.enable = false;
+ systemd.tmpfiles.rules = [
+ "f /etc/munge/munge.key 0400 munge munge - mungeverryweakkeybuteasytointegratoinatest"
+ ];
services.slurm.dbdserver = {
enable = true;
storagePass = "password123";
@@ -87,24 +126,7 @@ in {
''
start_all()
- # Set up authentification across the cluster
- for node in [submit, control, dbd, node1, node2, node3]:
-
- node.wait_for_unit("default.target")
-
- node.succeed("mkdir /etc/munge")
- node.succeed(
- "echo '${mungekey}' > /etc/munge/munge.key"
- )
- node.succeed("chmod 0400 /etc/munge/munge.key")
- node.succeed("chown munge:munge /etc/munge/munge.key")
- node.succeed("systemctl restart munged")
-
- node.wait_for_unit("munged")
-
-
- # Restart the services since they have probably failed due to the munge init
- # failure
+ # Make sure DBD is up after DB initialzation
with subtest("can_start_slurmdbd"):
dbd.succeed("systemctl restart slurmdbd")
dbd.wait_for_unit("slurmdbd.service")
@@ -137,5 +159,8 @@ in {
# find the srun job from above in the database
control.succeed("sleep 5")
control.succeed("sacct | grep hostname")
+
+ with subtest("run_PMIx_mpitest"):
+ submit.succeed("srun -N 3 --mpi=pmix mpitest | grep size=3")
'';
})
diff --git a/nixpkgs/nixos/tests/snapcast.nix b/nixpkgs/nixos/tests/snapcast.nix
new file mode 100644
index 00000000000..92534f10281
--- /dev/null
+++ b/nixpkgs/nixos/tests/snapcast.nix
@@ -0,0 +1,58 @@
+import ./make-test-python.nix ({ pkgs, ...} :
+
+let
+ port = 10004;
+ tcpPort = 10005;
+ httpPort = 10080;
+in {
+ name = "snapcast";
+ meta = with pkgs.stdenv.lib.maintainers; {
+ maintainers = [ hexa ];
+ };
+
+ nodes = {
+ server = {
+ services.snapserver = {
+ enable = true;
+ port = port;
+ tcp.port = tcpPort;
+ http.port = httpPort;
+ streams = {
+ mpd = {
+ type = "pipe";
+ location = "/run/snapserver/mpd";
+ };
+ bluetooth = {
+ type = "pipe";
+ location = "/run/snapserver/bluetooth";
+ };
+ };
+ };
+ };
+ };
+
+ testScript = ''
+ import json
+
+ get_rpc_version = {"id": "1", "jsonrpc": "2.0", "method": "Server.GetRPCVersion"}
+
+ start_all()
+
+ server.wait_for_unit("snapserver.service")
+ server.wait_until_succeeds("ss -ntl | grep -q ${toString port}")
+ server.wait_until_succeeds("ss -ntl | grep -q ${toString tcpPort}")
+ server.wait_until_succeeds("ss -ntl | grep -q ${toString httpPort}")
+
+ with subtest("check that pipes are created"):
+ server.succeed("test -p /run/snapserver/mpd")
+ server.succeed("test -p /run/snapserver/bluetooth")
+
+ with subtest("test tcp json-rpc"):
+ server.succeed(f"echo '{json.dumps(get_rpc_version)}' | nc -w 1 localhost ${toString tcpPort}")
+
+ with subtest("test http json-rpc"):
+ server.succeed(
+ "curl --fail http://localhost:${toString httpPort}/jsonrpc -d '{json.dumps(get_rpc_version)}'"
+ )
+ '';
+})
diff --git a/nixpkgs/nixos/tests/sslh.nix b/nixpkgs/nixos/tests/sslh.nix
new file mode 100644
index 00000000000..2a800aa52d0
--- /dev/null
+++ b/nixpkgs/nixos/tests/sslh.nix
@@ -0,0 +1,83 @@
+import ./make-test-python.nix {
+ name = "sslh";
+
+ nodes = {
+ server = { pkgs, lib, ... }: {
+ networking.firewall.allowedTCPPorts = [ 443 ];
+ networking.interfaces.eth1.ipv6.addresses = [
+ {
+ address = "fe00:aa:bb:cc::2";
+ prefixLength = 64;
+ }
+ ];
+ # sslh is really slow when reverse dns does not work
+ networking.hosts = {
+ "fe00:aa:bb:cc::2" = [ "server" ];
+ "fe00:aa:bb:cc::1" = [ "client" ];
+ };
+ services.sslh = {
+ enable = true;
+ transparent = true;
+ appendConfig = ''
+ protocols:
+ (
+ { name: "ssh"; service: "ssh"; host: "localhost"; port: "22"; probe: "builtin"; },
+ { name: "http"; host: "localhost"; port: "80"; probe: "builtin"; },
+ );
+ '';
+ };
+ services.openssh.enable = true;
+ users.users.root.openssh.authorizedKeys.keyFiles = [ ./initrd-network-ssh/id_ed25519.pub ];
+ services.nginx = {
+ enable = true;
+ virtualHosts."localhost" = {
+ addSSL = false;
+ default = true;
+ root = pkgs.runCommand "testdir" {} ''
+ mkdir "$out"
+ echo hello world > "$out/index.html"
+ '';
+ };
+ };
+ };
+ client = { ... }: {
+ networking.interfaces.eth1.ipv6.addresses = [
+ {
+ address = "fe00:aa:bb:cc::1";
+ prefixLength = 64;
+ }
+ ];
+ networking.hosts."fe00:aa:bb:cc::2" = [ "server" ];
+ environment.etc.sshKey = {
+ source = ./initrd-network-ssh/id_ed25519; # dont use this anywhere else
+ mode = "0600";
+ };
+ };
+ };
+
+ testScript = ''
+ start_all()
+
+ server.wait_for_unit("sslh.service")
+ server.wait_for_unit("nginx.service")
+ server.wait_for_unit("sshd.service")
+ server.wait_for_open_port(80)
+ server.wait_for_open_port(443)
+ server.wait_for_open_port(22)
+
+ for arg in ["-6", "-4"]:
+ client.wait_until_succeeds(f"ping {arg} -c1 server")
+
+ # check that ssh through sslh works
+ client.succeed(
+ f"ssh {arg} -p 443 -i /etc/sshKey -o StrictHostKeyChecking=accept-new server 'echo $SSH_CONNECTION > /tmp/foo{arg}'"
+ )
+
+ # check that 1/ the above ssh command had an effect 2/ transparent proxying really works
+ ip = "fe00:aa:bb:cc::1" if arg == "-6" else "192.168.1."
+ server.succeed(f"grep '{ip}' /tmp/foo{arg}")
+
+ # check that http through sslh works
+ assert client.succeed(f"curl {arg} http://server:443").strip() == "hello world"
+ '';
+}
diff --git a/nixpkgs/nixos/tests/sudo.nix b/nixpkgs/nixos/tests/sudo.nix
index 5bbec3d5726..8c38f1b47ef 100644
--- a/nixpkgs/nixos/tests/sudo.nix
+++ b/nixpkgs/nixos/tests/sudo.nix
@@ -74,7 +74,7 @@ in
with subtest("test5 user should not be able to run commands under root"):
machine.fail("sudo -u test5 sudo -n -u root true")
- with subtest("test5 user should be able to keep his environment"):
+ with subtest("test5 user should be able to keep their environment"):
machine.succeed("sudo -u test5 sudo -n -E -u test1 true")
with subtest("users in group 'barfoo' should not be able to keep their environment"):
diff --git a/nixpkgs/nixos/tests/syncthing-init.nix b/nixpkgs/nixos/tests/syncthing-init.nix
index 9c8e0a3d087..0a01da52b68 100644
--- a/nixpkgs/nixos/tests/syncthing-init.nix
+++ b/nixpkgs/nixos/tests/syncthing-init.nix
@@ -24,9 +24,8 @@ in {
testScript = ''
machine.wait_for_unit("syncthing-init.service")
config = machine.succeed("cat /var/lib/syncthing/.config/syncthing/config.xml")
-
+
assert "testFolder" in config
assert "${testId}" in config
'';
})
-
diff --git a/nixpkgs/nixos/tests/syncthing.nix b/nixpkgs/nixos/tests/syncthing.nix
new file mode 100644
index 00000000000..9e2a8e01e3f
--- /dev/null
+++ b/nixpkgs/nixos/tests/syncthing.nix
@@ -0,0 +1,65 @@
+import ./make-test-python.nix ({ lib, pkgs, ... }: {
+ name = "syncthing";
+ meta.maintainers = with pkgs.stdenv.lib.maintainers; [ chkno ];
+
+ nodes = rec {
+ a = {
+ environment.systemPackages = with pkgs; [ curl libxml2 syncthing ];
+ services.syncthing = {
+ enable = true;
+ openDefaultPorts = true;
+ };
+ };
+ b = a;
+ };
+
+ testScript = ''
+ import json
+ import shlex
+
+ confdir = "/var/lib/syncthing/.config/syncthing"
+
+
+ def addPeer(host, name, deviceID):
+ APIKey = host.succeed(
+ "xmllint --xpath 'string(configuration/gui/apikey)' %s/config.xml" % confdir
+ ).strip()
+ oldConf = host.succeed(
+ "curl -Ss -H 'X-API-Key: %s' 127.0.0.1:8384/rest/system/config" % APIKey
+ )
+ conf = json.loads(oldConf)
+ conf["devices"].append({"deviceID": deviceID, "id": name})
+ conf["folders"].append(
+ {
+ "devices": [{"deviceID": deviceID}],
+ "id": "foo",
+ "path": "/var/lib/syncthing/foo",
+ "rescanIntervalS": 1,
+ }
+ )
+ newConf = json.dumps(conf)
+ host.succeed(
+ "curl -Ss -H 'X-API-Key: %s' 127.0.0.1:8384/rest/system/config -d %s"
+ % (APIKey, shlex.quote(newConf))
+ )
+
+
+ start_all()
+ a.wait_for_unit("syncthing.service")
+ b.wait_for_unit("syncthing.service")
+ a.wait_for_open_port(22000)
+ b.wait_for_open_port(22000)
+
+ aDeviceID = a.succeed("syncthing -home=%s -device-id" % confdir).strip()
+ bDeviceID = b.succeed("syncthing -home=%s -device-id" % confdir).strip()
+ addPeer(a, "b", bDeviceID)
+ addPeer(b, "a", aDeviceID)
+
+ a.wait_for_file("/var/lib/syncthing/foo")
+ b.wait_for_file("/var/lib/syncthing/foo")
+ a.succeed("echo a2b > /var/lib/syncthing/foo/a2b")
+ b.succeed("echo b2a > /var/lib/syncthing/foo/b2a")
+ a.wait_for_file("/var/lib/syncthing/foo/b2a")
+ b.wait_for_file("/var/lib/syncthing/foo/a2b")
+ '';
+})
diff --git a/nixpkgs/nixos/tests/systemd-boot.nix b/nixpkgs/nixos/tests/systemd-boot.nix
index e911c393361..7a663dd9b42 100644
--- a/nixpkgs/nixos/tests/systemd-boot.nix
+++ b/nixpkgs/nixos/tests/systemd-boot.nix
@@ -6,26 +6,85 @@
with import ../lib/testing-python.nix { inherit system pkgs; };
with pkgs.lib;
-makeTest {
- name = "systemd-boot";
- meta.maintainers = with pkgs.stdenv.lib.maintainers; [ danielfullmer ];
-
- machine = { pkgs, lib, ... }: {
+let
+ common = {
virtualisation.useBootLoader = true;
virtualisation.useEFIBoot = true;
boot.loader.systemd-boot.enable = true;
+ boot.loader.efi.canTouchEfiVariables = true;
+ environment.systemPackages = [ pkgs.efibootmgr ];
};
+in
+{
+ basic = makeTest {
+ name = "systemd-boot";
+ meta.maintainers = with pkgs.stdenv.lib.maintainers; [ danielfullmer ];
+
+ machine = common;
+
+ testScript = ''
+ machine.start()
+ machine.wait_for_unit("multi-user.target")
+
+ machine.succeed("test -e /boot/loader/entries/nixos-generation-1.conf")
+
+ # Ensure we actually booted using systemd-boot
+ # Magic number is the vendor UUID used by systemd-boot.
+ machine.succeed(
+ "test -e /sys/firmware/efi/efivars/LoaderEntrySelected-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f"
+ )
+
+ # "bootctl install" should have created an EFI entry
+ machine.succeed('efibootmgr | grep "Linux Boot Manager"')
+ '';
+ };
+
+ # Boot without having created an EFI entry--instead using default "/EFI/BOOT/BOOTX64.EFI"
+ fallback = makeTest {
+ name = "systemd-boot-fallback";
+ meta.maintainers = with pkgs.stdenv.lib.maintainers; [ danielfullmer ];
+
+ machine = { pkgs, lib, ... }: {
+ imports = [ common ];
+ boot.loader.efi.canTouchEfiVariables = mkForce false;
+ };
- testScript = ''
- machine.start()
- machine.wait_for_unit("multi-user.target")
+ testScript = ''
+ machine.start()
+ machine.wait_for_unit("multi-user.target")
- machine.succeed("test -e /boot/loader/entries/nixos-generation-1.conf")
+ machine.succeed("test -e /boot/loader/entries/nixos-generation-1.conf")
- # Ensure we actually booted using systemd-boot.
- # Magic number is the vendor UUID used by systemd-boot.
- machine.succeed(
- "test -e /sys/firmware/efi/efivars/LoaderEntrySelected-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f"
- )
- '';
+ # Ensure we actually booted using systemd-boot
+ # Magic number is the vendor UUID used by systemd-boot.
+ machine.succeed(
+ "test -e /sys/firmware/efi/efivars/LoaderEntrySelected-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f"
+ )
+
+ # "bootctl install" should _not_ have created an EFI entry
+ machine.fail('efibootmgr | grep "Linux Boot Manager"')
+ '';
+ };
+
+ update = makeTest {
+ name = "systemd-boot-update";
+ meta.maintainers = with pkgs.stdenv.lib.maintainers; [ danielfullmer ];
+
+ machine = common;
+
+ testScript = ''
+ machine.succeed("mount -o remount,rw /boot")
+
+ # Replace version inside sd-boot with something older. See magic[] string in systemd src/boot/efi/boot.c
+ machine.succeed(
+ """
+ find /boot -iname '*.efi' -print0 | \
+ xargs -0 -I '{}' sed -i 's/#### LoaderInfo: systemd-boot .* ####/#### LoaderInfo: systemd-boot 001 ####/' '{}'
+ """
+ )
+
+ output = machine.succeed("/run/current-system/bin/switch-to-configuration boot")
+ assert "updating systemd-boot from 001 to " in output
+ '';
+ };
}
diff --git a/nixpkgs/nixos/tests/systemd-networkd-vrf.nix b/nixpkgs/nixos/tests/systemd-networkd-vrf.nix
index af7813a2e60..bd4751f8e43 100644
--- a/nixpkgs/nixos/tests/systemd-networkd-vrf.nix
+++ b/nixpkgs/nixos/tests/systemd-networkd-vrf.nix
@@ -159,6 +159,8 @@ in {
node2.wait_for_unit("network.target")
node3.wait_for_unit("network.target")
+ # NOTE: please keep in mind that the trailing whitespaces in the following strings
+ # are intentional as the output is compared against the raw `iproute2`-output.
client_ipv4_table = """
192.168.1.2 dev vrf1 proto static metric 100
192.168.2.3 dev vrf2 proto static metric 100
@@ -194,18 +196,16 @@ in {
client.succeed("ping -c5 192.168.1.2")
client.succeed("ping -c5 192.168.2.3")
- # Test whether SSH through a VRF IP is possible.
- # (Note: this seems to be an issue on Linux 5.x, so I decided to add this to
- # ensure that we catch this when updating the default kernel).
- # with subtest("tcp traffic through vrf works"):
- # node1.wait_for_open_port(22)
- # client.succeed(
- # "cat ${snakeOilPrivateKey} > privkey.snakeoil"
- # )
- # client.succeed("chmod 600 privkey.snakeoil")
- # client.succeed(
- # "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i privkey.snakeoil root@192.168.1.2 true"
- # )
+ # Test whether TCP through a VRF IP is possible.
+ with subtest("tcp traffic through vrf works"):
+ node1.wait_for_open_port(22)
+ client.succeed(
+ "cat ${snakeOilPrivateKey} > privkey.snakeoil"
+ )
+ client.succeed("chmod 600 privkey.snakeoil")
+ client.succeed(
+ "ulimit -l 2048; ip vrf exec vrf1 ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i privkey.snakeoil root@192.168.1.2 true"
+ )
# Only configured routes through the VRF from the main routing table should
# work. Additional IPs are only reachable when binding to the vrf interface.
diff --git a/nixpkgs/nixos/tests/systemd.nix b/nixpkgs/nixos/tests/systemd.nix
index ca2e36a443e..a653932fb37 100644
--- a/nixpkgs/nixos/tests/systemd.nix
+++ b/nixpkgs/nixos/tests/systemd.nix
@@ -50,6 +50,13 @@ import ./make-test-python.nix ({ pkgs, ... }: {
fi
'';
};
+
+ systemd.watchdog = {
+ device = "/dev/watchdog";
+ runtimeTime = "30s";
+ rebootTime = "10min";
+ kexecTime = "5min";
+ };
};
testScript = ''
@@ -97,6 +104,11 @@ import ./make-test-python.nix ({ pkgs, ... }: {
re.search(r"^Filesystem state: *clean$", extinfo, re.MULTILINE) is not None
), ("File system was not cleanly unmounted: " + extinfo)
+ # Regression test for https://github.com/NixOS/nixpkgs/pull/91232
+ with subtest("setting transient hostnames works"):
+ machine.succeed("hostnamectl set-hostname --transient machine-transient")
+ machine.fail("hostnamectl set-hostname machine-all")
+
with subtest("systemd-shutdown works"):
machine.shutdown()
machine.wait_for_unit("multi-user.target")
@@ -117,5 +129,20 @@ import ./make-test-python.nix ({ pkgs, ... }: {
retcode, output = machine.execute("systemctl status testservice1.service")
assert retcode in [0, 3] # https://bugs.freedesktop.org/show_bug.cgi?id=77507
assert "CPU:" in output
+
+ # Test systemd is configured to manage a watchdog
+ with subtest("systemd manages hardware watchdog"):
+ machine.wait_for_unit("multi-user.target")
+
+ # It seems that the device's path doesn't appear in 'systemctl show' so
+ # check it separately.
+ assert "WatchdogDevice=/dev/watchdog" in machine.succeed(
+ "cat /etc/systemd/system.conf"
+ )
+
+ output = machine.succeed("systemctl show | grep Watchdog")
+ assert "RuntimeWatchdogUSec=30s" in output
+ assert "RebootWatchdogUSec=10m" in output
+ assert "KExecWatchdogUSec=5m" in output
'';
})
diff --git a/nixpkgs/nixos/tests/taskserver.nix b/nixpkgs/nixos/tests/taskserver.nix
index ab9b589f859..f34782c7059 100644
--- a/nixpkgs/nixos/tests/taskserver.nix
+++ b/nixpkgs/nixos/tests/taskserver.nix
@@ -1,4 +1,4 @@
-import ./make-test.nix ({ pkgs, ... }: let
+import ./make-test-python.nix ({ pkgs, ... }: let
snakeOil = pkgs.runCommand "snakeoil-certs" {
outputs = [ "out" "cacert" "cert" "key" "crl" ];
buildInputs = [ pkgs.gnutls.bin ];
@@ -105,186 +105,178 @@ in {
newServerSystem = nodes.newServer.config.system.build.toplevel;
switchToNewServer = "${newServerSystem}/bin/switch-to-configuration test";
in ''
- sub su ($$) {
- my ($user, $cmd) = @_;
- my $esc = $cmd =~ s/'/'\\${"'"}'/gr;
- return "su - $user -c '$esc'";
- }
-
- sub setupClientsFor ($$;$) {
- my ($org, $user, $extraInit) = @_;
-
- for my $client ($client1, $client2) {
- $client->nest("initialize client for user $user", sub {
- $client->succeed(
- (su $user, "rm -rf /home/$user/.task"),
- (su $user, "task rc.confirmation=no config confirmation no")
- );
-
- my $exportinfo = $server->succeed(
- "nixos-taskserver user export $org $user"
- );
-
- $exportinfo =~ s/'/'\\'''/g;
-
- $client->nest("importing taskwarrior configuration", sub {
- my $cmd = su $user, "eval '$exportinfo' >&2";
- my ($status, $out) = $client->execute_($cmd);
- if ($status != 0) {
- $client->log("output: $out");
- die "command `$cmd' did not succeed (exit code $status)\n";
- }
- });
-
- eval { &$extraInit($client, $org, $user) };
-
- $client->succeed(su $user,
- "task config taskd.server server:${portStr} >&2"
- );
-
- $client->succeed(su $user, "task sync init >&2");
- });
- }
- }
-
- sub restartServer {
- $server->succeed("systemctl restart taskserver.service");
- $server->waitForOpenPort(${portStr});
- }
-
- sub readdImperativeUser {
- $server->nest("(re-)add imperative user bar", sub {
- $server->execute("nixos-taskserver org remove imperativeOrg");
- $server->succeed(
- "nixos-taskserver org add imperativeOrg",
- "nixos-taskserver user add imperativeOrg bar"
- );
- setupClientsFor "imperativeOrg", "bar";
- });
- }
-
- sub testSync ($) {
- my $user = $_[0];
- subtest "sync for user $user", sub {
- $client1->succeed(su $user, "task add foo >&2");
- $client1->succeed(su $user, "task sync >&2");
- $client2->fail(su $user, "task list >&2");
- $client2->succeed(su $user, "task sync >&2");
- $client2->succeed(su $user, "task list >&2");
- };
- }
-
- sub checkClientCert ($) {
- my $user = $_[0];
- my $cmd = "gnutls-cli".
- " --x509cafile=/home/$user/.task/keys/ca.cert".
- " --x509keyfile=/home/$user/.task/keys/private.key".
- " --x509certfile=/home/$user/.task/keys/public.cert".
- " --port=${portStr} server < /dev/null";
- return su $user, $cmd;
- }
+ from shlex import quote
+
+
+ def su(user, cmd):
+ return f"su - {user} -c {quote(cmd)}"
+
+
+ def no_extra_init(client, org, user):
+ pass
+
+
+ def setup_clients_for(org, user, extra_init=no_extra_init):
+ for client in [client1, client2]:
+ with client.nested(f"initialize client for user {user}"):
+ client.succeed(
+ su(user, f"rm -rf /home/{user}/.task"),
+ su(user, "task rc.confirmation=no config confirmation no"),
+ )
+
+ exportinfo = server.succeed(f"nixos-taskserver user export {org} {user}")
+
+ with client.nested("importing taskwarrior configuration"):
+ client.succeed(su(user, f"eval {quote(exportinfo)} >&2"))
+
+ extra_init(client, org, user)
+
+ client.succeed(su(user, "task config taskd.server server:${portStr} >&2"))
+
+ client.succeed(su(user, "task sync init >&2"))
+
+
+ def restart_server():
+ server.systemctl("restart taskserver.service")
+ server.wait_for_open_port(${portStr})
+
+
+ def re_add_imperative_user():
+ with server.nested("(re-)add imperative user bar"):
+ server.execute("nixos-taskserver org remove imperativeOrg")
+ server.succeed(
+ "nixos-taskserver org add imperativeOrg",
+ "nixos-taskserver user add imperativeOrg bar",
+ )
+ setup_clients_for("imperativeOrg", "bar")
+
+
+ def test_sync(user):
+ with subtest(f"sync for user {user}"):
+ client1.succeed(su(user, "task add foo >&2"))
+ client1.succeed(su(user, "task sync >&2"))
+ client2.fail(su(user, "task list >&2"))
+ client2.succeed(su(user, "task sync >&2"))
+ client2.succeed(su(user, "task list >&2"))
+
+
+ def check_client_cert(user):
+ # debug level 3 is a workaround for gnutls issue https://gitlab.com/gnutls/gnutls/-/issues/1040
+ cmd = (
+ f"gnutls-cli -d 3"
+ f" --x509cafile=/home/{user}/.task/keys/ca.cert"
+ f" --x509keyfile=/home/{user}/.task/keys/private.key"
+ f" --x509certfile=/home/{user}/.task/keys/public.cert"
+ f" --port=${portStr} server < /dev/null"
+ )
+ return su(user, cmd)
+
# Explicitly start the VMs so that we don't accidentally start newServer
- $server->start;
- $client1->start;
- $client2->start;
+ server.start()
+ client1.start()
+ client2.start()
- $server->waitForUnit("taskserver.service");
+ server.wait_for_unit("taskserver.service")
- $server->succeed(
- "nixos-taskserver user list testOrganisation | grep -qxF alice",
- "nixos-taskserver user list testOrganisation | grep -qxF foo",
- "nixos-taskserver user list anotherOrganisation | grep -qxF bob"
- );
+ server.succeed(
+ "nixos-taskserver user list testOrganisation | grep -qxF alice",
+ "nixos-taskserver user list testOrganisation | grep -qxF foo",
+ "nixos-taskserver user list anotherOrganisation | grep -qxF bob",
+ )
- $server->waitForOpenPort(${portStr});
+ server.wait_for_open_port(${portStr})
- $client1->waitForUnit("multi-user.target");
- $client2->waitForUnit("multi-user.target");
+ client1.wait_for_unit("multi-user.target")
+ client2.wait_for_unit("multi-user.target")
- setupClientsFor "testOrganisation", "alice";
- setupClientsFor "testOrganisation", "foo";
- setupClientsFor "anotherOrganisation", "bob";
+ setup_clients_for("testOrganisation", "alice")
+ setup_clients_for("testOrganisation", "foo")
+ setup_clients_for("anotherOrganisation", "bob")
- testSync $_ for ("alice", "bob", "foo");
+ for user in ["alice", "bob", "foo"]:
+ test_sync(user)
- $server->fail("nixos-taskserver user add imperativeOrg bar");
- readdImperativeUser;
+ server.fail("nixos-taskserver user add imperativeOrg bar")
+ re_add_imperative_user()
- testSync "bar";
+ test_sync("bar")
- subtest "checking certificate revocation of user bar", sub {
- $client1->succeed(checkClientCert "bar");
+ with subtest("checking certificate revocation of user bar"):
+ client1.succeed(check_client_cert("bar"))
- $server->succeed("nixos-taskserver user remove imperativeOrg bar");
- restartServer;
+ server.succeed("nixos-taskserver user remove imperativeOrg bar")
+ restart_server()
- $client1->fail(checkClientCert "bar");
+ client1.fail(check_client_cert("bar"))
- $client1->succeed(su "bar", "task add destroy everything >&2");
- $client1->fail(su "bar", "task sync >&2");
- };
+ client1.succeed(su("bar", "task add destroy everything >&2"))
+ client1.fail(su("bar", "task sync >&2"))
- readdImperativeUser;
+ re_add_imperative_user()
- subtest "checking certificate revocation of org imperativeOrg", sub {
- $client1->succeed(checkClientCert "bar");
+ with subtest("checking certificate revocation of org imperativeOrg"):
+ client1.succeed(check_client_cert("bar"))
- $server->succeed("nixos-taskserver org remove imperativeOrg");
- restartServer;
+ server.succeed("nixos-taskserver org remove imperativeOrg")
+ restart_server()
- $client1->fail(checkClientCert "bar");
+ client1.fail(check_client_cert("bar"))
- $client1->succeed(su "bar", "task add destroy even more >&2");
- $client1->fail(su "bar", "task sync >&2");
- };
+ client1.succeed(su("bar", "task add destroy even more >&2"))
+ client1.fail(su("bar", "task sync >&2"))
- readdImperativeUser;
+ re_add_imperative_user()
- subtest "check whether declarative config overrides user bar", sub {
- restartServer;
- testSync "bar";
- };
+ with subtest("check whether declarative config overrides user bar"):
+ restart_server()
+ test_sync("bar")
- subtest "check manual configuration", sub {
- # Remove the keys from automatic CA creation, to make sure the new
- # generation doesn't use keys from before.
- $server->succeed('rm -rf ${cfg.dataDir}/keys/* >&2');
-
- $server->succeed('${switchToNewServer} >&2');
- $server->waitForUnit("taskserver.service");
- $server->waitForOpenPort(${portStr});
-
- $server->succeed(
- "nixos-taskserver org add manualOrg",
- "nixos-taskserver user add manualOrg alice"
- );
-
- setupClientsFor "manualOrg", "alice", sub {
- my ($client, $org, $user) = @_;
- my $cfgpath = "/home/$user/.task";
-
- $client->copyFileFromHost("${snakeOil.cacert}", "$cfgpath/ca.cert");
- for my $file ('alice.key', 'alice.cert') {
- $client->copyFileFromHost("${snakeOil}/$file", "$cfgpath/$file");
- }
-
- for my $file ("$user.key", "$user.cert") {
- $client->copyFileFromHost(
- "${snakeOil}/$file", "$cfgpath/$file"
- );
- }
- $client->copyFileFromHost(
- "${snakeOil.cacert}", "$cfgpath/ca.cert"
- );
- $client->succeed(
- (su "alice", "task config taskd.ca $cfgpath/ca.cert"),
- (su "alice", "task config taskd.key $cfgpath/$user.key"),
- (su $user, "task config taskd.certificate $cfgpath/$user.cert")
- );
- };
- testSync "alice";
- };
+ def init_manual_config(client, org, user):
+ cfgpath = f"/home/{user}/.task"
+
+ client.copy_from_host(
+ "${snakeOil.cacert}",
+ f"{cfgpath}/ca.cert",
+ )
+ for file in ["alice.key", "alice.cert"]:
+ client.copy_from_host(
+ f"${snakeOil}/{file}",
+ f"{cfgpath}/{file}",
+ )
+
+ for file in [f"{user}.key", f"{user}.cert"]:
+ client.copy_from_host(
+ f"${snakeOil}/{file}",
+ f"{cfgpath}/{file}",
+ )
+
+ client.succeed(
+ su("alice", f"task config taskd.ca {cfgpath}/ca.cert"),
+ su("alice", f"task config taskd.key {cfgpath}/{user}.key"),
+ su(user, f"task config taskd.certificate {cfgpath}/{user}.cert"),
+ )
+
+
+ with subtest("check manual configuration"):
+ # Remove the keys from automatic CA creation, to make sure the new
+ # generation doesn't use keys from before.
+ server.succeed("rm -rf ${cfg.dataDir}/keys/* >&2")
+
+ server.succeed(
+ "${switchToNewServer} >&2"
+ )
+ server.wait_for_unit("taskserver.service")
+ server.wait_for_open_port(${portStr})
+
+ server.succeed(
+ "nixos-taskserver org add manualOrg",
+ "nixos-taskserver user add manualOrg alice",
+ )
+
+ setup_clients_for("manualOrg", "alice", init_manual_config)
+
+ test_sync("alice")
'';
})
diff --git a/nixpkgs/nixos/tests/teeworlds.nix b/nixpkgs/nixos/tests/teeworlds.nix
new file mode 100644
index 00000000000..edf58896878
--- /dev/null
+++ b/nixpkgs/nixos/tests/teeworlds.nix
@@ -0,0 +1,55 @@
+import ./make-test-python.nix ({ pkgs, ... }:
+
+let
+ client =
+ { pkgs, ... }:
+
+ { imports = [ ./common/x11.nix ];
+ environment.systemPackages = [ pkgs.teeworlds ];
+ };
+
+in {
+ name = "teeworlds";
+ meta = with pkgs.stdenv.lib.maintainers; {
+ maintainers = [ hax404 ];
+ };
+
+ nodes =
+ { server =
+ { services.teeworlds = {
+ enable = true;
+ openPorts = true;
+ };
+ };
+
+ client1 = client;
+ client2 = client;
+ };
+
+ testScript =
+ ''
+ start_all()
+
+ server.wait_for_unit("teeworlds.service")
+ server.wait_until_succeeds("ss --numeric --udp --listening | grep -q 8303")
+
+ client1.wait_for_x()
+ client2.wait_for_x()
+
+ client1.execute("teeworlds 'player_name Alice;connect server'&")
+ server.wait_until_succeeds(
+ 'journalctl -u teeworlds -e | grep --extended-regexp -q "team_join player=\'[0-9]:Alice"'
+ )
+
+ client2.execute("teeworlds 'player_name Bob;connect server'&")
+ server.wait_until_succeeds(
+ 'journalctl -u teeworlds -e | grep --extended-regexp -q "team_join player=\'[0-9]:Bob"'
+ )
+
+ server.sleep(10) # wait for a while to get a nice screenshot
+
+ client1.screenshot("screen_client1")
+ client2.screenshot("screen_client2")
+ '';
+
+})
diff --git a/nixpkgs/nixos/tests/tiddlywiki.nix b/nixpkgs/nixos/tests/tiddlywiki.nix
index cf45578b0f9..822711b8939 100644
--- a/nixpkgs/nixos/tests/tiddlywiki.nix
+++ b/nixpkgs/nixos/tests/tiddlywiki.nix
@@ -44,7 +44,7 @@ import ./make-test-python.nix ({ ... }: {
configured.succeed(
"curl --fail -o /dev/null 127.0.0.1:3000 --user somelogin:somesecret"
)
-
+
with subtest("restart preserves changes"):
# given running wiki
default.wait_for_unit("tiddlywiki.service")
diff --git a/nixpkgs/nixos/tests/trezord.nix b/nixpkgs/nixos/tests/trezord.nix
index 8d908a52249..67646496ff9 100644
--- a/nixpkgs/nixos/tests/trezord.nix
+++ b/nixpkgs/nixos/tests/trezord.nix
@@ -1,9 +1,8 @@
import ./make-test-python.nix ({ pkgs, ... }: {
name = "trezord";
- meta = with pkgs.stdenv.lib.maintainers; {
- maintainers = [ mmahut "1000101" ];
+ meta = with pkgs.stdenv.lib; {
+ maintainers = with maintainers; [ mmahut maintainers."1000101" ];
};
-
nodes = {
machine = { ... }: {
services.trezord.enable = true;
diff --git a/nixpkgs/nixos/tests/trickster.nix b/nixpkgs/nixos/tests/trickster.nix
index e2ca00980d5..c65160f81e3 100644
--- a/nixpkgs/nixos/tests/trickster.nix
+++ b/nixpkgs/nixos/tests/trickster.nix
@@ -1,7 +1,7 @@
import ./make-test-python.nix ({ pkgs, ... }: {
name = "trickster";
- meta = with pkgs.stdenv.lib.maintainers; {
- maintainers = [ "1000101" ];
+ meta = with pkgs.stdenv.lib; {
+ maintainers = with maintainers; [ maintainers."1000101" ];
};
nodes = {
@@ -34,4 +34,4 @@ import ./make-test-python.nix ({ pkgs, ... }: {
"curl -L http://localhost:9090/metrics | grep 'promhttp_metric_handler_requests_total{code=\"500\"} 0'"
)
'';
-}) \ No newline at end of file
+})
diff --git a/nixpkgs/nixos/tests/wasabibackend.nix b/nixpkgs/nixos/tests/wasabibackend.nix
new file mode 100644
index 00000000000..d169ad15272
--- /dev/null
+++ b/nixpkgs/nixos/tests/wasabibackend.nix
@@ -0,0 +1,38 @@
+import ./make-test-python.nix ({ pkgs, ... }: {
+ name = "wasabibackend";
+ meta = with pkgs.stdenv.lib.maintainers; {
+ maintainers = [ mmahut ];
+ };
+
+ nodes = {
+ machine = { ... }: {
+ services.wasabibackend = {
+ enable = true;
+ network = "testnet";
+ rpc = {
+ user = "alice";
+ port = 18332;
+ };
+ };
+ services.bitcoind = {
+ enable = true;
+ testnet = true;
+ rpc.users = {
+ alice.passwordHMAC = "e7096bc21da60b29ecdbfcdb2c3acc62$f948e61cb587c399358ed99c6ed245a41460b4bf75125d8330c9f6fcc13d7ae7";
+ };
+ };
+ };
+ };
+
+ testScript = ''
+ start_all()
+ machine.wait_for_unit("wasabibackend.service")
+ machine.wait_until_succeeds(
+ "grep 'Wasabi Backend started' /var/lib/wasabibackend/.walletwasabi/backend/Logs.txt"
+ )
+ machine.sleep(5)
+ machine.succeed(
+ "grep 'Config is successfully initialized' /var/lib/wasabibackend/.walletwasabi/backend/Logs.txt"
+ )
+ '';
+})
diff --git a/nixpkgs/nixos/tests/xandikos.nix b/nixpkgs/nixos/tests/xandikos.nix
index 0fded20ff1a..886c3e0082f 100644
--- a/nixpkgs/nixos/tests/xandikos.nix
+++ b/nixpkgs/nixos/tests/xandikos.nix
@@ -17,7 +17,7 @@ import ./make-test-python.nix (
services.xandikos.enable = true;
services.xandikos.address = "localhost";
services.xandikos.port = 8080;
- services.xandikos.routePrefix = "/xandikos/";
+ services.xandikos.routePrefix = "/xandikos-prefix/";
services.xandikos.extraOptions = [
"--defaults"
];
@@ -28,7 +28,7 @@ import ./make-test-python.nix (
serverName = "xandikos.local";
basicAuth.xandikos = "snakeOilPassword";
locations."/xandikos/" = {
- proxyPass = "http://localhost:8080/";
+ proxyPass = "http://localhost:8080/xandikos-prefix/";
};
};
};
diff --git a/nixpkgs/nixos/tests/xfce.nix b/nixpkgs/nixos/tests/xfce.nix
index 99065669661..99e30342e59 100644
--- a/nixpkgs/nixos/tests/xfce.nix
+++ b/nixpkgs/nixos/tests/xfce.nix
@@ -11,8 +11,8 @@ import ./make-test-python.nix ({ pkgs, ...} : {
services.xserver.enable = true;
- services.xserver.displayManager.lightdm = {
- enable = true;
+ services.xserver.displayManager = {
+ lightdm.enable = true;
autoLogin = {
enable = true;
user = "alice";
diff --git a/nixpkgs/nixos/tests/yggdrasil.nix b/nixpkgs/nixos/tests/yggdrasil.nix
index 9ceb7974733..1d7541308b4 100644
--- a/nixpkgs/nixos/tests/yggdrasil.nix
+++ b/nixpkgs/nixos/tests/yggdrasil.nix
@@ -7,6 +7,7 @@ let
SigningPrivateKey = "fe3add8da35316c05f6d90d3ca79bd2801e6ccab6d37e5339fef4152589398abe2c43349083bc1e998e4ec4535b4c6a8f44ca9a5a8e07336561267253b2be5f4";
};
bobIp6 = "201:ebbd:bde9:f138:c302:4afa:1fb6:a19a";
+ bobPrefix = "301:ebbd:bde9:f138";
bobConfig = {
InterfacePeers = {
eth1 = [ "tcp://192.168.1.200:12345" ];
@@ -18,6 +19,7 @@ let
SigningPublicKey = "de111da0ec781e45bf6c63ecb45a78c24d7d4655abfaeea83b26c36eb5c0fd5b";
SigningPrivateKey = "2a6c21550f3fca0331df50668ffab66b6dce8237bcd5728e571e8033b363e247de111da0ec781e45bf6c63ecb45a78c24d7d4655abfaeea83b26c36eb5c0fd5b";
};
+ danIp6 = bobPrefix + "::2";
in import ./make-test-python.nix ({ pkgs, ...} : {
name = "yggdrasil";
@@ -69,6 +71,41 @@ in import ./make-test-python.nix ({ pkgs, ...} : {
text = builtins.toJSON bobConfig;
});
};
+
+ boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = 1;
+
+ networking = {
+ bridges.br0.interfaces = [ ];
+ interfaces.br0 = {
+ ipv6.addresses = [{
+ address = bobPrefix + "::1";
+ prefixLength = 64;
+ }];
+ };
+ };
+
+ # dan is a node inside a container running on bob's host.
+ containers.dan = {
+ autoStart = true;
+ privateNetwork = true;
+ hostBridge = "br0";
+ config = { config, pkgs, ... }: {
+ networking.interfaces.eth0.ipv6 = {
+ addresses = [{
+ address = bobPrefix + "::2";
+ prefixLength = 64;
+ }];
+ routes = [{
+ address = "200::";
+ prefixLength = 7;
+ via = bobPrefix + "::1";
+ }];
+ };
+ services.httpd.enable = true;
+ services.httpd.adminAddr = "foo@example.org";
+ networking.firewall.allowedTCPPorts = [ 80 ];
+ };
+ };
};
# Carol only does local peering. Carol's yggdrasil config is all Nix.
@@ -100,7 +137,7 @@ in import ./make-test-python.nix ({ pkgs, ...} : {
bob.start()
carol.start()
- bob.wait_for_unit("yggdrasil.service")
+ bob.wait_for_unit("default.target")
carol.wait_for_unit("yggdrasil.service")
ip_addr_show = "ip -o -6 addr show dev ygg0 scope global"
@@ -117,10 +154,13 @@ in import ./make-test-python.nix ({ pkgs, ...} : {
carol.succeed("ping -c 1 ${aliceIp6}")
carol.succeed("ping -c 1 ${bobIp6}")
+ carol.succeed("ping -c 1 ${bobPrefix}::1")
+ carol.succeed("ping -c 8 ${danIp6}")
carol.fail("journalctl -u dhcpcd | grep ygg0")
alice.wait_for_unit("httpd.service")
carol.succeed("curl --fail -g http://[${aliceIp6}]")
+ carol.succeed("curl --fail -g http://[${danIp6}]")
'';
})
diff --git a/nixpkgs/nixos/tests/zigbee2mqtt.nix b/nixpkgs/nixos/tests/zigbee2mqtt.nix
new file mode 100644
index 00000000000..b7bb21f9227
--- /dev/null
+++ b/nixpkgs/nixos/tests/zigbee2mqtt.nix
@@ -0,0 +1,19 @@
+import ./make-test-python.nix ({ pkgs, ... }:
+
+ {
+ machine = { pkgs, ... }:
+ {
+ services.zigbee2mqtt = {
+ enable = true;
+ };
+ };
+
+ testScript = ''
+ machine.wait_for_unit("zigbee2mqtt.service")
+ machine.wait_until_fails("systemctl status zigbee2mqtt.service")
+ machine.succeed(
+ "journalctl -eu zigbee2mqtt | grep \"Error: Error while opening serialport 'Error: Error: No such file or directory, cannot open /dev/ttyACM0'\""
+ )
+ '';
+ }
+)