aboutsummaryrefslogtreecommitdiff
path: root/nixpkgs/nixos
diff options
context:
space:
mode:
authorKatharina Fey <kookie@spacekookie.de>2020-03-24 10:15:32 +0100
committerKatharina Fey <kookie@spacekookie.de>2020-03-24 10:15:32 +0100
commit96f063dd321abc80ecaa156226cfb7cf9540315a (patch)
tree7a53ef61484fc7bfff6419b1fd635c67199f27d2 /nixpkgs/nixos
parentaf58f08d3d524e7b008b73a8497ea710915ffaf1 (diff)
parentd96bd3394b734487d1c3bfbac0e8f17465e03afe (diff)
Merge commit 'd96bd3394b734487d1c3bfbac0e8f17465e03afe'
Diffstat (limited to 'nixpkgs/nixos')
-rw-r--r--nixpkgs/nixos/doc/manual/configuration/configuration.xml1
-rw-r--r--nixpkgs/nixos/doc/manual/configuration/modularity.xml1
-rw-r--r--nixpkgs/nixos/doc/manual/configuration/network-manager.xml16
-rw-r--r--nixpkgs/nixos/doc/manual/configuration/xfce.xml24
-rwxr-xr-xnixpkgs/nixos/doc/manual/development/releases.xml5
-rw-r--r--nixpkgs/nixos/doc/manual/installation/upgrading.xml13
-rw-r--r--nixpkgs/nixos/doc/manual/man-nixos-option.xml21
-rw-r--r--nixpkgs/nixos/doc/manual/man-nixos-rebuild.xml59
-rw-r--r--nixpkgs/nixos/doc/manual/man-nixos-version.xml29
-rw-r--r--nixpkgs/nixos/doc/manual/release-notes/release-notes.xml1
-rw-r--r--nixpkgs/nixos/doc/manual/release-notes/rl-2003.xml219
-rw-r--r--nixpkgs/nixos/doc/manual/release-notes/rl-2009.xml115
-rw-r--r--nixpkgs/nixos/lib/eval-config.nix6
-rw-r--r--nixpkgs/nixos/lib/make-ext4-fs.nix19
-rw-r--r--nixpkgs/nixos/lib/qemu-flags.nix4
-rw-r--r--nixpkgs/nixos/lib/test-driver/test-driver.py46
-rw-r--r--nixpkgs/nixos/lib/testing-python.nix19
-rw-r--r--nixpkgs/nixos/lib/testing.nix11
-rw-r--r--nixpkgs/nixos/lib/utils.nix2
-rwxr-xr-xnixpkgs/nixos/maintainers/scripts/ec2/create-amis.sh2
-rw-r--r--nixpkgs/nixos/modules/config/ldap.nix3
-rw-r--r--nixpkgs/nixos/modules/config/networking.nix27
-rw-r--r--nixpkgs/nixos/modules/config/pulseaudio.nix3
-rw-r--r--nixpkgs/nixos/modules/config/resolvconf.nix10
-rw-r--r--nixpkgs/nixos/modules/config/swap.nix2
-rw-r--r--nixpkgs/nixos/modules/config/system-path.nix1
-rw-r--r--nixpkgs/nixos/modules/config/xdg/portal.nix6
-rw-r--r--nixpkgs/nixos/modules/hardware/brightnessctl.nix31
-rw-r--r--nixpkgs/nixos/modules/hardware/openrazer.nix2
-rw-r--r--nixpkgs/nixos/modules/hardware/video/amdgpu-pro.nix2
-rw-r--r--nixpkgs/nixos/modules/hardware/video/ati.nix2
-rw-r--r--nixpkgs/nixos/modules/hardware/video/nvidia.nix138
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/channel.nix4
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix3
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix21
-rw-r--r--nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix14
-rw-r--r--nixpkgs/nixos/modules/installer/netboot/netboot.nix14
-rw-r--r--nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix8
-rw-r--r--nixpkgs/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix2
-rw-r--r--nixpkgs/nixos/modules/installer/tools/nixos-enter.sh18
-rw-r--r--nixpkgs/nixos/modules/installer/tools/nixos-option/nixos-option.cc251
-rw-r--r--nixpkgs/nixos/modules/installer/tools/nixos-rebuild.sh98
-rw-r--r--nixpkgs/nixos/modules/installer/tools/nixos-version.sh9
-rw-r--r--nixpkgs/nixos/modules/installer/tools/tools.nix9
-rw-r--r--nixpkgs/nixos/modules/misc/ids.nix8
-rw-r--r--nixpkgs/nixos/modules/misc/locate.nix7
-rw-r--r--nixpkgs/nixos/modules/misc/nixpkgs.nix8
-rw-r--r--nixpkgs/nixos/modules/misc/version.nix16
-rw-r--r--nixpkgs/nixos/modules/module-list.nix25
-rw-r--r--nixpkgs/nixos/modules/programs/bash-my-aws.nix25
-rw-r--r--nixpkgs/nixos/modules/programs/bash/bash.nix13
-rw-r--r--nixpkgs/nixos/modules/programs/firejail.nix30
-rw-r--r--nixpkgs/nixos/modules/programs/fish_completion-generator.patch12
-rw-r--r--nixpkgs/nixos/modules/programs/sway.nix4
-rw-r--r--nixpkgs/nixos/modules/programs/tmux.nix8
-rw-r--r--nixpkgs/nixos/modules/programs/zsh/zsh.nix69
-rw-r--r--nixpkgs/nixos/modules/rename.nix19
-rw-r--r--nixpkgs/nixos/modules/security/acme.nix224
-rw-r--r--nixpkgs/nixos/modules/security/acme.xml2
-rw-r--r--nixpkgs/nixos/modules/security/duosec.nix16
-rw-r--r--nixpkgs/nixos/modules/security/google_oslogin.nix6
-rw-r--r--nixpkgs/nixos/modules/security/rngd.nix12
-rw-r--r--nixpkgs/nixos/modules/security/sudo.nix36
-rw-r--r--nixpkgs/nixos/modules/security/tpm2.nix185
-rw-r--r--nixpkgs/nixos/modules/services/audio/alsa.nix6
-rw-r--r--nixpkgs/nixos/modules/services/audio/mopidy.nix4
-rw-r--r--nixpkgs/nixos/modules/services/backup/restic.nix56
-rw-r--r--nixpkgs/nixos/modules/services/backup/sanoid.nix213
-rw-r--r--nixpkgs/nixos/modules/services/backup/syncoid.nix168
-rw-r--r--nixpkgs/nixos/modules/services/computing/foldingathome/client.nix81
-rw-r--r--nixpkgs/nixos/modules/services/computing/slurm/slurm.nix1
-rw-r--r--nixpkgs/nixos/modules/services/continuous-integration/buildkite-agents.nix (renamed from nixpkgs/nixos/modules/services/continuous-integration/buildkite-agent.nix)81
-rw-r--r--nixpkgs/nixos/modules/services/databases/mysql.nix103
-rw-r--r--nixpkgs/nixos/modules/services/databases/postgresql.nix35
-rw-r--r--nixpkgs/nixos/modules/services/databases/redis.nix47
-rw-r--r--nixpkgs/nixos/modules/services/desktops/malcontent.nix32
-rw-r--r--nixpkgs/nixos/modules/services/development/jupyter/default.nix6
-rw-r--r--nixpkgs/nixos/modules/services/hardware/fwupd.nix5
-rw-r--r--nixpkgs/nixos/modules/services/hardware/irqbalance.nix14
-rw-r--r--nixpkgs/nixos/modules/services/hardware/tlp.nix142
-rw-r--r--nixpkgs/nixos/modules/services/mail/dovecot.nix234
-rw-r--r--nixpkgs/nixos/modules/services/mail/mailman.nix8
-rw-r--r--nixpkgs/nixos/modules/services/mail/sympa.nix596
-rw-r--r--nixpkgs/nixos/modules/services/misc/ankisyncd.nix79
-rw-r--r--nixpkgs/nixos/modules/services/misc/autorandr.nix2
-rw-r--r--nixpkgs/nixos/modules/services/misc/disnix.nix5
-rw-r--r--nixpkgs/nixos/modules/services/misc/folding-at-home.nix67
-rw-r--r--nixpkgs/nixos/modules/services/misc/home-assistant.nix15
-rw-r--r--nixpkgs/nixos/modules/services/misc/matrix-synapse.nix46
-rw-r--r--nixpkgs/nixos/modules/services/misc/matrix-synapse.xml (renamed from nixpkgs/nixos/doc/manual/configuration/matrix.xml)97
-rw-r--r--nixpkgs/nixos/modules/services/misc/parsoid.nix25
-rw-r--r--nixpkgs/nixos/modules/services/misc/sssd.nix6
-rw-r--r--nixpkgs/nixos/modules/services/misc/zoneminder.nix4
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/cadvisor.nix1
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/heapster.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/nagios.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix27
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix17
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/json.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mail.nix9
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mikrotik.nix66
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/minio.nix4
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix13
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix6
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix16
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix4
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix4
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix2
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/prometheus/xmpp-alerts.nix47
-rw-r--r--nixpkgs/nixos/modules/services/monitoring/statsd.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/cjdns.nix52
-rw-r--r--nixpkgs/nixos/modules/services/networking/dhcpcd.nix4
-rw-r--r--nixpkgs/nixos/modules/services/networking/dnscrypt-proxy.nix328
-rw-r--r--nixpkgs/nixos/modules/services/networking/dnscrypt-proxy.xml66
-rw-r--r--nixpkgs/nixos/modules/services/networking/dnscrypt-proxy2.nix61
-rw-r--r--nixpkgs/nixos/modules/services/networking/firewall.nix10
-rw-r--r--nixpkgs/nixos/modules/services/networking/freeradius.nix18
-rw-r--r--nixpkgs/nixos/modules/services/networking/git-daemon.nix4
-rw-r--r--nixpkgs/nixos/modules/services/networking/haproxy.nix26
-rw-r--r--nixpkgs/nixos/modules/services/networking/i2pd.nix22
-rw-r--r--nixpkgs/nixos/modules/services/networking/iodine.nix163
-rw-r--r--nixpkgs/nixos/modules/services/networking/iwd.nix7
-rw-r--r--nixpkgs/nixos/modules/services/networking/knot.nix40
-rw-r--r--nixpkgs/nixos/modules/services/networking/kresd.nix152
-rw-r--r--nixpkgs/nixos/modules/services/networking/minidlna.nix17
-rw-r--r--nixpkgs/nixos/modules/services/networking/nat.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/nix-store-gcs-proxy.nix75
-rw-r--r--nixpkgs/nixos/modules/services/networking/nsd.nix4
-rw-r--r--nixpkgs/nixos/modules/services/networking/ntp/ntpd.nix13
-rw-r--r--nixpkgs/nixos/modules/services/networking/pppd.nix4
-rw-r--r--nixpkgs/nixos/modules/services/networking/shorewall.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/shorewall6.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/smartdns.nix61
-rw-r--r--nixpkgs/nixos/modules/services/networking/ssh/sshd.nix26
-rw-r--r--nixpkgs/nixos/modules/services/networking/sslh.nix9
-rw-r--r--nixpkgs/nixos/modules/services/networking/stubby.nix3
-rw-r--r--nixpkgs/nixos/modules/services/networking/supybot.nix111
-rw-r--r--nixpkgs/nixos/modules/services/networking/tailscale.nix46
-rw-r--r--nixpkgs/nixos/modules/services/networking/vsftpd.nix2
-rw-r--r--nixpkgs/nixos/modules/services/networking/wireguard.nix6
-rw-r--r--nixpkgs/nixos/modules/services/networking/zerotierone.nix11
-rw-r--r--nixpkgs/nixos/modules/services/torrent/transmission.nix3
-rw-r--r--nixpkgs/nixos/modules/services/wayland/cage.nix99
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/codimd.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/grocy.nix172
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/grocy.xml77
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/jirafeau.nix169
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/limesurvey.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/mattermost.nix16
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/mediawiki.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/moodle.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/nextcloud.nix4
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/wordpress.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-apps/zabbix.nix2
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix210
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/apache-httpd/vhost-options.nix (renamed from nixpkgs/nixos/modules/services/web-servers/apache-httpd/per-server-options.nix)9
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/caddy.nix18
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/nginx/default.nix20
-rw-r--r--nixpkgs/nixos/modules/services/web-servers/uwsgi.nix2
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix1
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix5
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.xml130
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix178
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/xfce.nix11
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/default.nix7
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/gdm.nix5
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/tiny.nix92
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/lightdm.nix1
-rw-r--r--nixpkgs/nixos/modules/services/x11/unclutter.nix2
-rw-r--r--nixpkgs/nixos/modules/services/x11/urxvtd.nix6
-rw-r--r--nixpkgs/nixos/modules/services/x11/xserver.nix76
-rw-r--r--nixpkgs/nixos/modules/system/activation/activation-script.nix33
-rw-r--r--nixpkgs/nixos/modules/system/activation/switch-to-configuration.pl4
-rw-r--r--nixpkgs/nixos/modules/system/activation/top-level.nix1
-rw-r--r--nixpkgs/nixos/modules/system/boot/initrd-network.nix64
-rw-r--r--nixpkgs/nixos/modules/system/boot/kernel.nix272
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix8
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl3
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/grub/memtest.nix57
-rw-r--r--nixpkgs/nixos/modules/system/boot/networkd.nix168
-rw-r--r--nixpkgs/nixos/modules/system/boot/stage-1-init.sh19
-rw-r--r--nixpkgs/nixos/modules/system/boot/stage-1.nix28
-rw-r--r--nixpkgs/nixos/modules/system/boot/systemd-lib.nix5
-rw-r--r--nixpkgs/nixos/modules/system/boot/systemd.nix28
-rw-r--r--nixpkgs/nixos/modules/system/etc/etc.nix8
-rw-r--r--nixpkgs/nixos/modules/tasks/auto-upgrade.nix15
-rw-r--r--nixpkgs/nixos/modules/tasks/encrypted-devices.nix2
-rw-r--r--nixpkgs/nixos/modules/tasks/filesystems.nix9
-rw-r--r--nixpkgs/nixos/modules/tasks/filesystems/btrfs.nix7
-rw-r--r--nixpkgs/nixos/modules/tasks/filesystems/zfs.nix6
-rw-r--r--nixpkgs/nixos/modules/tasks/network-interfaces-scripted.nix49
-rw-r--r--nixpkgs/nixos/modules/tasks/network-interfaces-systemd.nix69
-rw-r--r--nixpkgs/nixos/modules/tasks/network-interfaces.nix119
-rw-r--r--nixpkgs/nixos/modules/testing/service-runner.nix28
-rw-r--r--nixpkgs/nixos/modules/virtualisation/docker-containers.nix34
-rw-r--r--nixpkgs/nixos/modules/virtualisation/hyperv-guest.nix2
-rw-r--r--nixpkgs/nixos/modules/virtualisation/kvmgt.nix16
-rw-r--r--nixpkgs/nixos/modules/virtualisation/libvirtd.nix2
-rw-r--r--nixpkgs/nixos/modules/virtualisation/openvswitch.nix7
-rw-r--r--nixpkgs/nixos/modules/virtualisation/virtualbox-image.nix39
-rw-r--r--nixpkgs/nixos/release-combined.nix187
-rw-r--r--nixpkgs/nixos/release-small.nix38
-rw-r--r--nixpkgs/nixos/release.nix14
-rw-r--r--nixpkgs/nixos/tests/acme.nix119
-rw-r--r--nixpkgs/nixos/tests/all-tests.nix22
-rw-r--r--nixpkgs/nixos/tests/buildbot.nix130
-rw-r--r--nixpkgs/nixos/tests/buildkite-agents.nix (renamed from nixpkgs/nixos/tests/buildkite-agent.nix)19
-rw-r--r--nixpkgs/nixos/tests/cage.nix43
-rw-r--r--nixpkgs/nixos/tests/chromium.nix367
-rw-r--r--nixpkgs/nixos/tests/common/letsencrypt/common.nix3
-rw-r--r--nixpkgs/nixos/tests/containers-imperative.nix15
-rw-r--r--nixpkgs/nixos/tests/corerad.nix2
-rw-r--r--nixpkgs/nixos/tests/dnscrypt-proxy2.nix (renamed from nixpkgs/nixos/tests/dnscrypt-proxy.nix)23
-rw-r--r--nixpkgs/nixos/tests/docker-containers.nix27
-rw-r--r--nixpkgs/nixos/tests/docker-tools.nix221
-rw-r--r--nixpkgs/nixos/tests/firefox.nix6
-rw-r--r--nixpkgs/nixos/tests/gitdaemon.nix64
-rw-r--r--nixpkgs/nixos/tests/glusterfs.nix19
-rw-r--r--nixpkgs/nixos/tests/grocy.nix47
-rw-r--r--nixpkgs/nixos/tests/ihatemoney.nix59
-rw-r--r--nixpkgs/nixos/tests/initrd-network.nix15
-rw-r--r--nixpkgs/nixos/tests/installed-tests/default.nix2
-rw-r--r--nixpkgs/nixos/tests/installed-tests/fwupd.nix4
-rw-r--r--nixpkgs/nixos/tests/installed-tests/glib-testing.nix5
-rw-r--r--nixpkgs/nixos/tests/installed-tests/malcontent.nix5
-rw-r--r--nixpkgs/nixos/tests/installed-tests/xdg-desktop-portal.nix4
-rw-r--r--nixpkgs/nixos/tests/installer.nix1027
-rw-r--r--nixpkgs/nixos/tests/iodine.nix63
-rw-r--r--nixpkgs/nixos/tests/jirafeau.nix22
-rw-r--r--nixpkgs/nixos/tests/keymap.nix114
-rw-r--r--nixpkgs/nixos/tests/knot.nix15
-rw-r--r--nixpkgs/nixos/tests/krb5/deprecated-config.nix6
-rw-r--r--nixpkgs/nixos/tests/krb5/example-config.nix6
-rw-r--r--nixpkgs/nixos/tests/kubernetes/dns.nix2
-rw-r--r--nixpkgs/nixos/tests/lorri/default.nix6
-rw-r--r--nixpkgs/nixos/tests/matrix-synapse.nix21
-rw-r--r--nixpkgs/nixos/tests/misc.nix164
-rw-r--r--nixpkgs/nixos/tests/nesting.nix8
-rw-r--r--nixpkgs/nixos/tests/networking.nix29
-rw-r--r--nixpkgs/nixos/tests/nfs/simple.nix14
-rw-r--r--nixpkgs/nixos/tests/nsd.nix52
-rw-r--r--nixpkgs/nixos/tests/openarena.nix84
-rw-r--r--nixpkgs/nixos/tests/opensmtpd.nix2
-rw-r--r--nixpkgs/nixos/tests/openstack-image.nix6
-rw-r--r--nixpkgs/nixos/tests/orangefs.nix10
-rw-r--r--nixpkgs/nixos/tests/plotinus.nix27
-rw-r--r--nixpkgs/nixos/tests/postgresql-wal-receiver.nix19
-rw-r--r--nixpkgs/nixos/tests/predictable-interface-names.nix6
-rw-r--r--nixpkgs/nixos/tests/printing.nix165
-rw-r--r--nixpkgs/nixos/tests/prometheus-exporters.nix45
-rw-r--r--nixpkgs/nixos/tests/restic.nix63
-rw-r--r--nixpkgs/nixos/tests/rsyslogd.nix30
-rw-r--r--nixpkgs/nixos/tests/run-in-machine.nix2
-rw-r--r--nixpkgs/nixos/tests/sanoid.nix90
-rw-r--r--nixpkgs/nixos/tests/service-runner.nix36
-rw-r--r--nixpkgs/nixos/tests/signal-desktop.nix1
-rw-r--r--nixpkgs/nixos/tests/solr.nix50
-rw-r--r--nixpkgs/nixos/tests/sympa.nix36
-rw-r--r--nixpkgs/nixos/tests/systemd-networkd-vrf.nix221
-rw-r--r--nixpkgs/nixos/tests/systemd-networkd.nix (renamed from nixpkgs/nixos/tests/systemd-networkd-wireguard.nix)35
-rw-r--r--nixpkgs/nixos/tests/tinydns.nix2
-rw-r--r--nixpkgs/nixos/tests/zfs.nix75
267 files changed, 8656 insertions, 3574 deletions
diff --git a/nixpkgs/nixos/doc/manual/configuration/configuration.xml b/nixpkgs/nixos/doc/manual/configuration/configuration.xml
index 5961209bc13..507d28814ea 100644
--- a/nixpkgs/nixos/doc/manual/configuration/configuration.xml
+++ b/nixpkgs/nixos/doc/manual/configuration/configuration.xml
@@ -21,7 +21,6 @@
<xi:include href="xfce.xml" />
<xi:include href="networking.xml" />
<xi:include href="linux-kernel.xml" />
- <xi:include href="matrix.xml" />
<xi:include href="../generated/modules.xml" xpointer="xpointer(//section[@id='modules']/*)" />
<xi:include href="profiles.xml" />
<xi:include href="kubernetes.xml" />
diff --git a/nixpkgs/nixos/doc/manual/configuration/modularity.xml b/nixpkgs/nixos/doc/manual/configuration/modularity.xml
index 7ad0ae80a48..532a2c615e4 100644
--- a/nixpkgs/nixos/doc/manual/configuration/modularity.xml
+++ b/nixpkgs/nixos/doc/manual/configuration/modularity.xml
@@ -36,6 +36,7 @@
{ <xref linkend="opt-services.xserver.enable"/> = true;
<xref linkend="opt-services.xserver.displayManager.sddm.enable"/> = true;
<xref linkend="opt-services.xserver.desktopManager.plasma5.enable"/> = true;
+ <xref linkend="opt-environment.systemPackages"/> = [ pkgs.vim ];
}
</programlisting>
Note that both <filename>configuration.nix</filename> and
diff --git a/nixpkgs/nixos/doc/manual/configuration/network-manager.xml b/nixpkgs/nixos/doc/manual/configuration/network-manager.xml
index d103ee24978..3953e0ffe85 100644
--- a/nixpkgs/nixos/doc/manual/configuration/network-manager.xml
+++ b/nixpkgs/nixos/doc/manual/configuration/network-manager.xml
@@ -28,17 +28,21 @@
<command>nmtui</command> (curses-based terminal user interface). See their
manual pages for details on their usage. Some desktop environments (GNOME,
KDE) have their own configuration tools for NetworkManager. On XFCE, there is
- no configuration tool for NetworkManager by default: by adding
- <code>networkmanagerapplet</code> to the list of system packages, the
- graphical applet will be installed and will launch automatically when XFCE is
- starting (and will show in the status tray).
+ no configuration tool for NetworkManager by default: by enabling <xref linkend="opt-programs.nm-applet.enable"/>, the
+ graphical applet will be installed and will launch automatically when the graphical session is started.
</para>
<note>
<para>
<code>networking.networkmanager</code> and <code>networking.wireless</code>
- (WPA Supplicant) cannot be enabled at the same time: you can still connect
- to the wireless networks using NetworkManager.
+ (WPA Supplicant) can be used together if desired. To do this you need to instruct
+ NetworkManager to ignore those interfaces like:
+<programlisting>
+<xref linkend="opt-networking.networkmanager.unmanaged"/> = [
+ "*" "except:type:wwan" "except:type:gsm"
+];
+</programlisting>
+ Refer to the option description for the exact syntax and references to external documentation.
</para>
</note>
</section>
diff --git a/nixpkgs/nixos/doc/manual/configuration/xfce.xml b/nixpkgs/nixos/doc/manual/configuration/xfce.xml
index 7d2862f8b31..ebf1f493c5c 100644
--- a/nixpkgs/nixos/doc/manual/configuration/xfce.xml
+++ b/nixpkgs/nixos/doc/manual/configuration/xfce.xml
@@ -9,7 +9,6 @@
<programlisting>
<xref linkend="opt-services.xserver.desktopManager.xfce.enable" /> = true;
<xref linkend="opt-services.xserver.displayManager.defaultSession" /> = "xfce";
-};
</programlisting>
</para>
<para>
@@ -28,25 +27,14 @@
<para>
Some Xfce programs are not installed automatically. To install them manually
(system wide), put them into your
- <xref linkend="opt-environment.systemPackages"/>.
+ <xref linkend="opt-environment.systemPackages"/> from <literal>pkgs.xfce</literal>.
</para>
- <simplesect xml:id="sec-xfce-thunar-volumes">
- <title>Thunar Volume Support</title>
- <para>
- To enable <emphasis>Thunar</emphasis> volume support, put
-<programlisting>
-<xref linkend="opt-services.xserver.desktopManager.xfce.enable"/> = true;
-</programlisting>
- into your <emphasis>configuration.nix</emphasis>.
- </para>
- </simplesect>
- <simplesect xml:id="sec-xfce-polkit">
- <title>Polkit Authentication Agent</title>
+ <simplesect xml:id="sec-xfce-thunar-plugins">
+ <title>Thunar Plugins</title>
<para>
- There is no authentication agent automatically installed alongside Xfce. To
- allow mounting of local (non-removable) filesystems, you will need to
- install one. Installing <emphasis>polkit_gnome</emphasis>, a rebuild, logout
- and login did the trick.
+ If you'd like to add extra plugins to Thunar, add them to
+ <xref linkend="opt-services.xserver.desktopManager.xfce.thunarPlugins"/>.
+ You shouldn't just add them to <xref linkend="opt-environment.systemPackages"/>.
</para>
</simplesect>
<simplesect xml:id="sec-xfce-troubleshooting">
diff --git a/nixpkgs/nixos/doc/manual/development/releases.xml b/nixpkgs/nixos/doc/manual/development/releases.xml
index a22a0a3707b..cc0ec78cc74 100755
--- a/nixpkgs/nixos/doc/manual/development/releases.xml
+++ b/nixpkgs/nixos/doc/manual/development/releases.xml
@@ -71,8 +71,9 @@
<para>
<link xlink:href="https://github.com/NixOS/nixpkgs/commit/d6b08acd1ccac0d9d502c4b635e00b04d3387f06">
Update <literal>versionSuffix</literal> in
- <literal>nixos/release.nix</literal></link>, use <literal>git log
- --format=%an|wc -l</literal> to get the commit count
+ <literal>nixos/release.nix</literal></link>, use
+ <literal>git rev-list --count 17.09-beta</literal>
+ to get the commit count.
</para>
</listitem>
<listitem>
diff --git a/nixpkgs/nixos/doc/manual/installation/upgrading.xml b/nixpkgs/nixos/doc/manual/installation/upgrading.xml
index 8d3f35b7c26..92864cf2557 100644
--- a/nixpkgs/nixos/doc/manual/installation/upgrading.xml
+++ b/nixpkgs/nixos/doc/manual/installation/upgrading.xml
@@ -120,12 +120,17 @@ nixos https://nixos.org/channels/nixos-unstable
to <filename>configuration.nix</filename>:
<programlisting>
<xref linkend="opt-system.autoUpgrade.enable"/> = true;
+<xref linkend="opt-system.autoUpgrade.allowReboot"/> = true;
</programlisting>
This enables a periodically executed systemd service named
- <literal>nixos-upgrade.service</literal>. It runs <command>nixos-rebuild
- switch --upgrade</command> to upgrade NixOS to the latest version in the
- current channel. (To see when the service runs, see <command>systemctl
- list-timers</command>.) You can also specify a channel explicitly, e.g.
+ <literal>nixos-upgrade.service</literal>. If the <literal>allowReboot</literal>
+ option is <literal>false</literal>, it runs <command>nixos-rebuild switch
+ --upgrade</command> to upgrade NixOS to the latest version in the current
+ channel. (To see when the service runs, see <command>systemctl list-timers</command>.)
+ If <literal>allowReboot</literal> is <literal>true</literal>, then the
+ system will automatically reboot if the new generation contains a different
+ kernel, initrd or kernel modules.
+ You can also specify a channel explicitly, e.g.
<programlisting>
<xref linkend="opt-system.autoUpgrade.channel"/> = https://nixos.org/channels/nixos-19.09;
</programlisting>
diff --git a/nixpkgs/nixos/doc/manual/man-nixos-option.xml b/nixpkgs/nixos/doc/manual/man-nixos-option.xml
index b82f3125609..b921386d0df 100644
--- a/nixpkgs/nixos/doc/manual/man-nixos-option.xml
+++ b/nixpkgs/nixos/doc/manual/man-nixos-option.xml
@@ -14,12 +14,16 @@
<refsynopsisdiv>
<cmdsynopsis>
<command>nixos-option</command>
+
<arg>
- <option>-I</option> <replaceable>path</replaceable>
+ <group choice='req'>
+ <arg choice='plain'><option>-r</option></arg>
+ <arg choice='plain'><option>--recursive</option></arg>
+ </group>
</arg>
<arg>
- <option>--all</option>
+ <option>-I</option> <replaceable>path</replaceable>
</arg>
<arg>
@@ -46,23 +50,22 @@
</para>
<variablelist>
<varlistentry>
- <term>
- <option>-I</option> <replaceable>path</replaceable>
- </term>
+ <term><option>-r</option></term>
+ <term><option>--recursive</option></term>
<listitem>
<para>
- This option is passed to the underlying
- <command>nix-instantiate</command> invocation.
+ Print all the values at or below the specified path recursively.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
- <option>--all</option>
+ <option>-I</option> <replaceable>path</replaceable>
</term>
<listitem>
<para>
- Print the values of all options.
+ This option is passed to the underlying
+ <command>nix-instantiate</command> invocation.
</para>
</listitem>
</varlistentry>
diff --git a/nixpkgs/nixos/doc/manual/man-nixos-rebuild.xml b/nixpkgs/nixos/doc/manual/man-nixos-rebuild.xml
index 495dbc8859b..f4f663b84f0 100644
--- a/nixpkgs/nixos/doc/manual/man-nixos-rebuild.xml
+++ b/nixpkgs/nixos/doc/manual/man-nixos-rebuild.xml
@@ -77,7 +77,14 @@
<option>--builders</option> <replaceable>builder-spec</replaceable>
</arg>
+ <sbr/>
+
+ <arg>
+ <option>--flake</option> <replaceable>flake-uri</replaceable>
+ </arg>
+
<sbr />
+
<arg>
<group choice='req'>
<arg choice='plain'>
@@ -129,14 +136,17 @@
<title>Description</title>
<para>
- This command updates the system so that it corresponds to the configuration
- specified in <filename>/etc/nixos/configuration.nix</filename>. Thus, every
- time you modify <filename>/etc/nixos/configuration.nix</filename> or any
- NixOS module, you must run <command>nixos-rebuild</command> to make the
- changes take effect. It builds the new system in
- <filename>/nix/store</filename>, runs its activation script, and stop and
- (re)starts any system services if needed. Please note that user services need
- to be started manually as they aren't detected by the activation script at the moment.
+ This command updates the system so that it corresponds to the
+ configuration specified in
+ <filename>/etc/nixos/configuration.nix</filename> or
+ <filename>/etc/nixos/flake.nix</filename>. Thus, every time you
+ modify the configuration or any other NixOS module, you must run
+ <command>nixos-rebuild</command> to make the changes take
+ effect. It builds the new system in
+ <filename>/nix/store</filename>, runs its activation script, and
+ stop and (re)starts any system services if needed. Please note that
+ user services need to be started manually as they aren't detected
+ by the activation script at the moment.
</para>
<para>
@@ -508,6 +518,24 @@
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--flake</option> <replaceable>flake-uri</replaceable>[<replaceable>name</replaceable>]
+ </term>
+ <listitem>
+ <para>
+ Build the NixOS system from the specified flake. It defaults to
+ the directory containing the target of the symlink
+ <filename>/etc/nixos/flake.nix</filename>, if it exists. The
+ flake must contain an output named
+ <literal>nixosConfigurations.<replaceable>name</replaceable></literal>. If
+ <replaceable>name</replaceable> is omitted, it default to the
+ current host name.
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
<para>
@@ -556,6 +584,21 @@
<varlistentry>
<term>
+ <filename>/etc/nixos/flake.nix</filename>
+ </term>
+ <listitem>
+ <para>
+ If this file exists, then <command>nixos-rebuild</command> will
+ use it as if the <option>--flake</option> option was given. This
+ file may be a symlink to a <filename>flake.nix</filename> in an
+ actual flake; thus <filename>/etc/nixos</filename> need not be a
+ flake.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
<filename>/run/current-system</filename>
</term>
<listitem>
diff --git a/nixpkgs/nixos/doc/manual/man-nixos-version.xml b/nixpkgs/nixos/doc/manual/man-nixos-version.xml
index e9ad8bddcac..aada08c5b4a 100644
--- a/nixpkgs/nixos/doc/manual/man-nixos-version.xml
+++ b/nixpkgs/nixos/doc/manual/man-nixos-version.xml
@@ -12,16 +12,22 @@
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
- <command>nixos-version</command>
+ <command>nixos-version</command>
<arg>
<option>--hash</option>
</arg>
-
+
<arg>
<option>--revision</option>
</arg>
+
+ <arg>
+ <option>--json</option>
+ </arg>
+
</cmdsynopsis>
</refsynopsisdiv>
+
<refsection>
<title>Description</title>
<para>
@@ -84,12 +90,16 @@
</variablelist>
</para>
</refsection>
+
<refsection>
<title>Options</title>
+
<para>
This command accepts the following options:
</para>
+
<variablelist>
+
<varlistentry>
<term>
<option>--hash</option>
@@ -107,6 +117,21 @@
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--json</option>
+ </term>
+ <listitem>
+ <para>
+ Print a JSON representation of the versions of NixOS and the
+ top-level configuration flake.
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
+
</refsection>
+
</refentry>
diff --git a/nixpkgs/nixos/doc/manual/release-notes/release-notes.xml b/nixpkgs/nixos/doc/manual/release-notes/release-notes.xml
index 444862c5739..e2913b8a535 100644
--- a/nixpkgs/nixos/doc/manual/release-notes/release-notes.xml
+++ b/nixpkgs/nixos/doc/manual/release-notes/release-notes.xml
@@ -8,6 +8,7 @@
This section lists the release notes for each stable version of NixOS and
current unstable revision.
</para>
+ <xi:include href="rl-2009.xml" />
<xi:include href="rl-2003.xml" />
<xi:include href="rl-1909.xml" />
<xi:include href="rl-1903.xml" />
diff --git a/nixpkgs/nixos/doc/manual/release-notes/rl-2003.xml b/nixpkgs/nixos/doc/manual/release-notes/rl-2003.xml
index 13981c0853d..e5351519f8d 100644
--- a/nixpkgs/nixos/doc/manual/release-notes/rl-2003.xml
+++ b/nixpkgs/nixos/doc/manual/release-notes/rl-2003.xml
@@ -25,6 +25,13 @@
</listitem>
<listitem>
<para>
+ Linux kernel is updated to branch 5.4 by default (from 4.19).
+ Users of Intel GPUs may prefer to explicitly set branch to 4.19 to avoid some regressions.
+ <programlisting>boot.kernelPackages = pkgs.linuxPackages_4_19;</programlisting>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
Postgresql for NixOS service now defaults to v11.
</para>
</listitem>
@@ -52,7 +59,7 @@
<listitem>
<para>
<command>nixos-option</command> has been rewritten in C++, speeding it up, improving correctness,
- and adding a <option>--all</option> option which prints all options and their values.
+ and adding a <option>-r</option> option which prints all options and their values recursively.
</para>
</listitem>
<listitem>
@@ -96,6 +103,13 @@ services.xserver.displayManager.defaultSession = "xfce+icewm";
via <option>services.upower</option>.
</para>
</listitem>
+ <listitem>
+ <para>
+ To use Geary you should enable <xref linkend="opt-programs.geary.enable"/> instead of
+ just adding it to <xref linkend="opt-environment.systemPackages"/>.
+ It was created so Geary could function properly outside of GNOME.
+ </para>
+ </listitem>
</itemizedlist>
</section>
@@ -140,7 +154,7 @@ services.xserver.displayManager.defaultSession = "xfce+icewm";
</listitem>
<listitem>
<para>
- The <literal>99-main.network</literal> file was removed. Maching all
+ The <literal>99-main.network</literal> file was removed. Matching all
network interfaces caused many breakages, see
<link xlink:href="https://github.com/NixOS/nixpkgs/pull/18962">#18962</link>
and <link xlink:href="https://github.com/NixOS/nixpkgs/pull/71106">#71106</link>.
@@ -182,10 +196,10 @@ services.xserver.displayManager.defaultSession = "xfce+icewm";
</listitem>
<listitem>
<para>
- There is now only one Xfce package-set and module. This means attributes, <literal>xfce4-14</literal>
- <literal>xfce4-12</literal>, and <literal>xfceUnstable</literal> all now point to the latest Xfce 4.14
- packages. And in future NixOS releases will be the latest released version of Xfce available at the
- time during the releases development (if viable).
+ There is now only one Xfce package-set and module. This means that attributes <literal>xfce4-14</literal>
+ and <literal>xfceUnstable</literal> all now point to the latest Xfce 4.14
+ packages. And in the future NixOS releases will be the latest released version of Xfce available at the
+ time of the release's development (if viable).
</para>
</listitem>
<listitem>
@@ -221,7 +235,7 @@ services.xserver.displayManager.defaultSession = "xfce+icewm";
<listitem>
<para>
The <literal>buildRustCrate</literal> infrastructure now produces <literal>lib</literal> outputs in addition to the <literal>out</literal> output.
- This has led to drastically reduced closed sizes for some rust crates since development dependencies are now in the <literal>lib</literal> output.
+ This has led to drastically reduced closure sizes for some rust crates since development dependencies are now in the <literal>lib</literal> output.
</para>
</listitem>
<listitem>
@@ -234,6 +248,23 @@ services.xserver.displayManager.defaultSession = "xfce+icewm";
</listitem>
<listitem>
<para>
+ The <literal>roundcube</literal> module has been hardened.
+ <itemizedlist>
+ <listitem>
+ <para>
+ The password of the database is not written world readable in the store any more. If <literal>database.host</literal> is set to <literal>localhost</literal>, then a unix user of the same name as the database will be created and PostreSQL peer authentication will be used, removing the need for a password. Otherwise, a password is still needed and can be provided with the new option <literal>database.passwordFile</literal>, which should be set to the path of a file containing the password and readable by the user <literal>nginx</literal> only. The <literal>database.password</literal> option is insecure and deprecated. Usage of this option will print a warning.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ A random <literal>des_key</literal> is set by default in the configuration of roundcube, instead of using the hardcoded and insecure default. To ensure a clean migration, all users will be logged out when you upgrade to this release.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
The packages <literal>openobex</literal> and <literal>obexftp</literal>
are no longer installed when enabling Bluetooth via
<option>hardware.bluetooth.enable</option>.
@@ -409,15 +440,19 @@ users.users.me =
</listitem>
<listitem>
<para>
- The <link linkend="opt-services.buildkite-agent.enable">Buildkite Agent</link>
- module and corresponding packages have been updated to 3.x.
- While doing so, the following options have been changed:
+ The <link linkend="opt-services.buildkite-agents">Buildkite
+ Agent</link> module and corresponding packages have been updated to
+ 3.x, and to support multiple instances of the agent running at the
+ same time. This means you will have to rename
+ <literal>services.buildkite-agent</literal> to
+ <literal>services.buildkite-agents.&lt;name&gt;</literal>. Furthermore,
+ the following options have been changed:
</para>
<itemizedlist>
<listitem>
<para>
<literal>services.buildkite-agent.meta-data</literal> has been renamed to
- <link linkend="opt-services.buildkite-agent.tags">services.buildkite-agent.tags</link>,
+ <link linkend="opt-services.buildkite-agents">services.buildkite-agents.&lt;name&gt;.tags</link>,
to match upstreams naming for 3.x.
Its type has also changed - it now accepts an attrset of strings.
</para>
@@ -433,13 +468,13 @@ users.users.me =
<para>
<literal>services.buildkite-agent.openssh.privateKeyPath</literal>
has been renamed to
- <link linkend="opt-services.buildkite-agent.privateSshKeyPath">buildkite-agent.privateSshKeyPath</link>,
+ <link linkend="opt-services.buildkite-agents">buildkite-agents.&lt;name&gt;.privateSshKeyPath</link>,
as the whole <literal>openssh</literal> now only contained that single option.
</para>
</listitem>
<listitem>
<para>
- <link linkend="opt-services.buildkite-agent.shell">services.buildkite-agent.shell</link>
+ <link linkend="opt-services.buildkite-agents">services.buildkite-agents.&lt;name&gt;.shell</link>
has been introduced, allowing to specify a custom shell to be used.
</para>
</listitem>
@@ -539,6 +574,80 @@ auth required pam_succeed_if.so uid >= 1000 quiet
<listitem>
<para>The LLVM versions 3.5, 3.9 and 4 (including the corresponding CLang versions) have been dropped.</para>
</listitem>
+ <listitem>
+ <para>
+ The <option>networking.interfaces.*.preferTempAddress</option> option has
+ been replaced by <option>networking.interfaces.*.tempAddress</option>.
+ The new option allows better control of the IPv6 temporary addresses,
+ including completely disabling them for interfaces where they are not
+ needed.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Rspamd was updated to version 2.2. Read
+ <link xlink:href="https://rspamd.com/doc/migration.html#migration-to-rspamd-20">
+ the upstream migration notes</link> carefully. Please be especially
+ aware that some modules were removed and the default Bayes backend is
+ now Redis.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The <literal>*psu</literal> versions of <package>oraclejdk8</package> have been removed
+ as they aren't provided by upstream anymore.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The <option>services.dnscrypt-proxy</option> module has been removed
+ as it used the deprecated version of dnscrypt-proxy. We've added
+ <xref linkend="opt-services.dnscrypt-proxy2.enable"/> to use the supported version.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>qesteidutil</literal> has been deprecated in favor of <literal>qdigidoc</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <package>sqldeveloper_18</package> has been removed as it's not maintained anymore,
+ <package>sqldeveloper</package> has been updated to version <literal>19.4</literal>.
+ Please note that this means that this means that the <package>oraclejdk</package> is now
+ required. For further information please read the
+ <link xlink:href="https://www.oracle.com/technetwork/developer-tools/sql-developer/downloads/sqldev-relnotes-194-5908846.html">release notes</link>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The <package>gcc-snapshot</package>-package has been removed. It's marked as broken for &gt;2 years and used to point
+ to a fairly old snapshot from the <package>gcc7</package>-branch.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The <citerefentry><refentrytitle>nixos-build-vms</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>-script now uses the python test-driver.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The <package>riot-web</package> package now accepts configuration overrides as an attribute set instead of a string.
+ A formerly used JSON configuration can be converted to an attribute set with <literal>builtins.fromJSON</literal>.
+ </para>
+ <para>
+ The new default configuration also disables automatic guest account registration and analytics to improve privacy.
+ The previous behavior can be restored by setting <literal>config.riot-web.conf = { disable_guests = false; piwik = true; }</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Stand-alone usage of <literal>Upower</literal> now requires
+ <option>services.upower.enable</option> instead of just installing into
+ <xref linkend="opt-environment.systemPackages"/>.
+ </para>
+ </listitem>
</itemizedlist>
</section>
@@ -579,12 +688,94 @@ auth required pam_succeed_if.so uid >= 1000 quiet
now uses the short rather than full version string.
</para>
</listitem>
- <listitem>
+ <listitem>
+ <para>
+ The ACME module has switched from simp-le to <link xlink:href="https://github.com/go-acme/lego">lego</link>
+ which allows us to support DNS-01 challenges and wildcard certificates. The following options have been added:
+ <link linkend="opt-security.acme.acceptTerms">security.acme.acceptTerms</link>,
+ <link linkend="opt-security.acme.certs">security.acme.certs.&lt;name&gt;.dnsProvider</link>,
+ <link linkend="opt-security.acme.certs">security.acme.certs.&lt;name&gt;.credentialsFile</link>,
+ <link linkend="opt-security.acme.certs">security.acme.certs.&lt;name&gt;.dnsPropagationCheck</link>.
+ As well as this, the options <literal>security.acme.acceptTerms</literal> and either
+ <literal>security.acme.email</literal> or <literal>security.acme.certs.&lt;name&gt;.email</literal>
+ must be set in order to use the ACME module.
+ Certificates will be regenerated anew on the next renewal date. The credentials for simp-le are
+ preserved and thus it is possible to roll back to previous versions without breaking certificate
+ generation.
+ </para>
+ </listitem>
+ <listitem>
<para>
It is now possible to unlock LUKS-Encrypted file systems using a FIDO2 token
via <option>boot.initrd.luks.fido2Support</option>.
</para>
</listitem>
+ <listitem>
+ <para>
+ Predicatbly named network-interfaces get renamed in stage-1. This means that it's possible
+ to use the proper interface name for e.g. dropbear-setups.
+ </para>
+ <para>
+ For further reference, please read <link xlink:href="https://github.com/NixOS/nixpkgs/pull/68953">#68953</link> or the corresponding <link xlink:href="https://discourse.nixos.org/t/predictable-network-interface-names-in-initrd/4055">discourse thread</link>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The <package>matrix-synapse</package>-package has been updated to
+ <link xlink:href="https://github.com/matrix-org/synapse/releases/tag/v1.11.1">v1.11.1</link>.
+ Due to <link xlink:href="https://github.com/matrix-org/synapse/releases/tag/v1.10.0rc1">stricter requirements</link>
+ for database configuration when using <package>postgresql</package>, the automated database setup
+ of the module has been removed to avoid any further edge-cases.
+ </para>
+ <para>
+ <package>matrix-synapse</package> expects <literal>postgresql</literal>-databases to have the options
+ <literal>LC_COLLATE</literal> and <literal>LC_CTYPE</literal> set to
+ <link xlink:href="https://www.postgresql.org/docs/12/locale.html"><literal>'C'</literal></link> which basically
+ instructs <literal>postgresql</literal> to ignore any locale-based preferences.
+ </para>
+ <para>
+ Depending on your setup, you need to incorporate one of the following changes in your setup to
+ upgrade to 20.03:
+ <itemizedlist>
+ <listitem><para>If you use <literal>sqlite3</literal> you don't need to do anything.</para></listitem>
+ <listitem><para>If you use <literal>postgresql</literal> on a different server, you don't need
+ to change anything as well since this module was never designed to configure remote databases.
+ </para></listitem>
+ <listitem><para>If you use <literal>postgresql</literal> and configured your synapse initially on
+ <literal>19.09</literal> or older, you simply need to enable <package>postgresql</package>-support
+ explicitly:
+<programlisting>{ ... }: {
+ services.matrix-synapse = {
+ <link linkend="opt-services.matrix-synapse.enable">enable</link> = true;
+ /* and all the other config you've defined here */
+ };
+ <link linkend="opt-services.postgresql.enable">services.postgresql.enable</link> = true;
+}</programlisting>
+ </para></listitem>
+ <listitem><para>If you deploy a fresh <package>matrix-synapse</package>, you need to configure
+ the database yourself (e.g. by using the
+ <link linkend="opt-services.postgresql.initialScript">services.postgresql.initialScript</link>
+ option). An example for this can be found in the
+ <link linkend="module-services-matrix">documentation of the Matrix module</link>.
+ </para></listitem>
+ <listitem><para>If you initially deployed your <package>matrix-synapse</package> on
+ <literal>nixos-unstable</literal> <emphasis>after</emphasis> the <literal>19.09</literal>-release,
+ your database is misconfigured due to a regression in NixOS. For now, <package>matrix-synapse</package> will
+ startup with a warning, but it's recommended to reconfigure the database to set the values
+ <literal>LC_COLLATE</literal> and <literal>LC_CTYPE</literal> to
+ <link xlink:href="https://www.postgresql.org/docs/12/locale.html"><literal>'C'</literal></link>.
+ </para></listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The <link linkend="opt-systemd.network.links">systemd.network.links</link> option is now respected
+ even when <link linkend="opt-systemd.network.enable">systemd-networkd</link> is disabled.
+ This mirrors the behaviour of systemd - It's udev that parses <literal>.link</literal> files,
+ not <command>systemd-networkd</command>.
+ </para>
+ </listitem>
</itemizedlist>
</section>
</section>
diff --git a/nixpkgs/nixos/doc/manual/release-notes/rl-2009.xml b/nixpkgs/nixos/doc/manual/release-notes/rl-2009.xml
new file mode 100644
index 00000000000..2f61ee5ae2e
--- /dev/null
+++ b/nixpkgs/nixos/doc/manual/release-notes/rl-2009.xml
@@ -0,0 +1,115 @@
+<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-release-20.09">
+ <title>Release 20.09 (“Nightingale”, 2020.09/??)</title>
+
+ <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-release-20.09-highlights">
+ <title>Highlights</title>
+
+ <para>
+ In addition to numerous new and upgraded packages, this release has the
+ following highlights:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Support is planned until the end of April 2021, handing over to 21.03.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ PHP now defaults to PHP 7.4, updated from 7.3.
+ </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>
+ in your <link linkend="opt-services.openssh.extraConfig">services.openssh.extraConfig</link> you should
+ make use of these new options instead.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <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-release-20.09-new-services">
+ <title>New Services</title>
+
+ <para>
+ The following new services were added since the last release:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para />
+ </listitem>
+ </itemizedlist>
+
+ </section>
+
+ <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-release-20.09-incompatibilities">
+ <title>Backward Incompatibilities</title>
+
+ <para>
+ When upgrading from a previous release, please be aware of the following
+ incompatible changes:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Grafana is now built without support for phantomjs by default. Phantomjs support has been
+ <link xlink:href="https://grafana.com/docs/grafana/latest/guides/whats-new-in-v6-4/">deprecated in Grafana</link>
+ and the <package>phantomjs</package> project is
+ <link xlink:href="https://github.com/ariya/phantomjs/issues/15344#issue-302015362">currently unmaintained</link>.
+ It can still be enabled by providing <literal>phantomJsSupport = true</literal> to the package instanciation:
+<programlisting>{
+ services.grafana.package = pkgs.grafana.overrideAttrs (oldAttrs: rec {
+ phantomJsSupport = false;
+ });
+}</programlisting>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The <link linkend="opt-services.supybot.enable">supybot</link> module now uses <literal>/var/lib/supybot</literal>
+ as its default <link linkend="opt-services.supybot.stateDir">stateDir</link> path if <literal>stateVersion</literal>
+ is 20.09 or higher. It also enables number of
+ <link xlink:href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Sandboxing">systemd sandboxing options</link>
+ which may possibly interfere with some plugins. If this is the case you can disable the options through attributes in
+ <option>systemd.services.supybot.serviceConfig</option>.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <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-release-20.09-notable-changes">
+ <title>Other Notable Changes</title>
+
+ <itemizedlist>
+ <listitem>
+ <para />
+ </listitem>
+ </itemizedlist>
+ </section>
+</section>
diff --git a/nixpkgs/nixos/lib/eval-config.nix b/nixpkgs/nixos/lib/eval-config.nix
index 77490ca3762..9892d6f160f 100644
--- a/nixpkgs/nixos/lib/eval-config.nix
+++ b/nixpkgs/nixos/lib/eval-config.nix
@@ -41,6 +41,12 @@ let
# default to the argument. That way this new default could propagate all
# they way through, but has the last priority behind everything else.
nixpkgs.system = lib.mkDefault system;
+
+ # Stash the value of the `system` argument. When using `nesting.children`
+ # we want to have the same default value behavior (immediately above)
+ # without any interference from the user's configuration.
+ nixpkgs.initialSystem = system;
+
_module.args.pkgs = lib.mkIf (pkgs_ != null) (lib.mkForce pkgs_);
};
};
diff --git a/nixpkgs/nixos/lib/make-ext4-fs.nix b/nixpkgs/nixos/lib/make-ext4-fs.nix
index f46d3990c06..627ac324cf5 100644
--- a/nixpkgs/nixos/lib/make-ext4-fs.nix
+++ b/nixpkgs/nixos/lib/make-ext4-fs.nix
@@ -64,7 +64,7 @@ pkgs.stdenv.mkDerivation {
echo "copying files to image..."
cptofs -t ext4 -i $img ./files/* /
-
+ 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.
if ! fsck.ext4 -n -f $img; then
echo "--- Fsck failed for EXT4 image of $bytes bytes (numInodes=$numInodes, numDataBlocks=$numDataBlocks) ---"
@@ -72,21 +72,8 @@ pkgs.stdenv.mkDerivation {
return 1
fi
- (
- # Resizes **snugly** to its actual limits (or closer to)
- free=$(dumpe2fs $img | grep '^Free blocks:')
- blocksize=$(dumpe2fs $img | grep '^Block size:')
- blocks=$(dumpe2fs $img | grep '^Block count:')
- blocks=$((''${blocks##*:})) # format the number.
- blocksize=$((''${blocksize##*:})) # format the number.
- # System can't boot with 0 blocks free.
- # Add 16MiB of free space
- fudge=$(( 16 * 1024 * 1024 / blocksize ))
- size=$(( blocks - ''${free##*:} + fudge ))
-
- echo "Resizing from $blocks blocks to $size blocks. (~ $((size*blocksize/1024/1024))MiB)"
- EXT2FS_NO_MTAB_OK=yes resize2fs $img -f $size
- )
+ echo "Resizing to minimum allowed size"
+ resize2fs -M $img
# And a final fsck, because of the previous truncating.
fsck.ext4 -n -f $img
diff --git a/nixpkgs/nixos/lib/qemu-flags.nix b/nixpkgs/nixos/lib/qemu-flags.nix
index 774f66b4804..859d9e975fe 100644
--- a/nixpkgs/nixos/lib/qemu-flags.nix
+++ b/nixpkgs/nixos/lib/qemu-flags.nix
@@ -17,9 +17,9 @@ in
else throw "Unknown QEMU serial device for system '${pkgs.stdenv.hostPlatform.system}'";
qemuBinary = qemuPkg: {
- x86_64-linux = "${qemuPkg}/bin/qemu-kvm -cpu kvm64";
+ x86_64-linux = "${qemuPkg}/bin/qemu-kvm -cpu host";
armv7l-linux = "${qemuPkg}/bin/qemu-system-arm -enable-kvm -machine virt -cpu host";
aarch64-linux = "${qemuPkg}/bin/qemu-system-aarch64 -enable-kvm -machine virt,gic-version=host -cpu host";
- x86_64-darwin = "${qemuPkg}/bin/qemu-kvm -cpu kvm64";
+ x86_64-darwin = "${qemuPkg}/bin/qemu-kvm -cpu host";
}.${pkgs.stdenv.hostPlatform.system} or "${qemuPkg}/bin/qemu-kvm";
}
diff --git a/nixpkgs/nixos/lib/test-driver/test-driver.py b/nixpkgs/nixos/lib/test-driver/test-driver.py
index 75f80df53f2..c27947bc610 100644
--- a/nixpkgs/nixos/lib/test-driver/test-driver.py
+++ b/nixpkgs/nixos/lib/test-driver/test-driver.py
@@ -1,13 +1,17 @@
#! /somewhere/python3
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 _thread
import atexit
+import base64
import os
+import pathlib
import ptpython.repl
import pty
-from queue import Queue, Empty
import re
+import shlex
import shutil
import socket
import subprocess
@@ -15,9 +19,6 @@ import sys
import tempfile
import time
import unicodedata
-from typing import Tuple, Any, Callable, Dict, Iterator, Optional, List
-import shlex
-import pathlib
CHAR_TO_KEY = {
"A": "shift-a",
@@ -566,6 +567,41 @@ class Machine:
if ret.returncode != 0:
raise Exception("Cannot convert screenshot")
+ def copy_from_host_via_shell(self, source: str, target: str) -> None:
+ """Copy a file from the host into the guest by piping it over the
+ shell into the destination file. Works without host-guest shared folder.
+ Prefer copy_from_host for whenever possible.
+ """
+ with open(source, "rb") as fh:
+ content_b64 = base64.b64encode(fh.read()).decode()
+ self.succeed(
+ f"mkdir -p $(dirname {target})",
+ f"echo -n {content_b64} | base64 -d > {target}",
+ )
+
+ def copy_from_host(self, source: str, target: str) -> None:
+ """Copy a file from the host into the guest via the `shared_dir` shared
+ among all the VMs (using a temporary directory).
+ """
+ host_src = pathlib.Path(source)
+ vm_target = pathlib.Path(target)
+ with tempfile.TemporaryDirectory(dir=self.shared_dir) as shared_td:
+ shared_temp = pathlib.Path(shared_td)
+ host_intermediate = shared_temp / host_src.name
+ vm_shared_temp = pathlib.Path("/tmp/shared") / shared_temp.name
+ vm_intermediate = vm_shared_temp / host_src.name
+
+ self.succeed(make_command(["mkdir", "-p", vm_shared_temp]))
+ if host_src.is_dir():
+ shutil.copytree(host_src, host_intermediate)
+ else:
+ shutil.copy(host_src, host_intermediate)
+ self.succeed("sync")
+ self.succeed(make_command(["mkdir", "-p", vm_target.parent]))
+ self.succeed(make_command(["cp", "-r", vm_intermediate, vm_target]))
+ # Make sure the cleanup is synced into VM
+ self.succeed("sync")
+
def copy_from_vm(self, source: str, target_dir: str = "") -> None:
"""Copy a file from the VM (specified by an in-VM source path) to a path
relative to `$out`. The file is copied via the `shared_dir` shared among
@@ -875,7 +911,7 @@ def subtest(name: str) -> Iterator[None]:
if __name__ == "__main__":
log = Logger()
- vlan_nrs = list(dict.fromkeys(os.environ["VLANS"].split()))
+ vlan_nrs = list(dict.fromkeys(os.environ.get("VLANS", "").split()))
vde_sockets = [create_vlan(v) for v in vlan_nrs]
for nr, vde_socket, _, _ in vde_sockets:
os.environ["QEMU_VDE_SOCKET_{}".format(nr)] = vde_socket
diff --git a/nixpkgs/nixos/lib/testing-python.nix b/nixpkgs/nixos/lib/testing-python.nix
index a7f6d792651..3891adc1043 100644
--- a/nixpkgs/nixos/lib/testing-python.nix
+++ b/nixpkgs/nixos/lib/testing-python.nix
@@ -175,13 +175,13 @@ in rec {
nodeNames = builtins.attrNames nodes;
invalidNodeNames = lib.filter
- (node: builtins.match "^[A-z_][A-z0-9_]+$" node == null) nodeNames;
+ (node: builtins.match "^[A-z_]([A-z0-9_]+)?$" node == null) nodeNames;
in
if lib.length invalidNodeNames > 0 then
throw ''
Cannot create machines out of (${lib.concatStringsSep ", " invalidNodeNames})!
- All machines are referenced as perl variables in the testing framework which will break the
+ All machines are referenced as python variables in the testing framework which will break the
script when special characters are used.
Please stick to alphanumeric chars and underscores as separation.
@@ -218,12 +218,12 @@ in rec {
'';
testScript = ''
- startAll;
- $client->waitForUnit("multi-user.target");
+ start_all()
+ client.wait_for_unit("multi-user.target")
${preBuild}
- $client->succeed("env -i ${bash}/bin/bash ${buildrunner} /tmp/xchg/saved-env >&2");
+ client.succeed("env -i ${bash}/bin/bash ${buildrunner} /tmp/xchg/saved-env >&2")
${postBuild}
- $client->succeed("sync"); # flush all data before pulling the plug
+ client.succeed("sync") # flush all data before pulling the plug
'';
vmRunCommand = writeText "vm-run" ''
@@ -263,9 +263,12 @@ in rec {
{ ... }:
{
inherit require;
+ imports = [
+ ../tests/common/auto.nix
+ ];
virtualisation.memorySize = 1024;
services.xserver.enable = true;
- services.xserver.displayManager.auto.enable = true;
+ test-support.displayManager.auto.enable = true;
services.xserver.displayManager.defaultSession = "none+icewm";
services.xserver.windowManager.icewm.enable = true;
};
@@ -274,7 +277,7 @@ in rec {
machine = client;
preBuild =
''
- $client->waitForX;
+ client.wait_for_x()
'';
} // args);
diff --git a/nixpkgs/nixos/lib/testing.nix b/nixpkgs/nixos/lib/testing.nix
index ae8ecd6270c..7d6a5c0a290 100644
--- a/nixpkgs/nixos/lib/testing.nix
+++ b/nixpkgs/nixos/lib/testing.nix
@@ -19,7 +19,11 @@ in rec {
inherit pkgs;
- testDriver = stdenv.mkDerivation {
+ testDriver = lib.warn ''
+ Perl VM tests are deprecated and will be removed for 20.09.
+ Please update your tests to use the python test driver.
+ See https://github.com/NixOS/nixpkgs/pull/71684 for details.
+ '' stdenv.mkDerivation {
name = "nixos-test-driver";
buildInputs = [ makeWrapper perl ];
@@ -246,9 +250,12 @@ in rec {
{ ... }:
{
inherit require;
+ imports = [
+ ../tests/common/auto.nix
+ ];
virtualisation.memorySize = 1024;
services.xserver.enable = true;
- services.xserver.displayManager.auto.enable = true;
+ test-support.displayManager.auto.enable = true;
services.xserver.displayManager.defaultSession = "none+icewm";
services.xserver.windowManager.icewm.enable = true;
};
diff --git a/nixpkgs/nixos/lib/utils.nix b/nixpkgs/nixos/lib/utils.nix
index a522834e429..21f4c7c6988 100644
--- a/nixpkgs/nixos/lib/utils.nix
+++ b/nixpkgs/nixos/lib/utils.nix
@@ -14,7 +14,7 @@ rec {
# becomes dev-xyzzy. FIXME: slow.
escapeSystemdPath = s:
replaceChars ["/" "-" " "] ["-" "\\x2d" "\\x20"]
- (if hasPrefix "/" s then substring 1 (stringLength s) s else s);
+ (removePrefix "/" s);
# Returns a system path for a given shell package
toShellPath = shell:
diff --git a/nixpkgs/nixos/maintainers/scripts/ec2/create-amis.sh b/nixpkgs/nixos/maintainers/scripts/ec2/create-amis.sh
index 5dc1c5aaed5..145eb49ced7 100755
--- a/nixpkgs/nixos/maintainers/scripts/ec2/create-amis.sh
+++ b/nixpkgs/nixos/maintainers/scripts/ec2/create-amis.sh
@@ -18,7 +18,7 @@ state_dir=$HOME/amis/ec2-images
home_region=eu-west-1
bucket=nixos-amis
-regions=(eu-west-1 eu-west-2 eu-west-3 eu-central-1
+regions=(eu-west-1 eu-west-2 eu-west-3 eu-central-1 eu-north-1
us-east-1 us-east-2 us-west-1 us-west-2
ca-central-1
ap-southeast-1 ap-southeast-2 ap-northeast-1 ap-northeast-2
diff --git a/nixpkgs/nixos/modules/config/ldap.nix b/nixpkgs/nixos/modules/config/ldap.nix
index 9c8e9d14937..b554f197dc4 100644
--- a/nixpkgs/nixos/modules/config/ldap.nix
+++ b/nixpkgs/nixos/modules/config/ldap.nix
@@ -28,8 +28,6 @@ let
};
nslcdConfig = writeText "nslcd.conf" ''
- uid nslcd
- gid nslcd
uri ${cfg.server}
base ${cfg.base}
timelimit ${toString cfg.timeLimit}
@@ -282,6 +280,7 @@ in
Group = "nslcd";
RuntimeDirectory = [ "nslcd" ];
PIDFile = "/run/nslcd/nslcd.pid";
+ AmbientCapabilities = "CAP_SYS_RESOURCE";
};
};
diff --git a/nixpkgs/nixos/modules/config/networking.nix b/nixpkgs/nixos/modules/config/networking.nix
index 81427bb8ee6..dd36696b94d 100644
--- a/nixpkgs/nixos/modules/config/networking.nix
+++ b/nixpkgs/nixos/modules/config/networking.nix
@@ -35,12 +35,22 @@ in
'';
};
+ networking.hostFiles = lib.mkOption {
+ type = types.listOf types.path;
+ defaultText = lib.literalExample "Hosts from `networking.hosts` and `networking.extraHosts`";
+ example = lib.literalExample ''[ "''${pkgs.my-blocklist-package}/share/my-blocklist/hosts" ]'';
+ description = ''
+ Files that should be concatenated together to form <filename>/etc/hosts</filename>.
+ '';
+ };
+
networking.extraHosts = lib.mkOption {
type = types.lines;
default = "";
example = "192.168.0.1 lanlocalhost";
description = ''
Additional verbatim entries to be appended to <filename>/etc/hosts</filename>.
+ For adding hosts from derivation results, use <option>networking.hostFiles</option> instead.
'';
};
@@ -159,6 +169,15 @@ in
"::1" = [ "localhost" ];
};
+ networking.hostFiles = let
+ stringHosts =
+ let
+ oneToString = set: ip: ip + " " + concatStringsSep " " set.${ip} + "\n";
+ allToString = set: concatMapStrings (oneToString set) (attrNames set);
+ in pkgs.writeText "string-hosts" (allToString (filterAttrs (_: v: v != []) cfg.hosts));
+ extraHosts = pkgs.writeText "extra-hosts" cfg.extraHosts;
+ in mkBefore [ stringHosts extraHosts ];
+
environment.etc =
{ # /etc/services: TCP/UDP port assignments.
services.source = pkgs.iana-etc + "/etc/services";
@@ -167,12 +186,8 @@ in
protocols.source = pkgs.iana-etc + "/etc/protocols";
# /etc/hosts: Hostname-to-IP mappings.
- hosts.text = let
- oneToString = set: ip: ip + " " + concatStringsSep " " set.${ip};
- allToString = set: concatMapStringsSep "\n" (oneToString set) (attrNames set);
- in ''
- ${allToString (filterAttrs (_: v: v != []) cfg.hosts)}
- ${cfg.extraHosts}
+ hosts.source = pkgs.runCommandNoCC "hosts" {} ''
+ cat ${escapeShellArgs cfg.hostFiles} > $out
'';
# /etc/host.conf: resolver configuration file
diff --git a/nixpkgs/nixos/modules/config/pulseaudio.nix b/nixpkgs/nixos/modules/config/pulseaudio.nix
index 048bbb30c73..408d0a9c33f 100644
--- a/nixpkgs/nixos/modules/config/pulseaudio.nix
+++ b/nixpkgs/nixos/modules/config/pulseaudio.nix
@@ -248,6 +248,9 @@ in {
security.rtkit.enable = true;
systemd.packages = [ overriddenPackage ];
+
+ # PulseAudio is packaged with udev rules to handle various audio device quirks
+ services.udev.packages = [ overriddenPackage ];
})
(mkIf (cfg.extraModules != []) {
diff --git a/nixpkgs/nixos/modules/config/resolvconf.nix b/nixpkgs/nixos/modules/config/resolvconf.nix
index 7d2f252a888..cc202bca6c4 100644
--- a/nixpkgs/nixos/modules/config/resolvconf.nix
+++ b/nixpkgs/nixos/modules/config/resolvconf.nix
@@ -38,6 +38,7 @@ in
(mkRenamedOptionModule [ "networking" "dnsExtensionMechanism" ] [ "networking" "resolvconf" "dnsExtensionMechanism" ])
(mkRenamedOptionModule [ "networking" "extraResolvconfConf" ] [ "networking" "resolvconf" "extraConfig" ])
(mkRenamedOptionModule [ "networking" "resolvconfOptions" ] [ "networking" "resolvconf" "extraOptions" ])
+ (mkRemovedOptionModule [ "networking" "resolvconf" "useHostResolvConf" ] "This option was never used for anything anyways")
];
options = {
@@ -53,15 +54,6 @@ in
'';
};
- useHostResolvConf = mkOption {
- type = types.bool;
- default = false;
- description = ''
- In containers, whether to use the
- <filename>resolv.conf</filename> supplied by the host.
- '';
- };
-
dnsSingleRequest = lib.mkOption {
type = types.bool;
default = false;
diff --git a/nixpkgs/nixos/modules/config/swap.nix b/nixpkgs/nixos/modules/config/swap.nix
index d0fc0d4a3ea..adb4e229421 100644
--- a/nixpkgs/nixos/modules/config/swap.nix
+++ b/nixpkgs/nixos/modules/config/swap.nix
@@ -185,6 +185,8 @@ in
{ description = "Initialisation of swap device ${sw.device}";
wantedBy = [ "${realDevice'}.swap" ];
before = [ "${realDevice'}.swap" ];
+ # If swap is encrypted, depending on rngd resolves a possible entropy starvation during boot
+ after = mkIf (config.security.rngd.enable && sw.randomEncryption.enable) [ "rngd.service" ];
path = [ pkgs.utillinux ] ++ optional sw.randomEncryption.enable pkgs.cryptsetup;
script =
diff --git a/nixpkgs/nixos/modules/config/system-path.nix b/nixpkgs/nixos/modules/config/system-path.nix
index aba9bc0945b..4100ec89701 100644
--- a/nixpkgs/nixos/modules/config/system-path.nix
+++ b/nixpkgs/nixos/modules/config/system-path.nix
@@ -116,6 +116,7 @@ in
"/lib" # FIXME: remove and update debug-info.nix
"/sbin"
"/share/emacs"
+ "/share/hunspell"
"/share/nano"
"/share/org"
"/share/themes"
diff --git a/nixpkgs/nixos/modules/config/xdg/portal.nix b/nixpkgs/nixos/modules/config/xdg/portal.nix
index 95fa8e05fa3..1330a08070c 100644
--- a/nixpkgs/nixos/modules/config/xdg/portal.nix
+++ b/nixpkgs/nixos/modules/config/xdg/portal.nix
@@ -42,6 +42,10 @@ with lib;
let
cfg = config.xdg.portal;
packages = [ pkgs.xdg-desktop-portal ] ++ cfg.extraPortals;
+ joinedPortals = pkgs.symlinkJoin {
+ name = "xdg-portals";
+ paths = cfg.extraPortals;
+ };
in mkIf cfg.enable {
@@ -56,7 +60,7 @@ with lib;
environment.variables = {
GTK_USE_PORTAL = mkIf cfg.gtkUsePortal "1";
- XDG_DESKTOP_PORTAL_PATH = map (p: "${p}/share/xdg-desktop-portal/portals") cfg.extraPortals;
+ XDG_DESKTOP_PORTAL_DIR = "${joinedPortals}/share/xdg-desktop-portal/portals";
};
};
}
diff --git a/nixpkgs/nixos/modules/hardware/brightnessctl.nix b/nixpkgs/nixos/modules/hardware/brightnessctl.nix
deleted file mode 100644
index 2d54398d10d..00000000000
--- a/nixpkgs/nixos/modules/hardware/brightnessctl.nix
+++ /dev/null
@@ -1,31 +0,0 @@
-{ config, lib, pkgs, ... }:
-
-with lib;
-let
- cfg = config.hardware.brightnessctl;
-in
-{
-
- options = {
-
- hardware.brightnessctl = {
-
- enable = mkOption {
- default = false;
- type = types.bool;
- description = ''
- Enable brightnessctl in userspace.
- This will allow brightness control from users in the video group.
- '';
-
- };
- };
- };
-
-
- config = mkIf cfg.enable {
- services.udev.packages = with pkgs; [ brightnessctl ];
- environment.systemPackages = with pkgs; [ brightnessctl ];
- };
-
-}
diff --git a/nixpkgs/nixos/modules/hardware/openrazer.nix b/nixpkgs/nixos/modules/hardware/openrazer.nix
index 883db7f2f4f..b5c3d674414 100644
--- a/nixpkgs/nixos/modules/hardware/openrazer.nix
+++ b/nixpkgs/nixos/modules/hardware/openrazer.nix
@@ -49,7 +49,7 @@ in
{
options = {
hardware.openrazer = {
- enable = mkEnableOption "OpenRazer drivers and userspace daemon.";
+ enable = mkEnableOption "OpenRazer drivers and userspace daemon";
verboseLogging = mkOption {
type = types.bool;
diff --git a/nixpkgs/nixos/modules/hardware/video/amdgpu-pro.nix b/nixpkgs/nixos/modules/hardware/video/amdgpu-pro.nix
index 8e91e9d2baa..ec1c8c2d57a 100644
--- a/nixpkgs/nixos/modules/hardware/video/amdgpu-pro.nix
+++ b/nixpkgs/nixos/modules/hardware/video/amdgpu-pro.nix
@@ -30,7 +30,7 @@ in
nixpkgs.config.xorg.abiCompat = "1.19";
services.xserver.drivers = singleton
- { name = "amdgpu"; modules = [ package ]; };
+ { name = "amdgpu"; modules = [ package ]; display = true; };
hardware.opengl.package = package;
hardware.opengl.package32 = package32;
diff --git a/nixpkgs/nixos/modules/hardware/video/ati.nix b/nixpkgs/nixos/modules/hardware/video/ati.nix
index 0aab7bd6b92..06d3ea324d8 100644
--- a/nixpkgs/nixos/modules/hardware/video/ati.nix
+++ b/nixpkgs/nixos/modules/hardware/video/ati.nix
@@ -21,7 +21,7 @@ in
nixpkgs.config.xorg.abiCompat = "1.17";
services.xserver.drivers = singleton
- { name = "fglrx"; modules = [ ati_x11 ]; };
+ { name = "fglrx"; modules = [ ati_x11 ]; display = true; };
hardware.opengl.package = ati_x11;
hardware.opengl.package32 = pkgs.pkgsi686Linux.linuxPackages.ati_drivers_x11.override { libsOnly = true; kernel = null; };
diff --git a/nixpkgs/nixos/modules/hardware/video/nvidia.nix b/nixpkgs/nixos/modules/hardware/video/nvidia.nix
index 1794bb4b433..7461e231402 100644
--- a/nixpkgs/nixos/modules/hardware/video/nvidia.nix
+++ b/nixpkgs/nixos/modules/hardware/video/nvidia.nix
@@ -34,26 +34,57 @@ let
enabled = nvidia_x11 != null;
cfg = config.hardware.nvidia;
- optimusCfg = cfg.optimus_prime;
+ pCfg = cfg.prime;
+ syncCfg = pCfg.sync;
+ offloadCfg = pCfg.offload;
+ primeEnabled = syncCfg.enable || offloadCfg.enable;
in
{
+ imports =
+ [
+ (mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "enable" ] [ "hardware" "nvidia" "prime" "sync" "enable" ])
+ (mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "allowExternalGpu" ] [ "hardware" "nvidia" "prime" "sync" "allowExternalGpu" ])
+ (mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "nvidiaBusId" ] [ "hardware" "nvidia" "prime" "nvidiaBusId" ])
+ (mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "intelBusId" ] [ "hardware" "nvidia" "prime" "intelBusId" ])
+ ];
+
options = {
- hardware.nvidia.modesetting.enable = lib.mkOption {
- type = lib.types.bool;
+ hardware.nvidia.modesetting.enable = mkOption {
+ type = types.bool;
default = false;
description = ''
Enable kernel modesetting when using the NVIDIA proprietary driver.
Enabling this fixes screen tearing when using Optimus via PRIME (see
- <option>hardware.nvidia.optimus_prime.enable</option>. This is not enabled
+ <option>hardware.nvidia.prime.sync.enable</option>. This is not enabled
by default because it is not officially supported by NVIDIA and would not
work with SLI.
'';
};
- hardware.nvidia.optimus_prime.enable = lib.mkOption {
- type = lib.types.bool;
+ hardware.nvidia.prime.nvidiaBusId = mkOption {
+ type = types.str;
+ default = "";
+ example = "PCI:1:0:0";
+ description = ''
+ Bus ID of the NVIDIA GPU. You can find it using lspci; for example if lspci
+ shows the NVIDIA GPU at "01:00.0", set this option to "PCI:1:0:0".
+ '';
+ };
+
+ hardware.nvidia.prime.intelBusId = mkOption {
+ type = types.str;
+ default = "";
+ example = "PCI:0:2:0";
+ description = ''
+ Bus ID of the Intel GPU. You can find it using lspci; for example if lspci
+ shows the Intel GPU at "00:02.0", set this option to "PCI:0:2:0".
+ '';
+ };
+
+ hardware.nvidia.prime.sync.enable = mkOption {
+ type = types.bool;
default = false;
description = ''
Enable NVIDIA Optimus support using the NVIDIA proprietary driver via PRIME.
@@ -66,8 +97,8 @@ in
be the only driver there.
If this is enabled, then the bus IDs of the NVIDIA and Intel GPUs have to be
- specified (<option>hardware.nvidia.optimus_prime.nvidiaBusId</option> and
- <option>hardware.nvidia.optimus_prime.intelBusId</option>).
+ specified (<option>hardware.nvidia.prime.nvidiaBusId</option> and
+ <option>hardware.nvidia.prime.intelBusId</option>).
If you enable this, you may want to also enable kernel modesetting for the
NVIDIA driver (<option>hardware.nvidia.modesetting.enable</option>) in order
@@ -79,31 +110,23 @@ in
'';
};
- hardware.nvidia.optimus_prime.allowExternalGpu = lib.mkOption {
- type = lib.types.bool;
+ hardware.nvidia.prime.sync.allowExternalGpu = mkOption {
+ type = types.bool;
default = false;
description = ''
Configure X to allow external NVIDIA GPUs when using optimus.
'';
};
- hardware.nvidia.optimus_prime.nvidiaBusId = lib.mkOption {
- type = lib.types.str;
- default = "";
- example = "PCI:1:0:0";
+ hardware.nvidia.prime.offload.enable = mkOption {
+ type = types.bool;
+ default = false;
description = ''
- Bus ID of the NVIDIA GPU. You can find it using lspci; for example if lspci
- shows the NVIDIA GPU at "01:00.0", set this option to "PCI:1:0:0".
- '';
- };
+ Enable render offload support using the NVIDIA proprietary driver via PRIME.
- hardware.nvidia.optimus_prime.intelBusId = lib.mkOption {
- type = lib.types.str;
- default = "";
- example = "PCI:0:2:0";
- description = ''
- Bus ID of the Intel GPU. You can find it using lspci; for example if lspci
- shows the Intel GPU at "00:02.0", set this option to "PCI:0:2:0".
+ If this is enabled, then the bus IDs of the NVIDIA and Intel GPUs have to be
+ specified (<option>hardware.nvidia.prime.nvidiaBusId</option> and
+ <option>hardware.nvidia.prime.intelBusId</option>).
'';
};
};
@@ -116,12 +139,19 @@ in
}
{
- assertion = !optimusCfg.enable ||
- (optimusCfg.nvidiaBusId != "" && optimusCfg.intelBusId != "");
+ assertion = primeEnabled -> pCfg.nvidiaBusId != "" && pCfg.intelBusId != "";
message = ''
- When NVIDIA Optimus via PRIME is enabled, the GPU bus IDs must configured.
+ When NVIDIA PRIME is enabled, the GPU bus IDs must configured.
'';
}
+ {
+ assertion = offloadCfg.enable -> versionAtLeast nvidia_x11.version "435.21";
+ message = "NVIDIA PRIME render offload is currently only supported on versions >= 435.21.";
+ }
+ {
+ assertion = !(syncCfg.enable && offloadCfg.enable);
+ message = "Only one NVIDIA PRIME solution may be used at a time.";
+ }
];
# If Optimus/PRIME is enabled, we:
@@ -136,36 +166,38 @@ in
# - Configure the display manager to run specific `xrandr` commands which will
# configure/enable displays connected to the Intel GPU.
- services.xserver.drivers = singleton {
+ services.xserver.useGlamor = mkDefault offloadCfg.enable;
+
+ services.xserver.drivers = optional primeEnabled {
+ name = "modesetting";
+ display = offloadCfg.enable;
+ deviceSection = ''
+ BusID "${pCfg.intelBusId}"
+ ${optionalString syncCfg.enable ''Option "AccelMethod" "none"''}
+ '';
+ } ++ singleton {
name = "nvidia";
modules = [ nvidia_x11.bin ];
- deviceSection = optionalString optimusCfg.enable
+ display = !offloadCfg.enable;
+ deviceSection = optionalString primeEnabled
''
- BusID "${optimusCfg.nvidiaBusId}"
- ${optionalString optimusCfg.allowExternalGpu "Option \"AllowExternalGpus\""}
+ BusID "${pCfg.nvidiaBusId}"
+ ${optionalString syncCfg.allowExternalGpu "Option \"AllowExternalGpus\""}
'';
screenSection =
''
Option "RandRRotation" "on"
- ${optionalString optimusCfg.enable "Option \"AllowEmptyInitialConfiguration\""}
+ ${optionalString syncCfg.enable "Option \"AllowEmptyInitialConfiguration\""}
'';
};
- services.xserver.extraConfig = optionalString optimusCfg.enable
- ''
- Section "Device"
- Identifier "nvidia-optimus-intel"
- Driver "modesetting"
- BusID "${optimusCfg.intelBusId}"
- Option "AccelMethod" "none"
- EndSection
- '';
- services.xserver.serverLayoutSection = optionalString optimusCfg.enable
- ''
- Inactive "nvidia-optimus-intel"
- '';
+ services.xserver.serverLayoutSection = optionalString syncCfg.enable ''
+ Inactive "Device-modesetting[0]"
+ '' + optionalString offloadCfg.enable ''
+ Option "AllowNVIDIAGPUScreens"
+ '';
- services.xserver.displayManager.setupCommands = optionalString optimusCfg.enable ''
+ services.xserver.displayManager.setupCommands = optionalString syncCfg.enable ''
# Added by nvidia configuration module for Optimus/PRIME.
${pkgs.xorg.xrandr}/bin/xrandr --setprovideroutputsource modesetting NVIDIA-0
${pkgs.xorg.xrandr}/bin/xrandr --auto
@@ -175,11 +207,13 @@ in
source = "${nvidia_x11.bin}/share/nvidia/nvidia-application-profiles-rc";
};
- hardware.opengl.package = nvidia_x11.out;
- hardware.opengl.package32 = nvidia_libs32;
+ hardware.opengl.package = mkIf (!offloadCfg.enable) nvidia_x11.out;
+ hardware.opengl.package32 = mkIf (!offloadCfg.enable) nvidia_libs32;
+ hardware.opengl.extraPackages = optional offloadCfg.enable nvidia_x11.out;
+ hardware.opengl.extraPackages32 = optional offloadCfg.enable nvidia_libs32;
environment.systemPackages = [ nvidia_x11.bin nvidia_x11.settings ]
- ++ lib.filter (p: p != null) [ nvidia_x11.persistenced ];
+ ++ filter (p: p != null) [ nvidia_x11.persistenced ];
systemd.tmpfiles.rules = optional config.virtualisation.docker.enableNvidia
"L+ /run/nvidia-docker/bin - - - - ${nvidia_x11.bin}/origBin"
@@ -190,10 +224,10 @@ in
# nvidia-uvm is required by CUDA applications.
boot.kernelModules = [ "nvidia-uvm" ] ++
- lib.optionals config.services.xserver.enable [ "nvidia" "nvidia_modeset" "nvidia_drm" ];
+ optionals config.services.xserver.enable [ "nvidia" "nvidia_modeset" "nvidia_drm" ];
# If requested enable modesetting via kernel parameter.
- boot.kernelParams = optional cfg.modesetting.enable "nvidia-drm.modeset=1";
+ boot.kernelParams = optional (offloadCfg.enable || cfg.modesetting.enable) "nvidia-drm.modeset=1";
# Create /dev/nvidia-uvm when the nvidia-uvm module is loaded.
services.udev.extraRules =
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/channel.nix b/nixpkgs/nixos/modules/installer/cd-dvd/channel.nix
index ab5e7c0645f..92164d65e53 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/channel.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/channel.nix
@@ -21,7 +21,9 @@ let
if [ ! -e $out/nixos/nixpkgs ]; then
ln -s . $out/nixos/nixpkgs
fi
- echo -n ${config.system.nixos.revision} > $out/nixos/.git-revision
+ ${optionalString (config.system.nixos.revision != null) ''
+ echo -n ${config.system.nixos.revision} > $out/nixos/.git-revision
+ ''}
echo -n ${config.system.nixos.versionSuffix} > $out/nixos/.version-suffix
echo ${config.system.nixos.versionSuffix} | sed -e s/pre// > $out/nixos/svn-revision
'';
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix
index e0b558dcb0d..fa19daf1328 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix
@@ -44,6 +44,9 @@ with lib;
pkgs.bvi # binary editor
pkgs.joe
+ # Include some version control tools.
+ pkgs.git
+
# Firefox for reading the manual.
pkgs.firefox
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix
index 23c3426bff0..62cbdbcfd17 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix
@@ -1,5 +1,4 @@
-# This module defines a NixOS installation CD that contains X11 and
-# GNOME 3.
+# This module defines a NixOS installation CD that contains GNOME.
{ lib, ... }:
@@ -10,10 +9,22 @@ with lib;
services.xserver.desktopManager.gnome3.enable = true;
- # Auto-login as root.
- services.xserver.displayManager.gdm.autoLogin = {
+ # Wayland can be problematic for some hardware like Nvidia graphics cards.
+ services.xserver.displayManager.defaultSession = "gnome-xorg";
+
+ services.xserver.displayManager.gdm = {
enable = true;
- user = "root";
+ # autoSuspend makes the machine automatically suspend after inactivity.
+ # It's possible someone could/try to ssh'd into the machine and obviously
+ # have issues because it's inactive.
+ # See:
+ # * https://github.com/NixOS/nixpkgs/pull/63790
+ # * https://gitlab.gnome.org/GNOME/gnome-control-center/issues/22
+ autoSuspend = false;
+ autoLogin = {
+ enable = true;
+ user = "nixos";
+ };
};
}
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix b/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix
index 11319e5f4f8..4558b4dc955 100644
--- a/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix
+++ b/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -569,14 +569,18 @@ in
};
fileSystems."/nix/store" =
- { fsType = "unionfs-fuse";
- device = "unionfs";
- options = [ "allow_other" "cow" "nonempty" "chroot=/mnt-root" "max_files=32768" "hide_meta_files" "dirs=/nix/.rw-store=rw:/nix/.ro-store=ro" ];
+ { fsType = "overlay";
+ device = "overlay";
+ options = [
+ "lowerdir=/nix/.ro-store"
+ "upperdir=/nix/.rw-store/store"
+ "workdir=/nix/.rw-store/work"
+ ];
};
- boot.initrd.availableKernelModules = [ "squashfs" "iso9660" "uas" ];
+ boot.initrd.availableKernelModules = [ "squashfs" "iso9660" "uas" "overlay" ];
- boot.initrd.kernelModules = [ "loop" ];
+ boot.initrd.kernelModules = [ "loop" "overlay" ];
# Closures to be copied to the Nix store on the CD, namely the init
# script and the top-level system configuration directory.
diff --git a/nixpkgs/nixos/modules/installer/netboot/netboot.nix b/nixpkgs/nixos/modules/installer/netboot/netboot.nix
index 5146858cccf..95eba86bcb6 100644
--- a/nixpkgs/nixos/modules/installer/netboot/netboot.nix
+++ b/nixpkgs/nixos/modules/installer/netboot/netboot.nix
@@ -50,14 +50,18 @@ with lib;
};
fileSystems."/nix/store" =
- { fsType = "unionfs-fuse";
- device = "unionfs";
- options = [ "allow_other" "cow" "nonempty" "chroot=/mnt-root" "max_files=32768" "hide_meta_files" "dirs=/nix/.rw-store=rw:/nix/.ro-store=ro" ];
+ { fsType = "overlay";
+ device = "overlay";
+ options = [
+ "lowerdir=/nix/.ro-store"
+ "upperdir=/nix/.rw-store/store"
+ "workdir=/nix/.rw-store/work"
+ ];
};
- boot.initrd.availableKernelModules = [ "squashfs" ];
+ boot.initrd.availableKernelModules = [ "squashfs" "overlay" ];
- boot.initrd.kernelModules = [ "loop" ];
+ boot.initrd.kernelModules = [ "loop" "overlay" ];
# Closures to be copied to the Nix store, namely the init
# script and the top-level system configuration directory.
diff --git a/nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix b/nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix
index c2f2578733b..2068f27f1c9 100644
--- a/nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix
+++ b/nixpkgs/nixos/modules/installer/tools/nix-fallback-paths.nix
@@ -1,6 +1,6 @@
{
- x86_64-linux = "/nix/store/0q5qnh10m2sfrriszc1ysmggw659q6qm-nix-2.3.2";
- i686-linux = "/nix/store/i7ad7r5d8a5b3l22hg4a1im2qq05y6vd-nix-2.3.2";
- aarch64-linux = "/nix/store/bv06pavfw0dbqzr8w3l7s71nx27gnxa0-nix-2.3.2";
- x86_64-darwin = "/nix/store/x6mnl1nij7y4v5ihlplr4k937ayr403r-nix-2.3.2";
+ x86_64-linux = "/nix/store/ddmmzn4ggz1f66lwxjy64n89864yj9w9-nix-2.3.3";
+ i686-linux = "/nix/store/5axys7hsggb4282dsbps5k5p0v59yv13-nix-2.3.3";
+ aarch64-linux = "/nix/store/k80nwvi19hxwbz3c9cxgp24f1jjxwmcc-nix-2.3.3";
+ x86_64-darwin = "/nix/store/lrnvapsqmf0ja6zfyx4cpxr7ahdr7f9b-nix-2.3.3";
}
diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix b/nixpkgs/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix
index c1028a0ad7e..90f0702f717 100644
--- a/nixpkgs/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix
+++ b/nixpkgs/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix
@@ -5,7 +5,7 @@
let nodes = import networkExpr; in
-with import ../../../../lib/testing.nix {
+with import ../../../../lib/testing-python.nix {
inherit system;
pkgs = import ../../../../.. { inherit system config; };
};
diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-enter.sh b/nixpkgs/nixos/modules/installer/tools/nixos-enter.sh
index 4680cd8ae95..1fdd4627a90 100644
--- a/nixpkgs/nixos/modules/installer/tools/nixos-enter.sh
+++ b/nixpkgs/nixos/modules/installer/tools/nixos-enter.sh
@@ -60,15 +60,15 @@ chmod 0755 "$mountPoint/dev" "$mountPoint/sys"
mount --rbind /dev "$mountPoint/dev"
mount --rbind /sys "$mountPoint/sys"
-# If silent, write both stdout and stderr of activation script to /dev/null
-# otherwise, write both streams to stderr of this process
-if [ "$silent" -eq 0 ]; then
- PIPE_TARGET="/dev/stderr"
-else
- PIPE_TARGET="/dev/null"
-fi
+(
+ # If silent, write both stdout and stderr of activation script to /dev/null
+ # otherwise, write both streams to stderr of this process
+ if [ "$silent" -eq 1 ]; then
+ exec 2>/dev/null
+ fi
-# Run the activation script. Set $LOCALE_ARCHIVE to supress some Perl locale warnings.
-LOCALE_ARCHIVE="$system/sw/lib/locale/locale-archive" chroot "$mountPoint" "$system/activate" >>$PIPE_TARGET 2>&1 || true
+ # Run the activation script. Set $LOCALE_ARCHIVE to supress some Perl locale warnings.
+ LOCALE_ARCHIVE="$system/sw/lib/locale/locale-archive" chroot "$mountPoint" "$system/activate" 1>&2 || true
+)
exec chroot "$mountPoint" "${command[@]}"
diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-option/nixos-option.cc b/nixpkgs/nixos/modules/installer/tools/nixos-option/nixos-option.cc
index 9b92dc829cd..1a7b07a74f8 100644
--- a/nixpkgs/nixos/modules/installer/tools/nixos-option/nixos-option.cc
+++ b/nixpkgs/nixos/modules/installer/tools/nixos-option/nixos-option.cc
@@ -131,12 +131,12 @@ bool isOption(Context & ctx, const Value & v)
if (v.type != tAttrs) {
return false;
}
- const auto & atualType = v.attrs->find(ctx.underscoreType);
- if (atualType == v.attrs->end()) {
+ const auto & actualType = v.attrs->find(ctx.underscoreType);
+ if (actualType == v.attrs->end()) {
return false;
}
try {
- Value evaluatedType = evaluateValue(ctx, *atualType->value);
+ Value evaluatedType = evaluateValue(ctx, *actualType->value);
if (evaluatedType.type != tString) {
return false;
}
@@ -197,9 +197,107 @@ void recurse(const std::function<bool(const std::string & path, std::variant<Val
}
}
-// Calls f on all the option names
-void mapOptions(const std::function<void(const std::string & path)> & f, Context & ctx, Value root)
+bool optionTypeIs(Context & ctx, Value & v, const std::string & soughtType)
{
+ try {
+ const auto & typeLookup = v.attrs->find(ctx.state.sType);
+ if (typeLookup == v.attrs->end()) {
+ return false;
+ }
+ Value type = evaluateValue(ctx, *typeLookup->value);
+ if (type.type != tAttrs) {
+ return false;
+ }
+ const auto & nameLookup = type.attrs->find(ctx.state.sName);
+ if (nameLookup == type.attrs->end()) {
+ return false;
+ }
+ Value name = evaluateValue(ctx, *nameLookup->value);
+ if (name.type != tString) {
+ return false;
+ }
+ return name.string.s == soughtType;
+ } catch (Error &) {
+ return false;
+ }
+}
+
+bool isAggregateOptionType(Context & ctx, Value & v)
+{
+ return optionTypeIs(ctx, v, "attrsOf") || optionTypeIs(ctx, v, "listOf") || optionTypeIs(ctx, v, "loaOf");
+}
+
+MakeError(OptionPathError, EvalError);
+
+Value getSubOptions(Context & ctx, Value & option)
+{
+ Value getSubOptions = evaluateValue(ctx, *findAlongAttrPath(ctx.state, "type.getSubOptions", ctx.autoArgs, option));
+ if (getSubOptions.type != tLambda) {
+ throw OptionPathError("Option's type.getSubOptions isn't a function");
+ }
+ Value emptyString{};
+ nix::mkString(emptyString, "");
+ Value v;
+ ctx.state.callFunction(getSubOptions, emptyString, v, nix::Pos{});
+ return v;
+}
+
+// Carefully walk an option path, looking for sub-options when a path walks past
+// an option value.
+struct FindAlongOptionPathRet
+{
+ Value option;
+ std::string path;
+};
+FindAlongOptionPathRet findAlongOptionPath(Context & ctx, const std::string & path)
+{
+ Strings tokens = parseAttrPath(path);
+ Value v = ctx.optionsRoot;
+ std::string processedPath;
+ for (auto i = tokens.begin(); i != tokens.end(); i++) {
+ const auto & attr = *i;
+ try {
+ bool lastAttribute = std::next(i) == tokens.end();
+ v = evaluateValue(ctx, v);
+ if (attr.empty()) {
+ throw OptionPathError("empty attribute name");
+ }
+ if (isOption(ctx, v) && optionTypeIs(ctx, v, "submodule")) {
+ v = getSubOptions(ctx, v);
+ }
+ if (isOption(ctx, v) && isAggregateOptionType(ctx, v)) {
+ auto subOptions = getSubOptions(ctx, v);
+ if (lastAttribute && subOptions.attrs->empty()) {
+ break;
+ }
+ v = subOptions;
+ // Note that we've consumed attr, but didn't actually use it. This is the path component that's looked
+ // up in the list or attribute set that doesn't name an option -- the "root" in "users.users.root.name".
+ } else if (v.type != tAttrs) {
+ throw OptionPathError("Value is %s while a set was expected", showType(v));
+ } else {
+ const auto & next = v.attrs->find(ctx.state.symbols.create(attr));
+ if (next == v.attrs->end()) {
+ throw OptionPathError("Attribute not found", attr, path);
+ }
+ v = *next->value;
+ }
+ processedPath = appendPath(processedPath, attr);
+ } catch (OptionPathError & e) {
+ throw OptionPathError("At '%s' in path '%s': %s", attr, path, e.msg());
+ }
+ }
+ return {v, processedPath};
+}
+
+// Calls f on all the option names at or below the option described by `path`.
+// Note that "the option described by `path`" is not trivial -- if path describes a value inside an aggregate
+// option (such as users.users.root), the *option* described by that path is one path component shorter
+// (eg: users.users), which results in f being called on sibling-paths (eg: users.users.nixbld1). If f
+// doesn't want these, it must do its own filtering.
+void mapOptions(const std::function<void(const std::string & path)> & f, Context & ctx, const std::string & path)
+{
+ auto root = findAlongOptionPath(ctx, path);
recurse(
[f, &ctx](const std::string & path, std::variant<Value, std::exception_ptr> v) {
bool isOpt = std::holds_alternative<std::exception_ptr>(v) || isOption(ctx, std::get<Value>(v));
@@ -208,7 +306,7 @@ void mapOptions(const std::function<void(const std::string & path)> & f, Context
}
return !isOpt;
},
- ctx, root, "");
+ ctx, root.option, root.path);
}
// Calls f on all the config values inside one option.
@@ -294,9 +392,11 @@ void printAttrs(Context & ctx, Out & out, Value & v, const std::string & path)
Out attrsOut(out, "{", "}", v.attrs->size());
for (const auto & a : v.attrs->lexicographicOrder()) {
std::string name = a->name;
- attrsOut << name << " = ";
- printValue(ctx, attrsOut, *a->value, appendPath(path, name));
- attrsOut << ";" << Out::sep;
+ if (!forbiddenRecursionName(name)) {
+ attrsOut << name << " = ";
+ printValue(ctx, attrsOut, *a->value, appendPath(path, name));
+ attrsOut << ";" << Out::sep;
+ }
}
}
@@ -380,17 +480,26 @@ void printConfigValue(Context & ctx, Out & out, const std::string & path, std::v
out << ";\n";
}
-void printAll(Context & ctx, Out & out)
+// Replace with std::starts_with when C++20 is available
+bool starts_with(const std::string & s, const std::string & prefix)
+{
+ return s.size() >= prefix.size() &&
+ std::equal(s.begin(), std::next(s.begin(), prefix.size()), prefix.begin(), prefix.end());
+}
+
+void printRecursive(Context & ctx, Out & out, const std::string & path)
{
mapOptions(
- [&ctx, &out](const std::string & optionPath) {
+ [&ctx, &out, &path](const std::string & optionPath) {
mapConfigValuesInOption(
- [&ctx, &out](const std::string & configPath, std::variant<Value, std::exception_ptr> v) {
- printConfigValue(ctx, out, configPath, v);
+ [&ctx, &out, &path](const std::string & configPath, std::variant<Value, std::exception_ptr> v) {
+ if (starts_with(configPath, path)) {
+ printConfigValue(ctx, out, configPath, v);
+ }
},
optionPath, ctx);
},
- ctx, ctx.optionsRoot);
+ ctx, path);
}
void printAttr(Context & ctx, Out & out, const std::string & path, Value & root)
@@ -450,95 +559,17 @@ void printListing(Out & out, Value & v)
}
}
-bool optionTypeIs(Context & ctx, Value & v, const std::string & soughtType)
-{
- try {
- const auto & typeLookup = v.attrs->find(ctx.state.sType);
- if (typeLookup == v.attrs->end()) {
- return false;
- }
- Value type = evaluateValue(ctx, *typeLookup->value);
- if (type.type != tAttrs) {
- return false;
- }
- const auto & nameLookup = type.attrs->find(ctx.state.sName);
- if (nameLookup == type.attrs->end()) {
- return false;
- }
- Value name = evaluateValue(ctx, *nameLookup->value);
- if (name.type != tString) {
- return false;
- }
- return name.string.s == soughtType;
- } catch (Error &) {
- return false;
- }
-}
-
-bool isAggregateOptionType(Context & ctx, Value & v)
-{
- return optionTypeIs(ctx, v, "attrsOf") || optionTypeIs(ctx, v, "listOf") || optionTypeIs(ctx, v, "loaOf");
-}
-
-MakeError(OptionPathError, EvalError);
-
-Value getSubOptions(Context & ctx, Value & option)
-{
- Value getSubOptions = evaluateValue(ctx, *findAlongAttrPath(ctx.state, "type.getSubOptions", ctx.autoArgs, option));
- if (getSubOptions.type != tLambda) {
- throw OptionPathError("Option's type.getSubOptions isn't a function");
- }
- Value emptyString{};
- nix::mkString(emptyString, "");
- Value v;
- ctx.state.callFunction(getSubOptions, emptyString, v, nix::Pos{});
- return v;
-}
-
-// Carefully walk an option path, looking for sub-options when a path walks past
-// an option value.
-Value findAlongOptionPath(Context & ctx, const std::string & path)
-{
- Strings tokens = parseAttrPath(path);
- Value v = ctx.optionsRoot;
- for (auto i = tokens.begin(); i != tokens.end(); i++) {
- const auto & attr = *i;
- try {
- bool lastAttribute = std::next(i) == tokens.end();
- v = evaluateValue(ctx, v);
- if (attr.empty()) {
- throw OptionPathError("empty attribute name");
- }
- if (isOption(ctx, v) && optionTypeIs(ctx, v, "submodule")) {
- v = getSubOptions(ctx, v);
- }
- if (isOption(ctx, v) && isAggregateOptionType(ctx, v) && !lastAttribute) {
- v = getSubOptions(ctx, v);
- // Note that we've consumed attr, but didn't actually use it. This is the path component that's looked
- // up in the list or attribute set that doesn't name an option -- the "root" in "users.users.root.name".
- } else if (v.type != tAttrs) {
- throw OptionPathError("Value is %s while a set was expected", showType(v));
- } else {
- const auto & next = v.attrs->find(ctx.state.symbols.create(attr));
- if (next == v.attrs->end()) {
- throw OptionPathError("Attribute not found", attr, path);
- }
- v = *next->value;
- }
- } catch (OptionPathError & e) {
- throw OptionPathError("At '%s' in path '%s': %s", attr, path, e.msg());
- }
- }
- return v;
-}
-
void printOne(Context & ctx, Out & out, const std::string & path)
{
try {
- Value option = findAlongOptionPath(ctx, path);
+ auto result = findAlongOptionPath(ctx, path);
+ Value & option = result.option;
option = evaluateValue(ctx, option);
+ if (path != result.path) {
+ out << "Note: showing " << result.path << " instead of " << path << "\n";
+ }
if (isOption(ctx, option)) {
- printOption(ctx, out, path, option);
+ printOption(ctx, out, result.path, option);
} else {
printListing(out, option);
}
@@ -552,7 +583,7 @@ void printOne(Context & ctx, Out & out, const std::string & path)
int main(int argc, char ** argv)
{
- bool all = false;
+ bool recursive = false;
std::string path = ".";
std::string optionsExpr = "(import <nixpkgs/nixos> {}).options";
std::string configExpr = "(import <nixpkgs/nixos> {}).config";
@@ -568,8 +599,8 @@ int main(int argc, char ** argv)
nix::showManPage("nixos-option");
} else if (*arg == "--version") {
nix::printVersion("nixos-option");
- } else if (*arg == "--all") {
- all = true;
+ } else if (*arg == "-r" || *arg == "--recursive") {
+ recursive = true;
} else if (*arg == "--path") {
path = nix::getArg(*arg, arg, end);
} else if (*arg == "--options_expr") {
@@ -598,18 +629,12 @@ int main(int argc, char ** argv)
Context ctx{*state, *myArgs.getAutoArgs(*state), optionsRoot, configRoot};
Out out(std::cout);
- if (all) {
- if (!args.empty()) {
- throw UsageError("--all cannot be used with arguments");
- }
- printAll(ctx, out);
- } else {
- if (args.empty()) {
- printOne(ctx, out, "");
- }
- for (const auto & arg : args) {
- printOne(ctx, out, arg);
- }
+ auto print = recursive ? printRecursive : printOne;
+ if (args.empty()) {
+ print(ctx, out, "");
+ }
+ for (const auto & arg : args) {
+ print(ctx, out, arg);
}
ctx.state.printStats();
diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-rebuild.sh b/nixpkgs/nixos/modules/installer/tools/nixos-rebuild.sh
index 61b4af11027..354274478a3 100644
--- a/nixpkgs/nixos/modules/installer/tools/nixos-rebuild.sh
+++ b/nixpkgs/nixos/modules/installer/tools/nixos-rebuild.sh
@@ -3,6 +3,9 @@
if [ -x "@shell@" ]; then export SHELL="@shell@"; fi;
set -e
+set -o pipefail
+
+export PATH=@path@:$PATH
showSyntax() {
exec man nixos-rebuild
@@ -13,6 +16,7 @@ showSyntax() {
# Parse the command line.
origArgs=("$@")
extraBuildFlags=()
+lockFlags=()
action=
buildNix=1
fast=
@@ -58,7 +62,7 @@ while [ "$#" -gt 0 ]; do
j="$1"; shift 1
extraBuildFlags+=("$i" "$j")
;;
- --show-trace|--keep-failed|-K|--keep-going|-k|--verbose|-v|-vv|-vvv|-vvvv|-vvvvv|--fallback|--repair|--no-build-output|-Q|-j*)
+ --show-trace|--keep-failed|-K|--keep-going|-k|--verbose|-v|-vv|-vvv|-vvvv|-vvvvv|--fallback|--repair|--no-build-output|-Q|-j*|-L|--refresh|--no-net)
extraBuildFlags+=("$i")
;;
--option)
@@ -91,10 +95,24 @@ while [ "$#" -gt 0 ]; do
shift 1
;;
--use-remote-sudo)
- # note the trailing space
maybeSudo=(sudo --)
+ ;;
+ --flake)
+ flake="$1"
shift 1
;;
+ --recreate-lock-file|--no-update-lock-file|--no-write-lock-file|--no-registries|--commit-lock-file)
+ lockFlags+=("$i")
+ ;;
+ --update-input)
+ j="$1"; shift 1
+ lockFlags+=("$i" "$j")
+ ;;
+ --override-input)
+ j="$1"; shift 1
+ k="$1"; shift 1
+ lockFlags+=("$i" "$j" "$k")
+ ;;
*)
echo "$0: unknown option \`$i'"
exit 1
@@ -204,7 +222,7 @@ fi
# If ‘--upgrade’ is given, run ‘nix-channel --update nixos’.
-if [ -n "$upgrade" -a -z "$_NIXOS_REBUILD_REEXEC" ]; then
+if [[ -n $upgrade && -z $_NIXOS_REBUILD_REEXEC && -z $flake ]]; then
nix-channel --update nixos
# If there are other channels that contain a file called
@@ -227,8 +245,15 @@ if [ -z "$_NIXOS_REBUILD_REEXEC" ]; then
export PATH=@nix@/bin:$PATH
fi
+# Use /etc/nixos/flake.nix if it exists. It can be a symlink to the
+# actual flake.
+if [[ -z $flake && -e /etc/nixos/flake.nix ]]; then
+ flake="$(dirname "$(readlink -f /etc/nixos/flake.nix)")"
+fi
+
# Re-execute nixos-rebuild from the Nixpkgs tree.
-if [ -z "$_NIXOS_REBUILD_REEXEC" -a -n "$canRun" -a -z "$fast" ]; then
+# FIXME: get nixos-rebuild from $flake.
+if [[ -z $_NIXOS_REBUILD_REEXEC && -n $canRun && -z $fast && -z $flake ]]; then
if p=$(nix-build --no-out-link --expr 'with import <nixpkgs/nixos> {}; config.system.build.nixos-rebuild' "${extraBuildFlags[@]}"); then
export _NIXOS_REBUILD_REEXEC=1
exec $p/bin/nixos-rebuild "${origArgs[@]}"
@@ -236,10 +261,37 @@ if [ -z "$_NIXOS_REBUILD_REEXEC" -a -n "$canRun" -a -z "$fast" ]; then
fi
fi
+# For convenience, use the hostname as the default configuration to
+# build from the flake.
+if [[ -n $flake ]]; then
+ if [[ $flake =~ ^(.*)\#([^\#\"]*)$ ]]; then
+ flake="${BASH_REMATCH[1]}"
+ flakeAttr="${BASH_REMATCH[2]}"
+ fi
+ if [[ -z $flakeAttr ]]; then
+ read -r hostname < /proc/sys/kernel/hostname
+ if [[ -z $hostname ]]; then
+ hostname=default
+ fi
+ flakeAttr="nixosConfigurations.\"$hostname\""
+ else
+ flakeAttr="nixosConfigurations.\"$flakeAttr\""
+ fi
+fi
+
+# Resolve the flake.
+if [[ -n $flake ]]; then
+ flake=$(nix flake info --json "${extraBuildFlags[@]}" "${lockFlags[@]}" -- "$flake" | jq -r .url)
+fi
+
# Find configuration.nix and open editor instead of building.
if [ "$action" = edit ]; then
- NIXOS_CONFIG=${NIXOS_CONFIG:-$(nix-instantiate --find-file nixos-config)}
- exec "${EDITOR:-nano}" "$NIXOS_CONFIG"
+ if [[ -z $flake ]]; then
+ NIXOS_CONFIG=${NIXOS_CONFIG:-$(nix-instantiate --find-file nixos-config)}
+ exec "${EDITOR:-nano}" "$NIXOS_CONFIG"
+ else
+ exec nix edit "${lockFlags[@]}" -- "$flake#$flakeAttr"
+ fi
exit 1
fi
@@ -298,7 +350,7 @@ prebuiltNix() {
remotePATH=
-if [ -n "$buildNix" ]; then
+if [[ -n $buildNix && -z $flake ]]; then
echo "building Nix..." >&2
nixDrv=
if ! nixDrv="$(nix-instantiate '<nixpkgs/nixos>' --add-root $tmpDir/nix.drv --indirect -A config.nix.package.out "${extraBuildFlags[@]}")"; then
@@ -339,7 +391,7 @@ fi
# Update the version suffix if we're building from Git (so that
# nixos-version shows something useful).
-if [ -n "$canRun" ]; then
+if [[ -n $canRun && -z $flake ]]; then
if nixpkgs=$(nix-instantiate --find-file nixpkgs "${extraBuildFlags[@]}"); then
suffix=$($SHELL $nixpkgs/nixos/modules/installer/tools/get-version-suffix "${extraBuildFlags[@]}" || true)
if [ -n "$suffix" ]; then
@@ -360,15 +412,37 @@ fi
if [ -z "$rollback" ]; then
echo "building the system configuration..." >&2
if [ "$action" = switch -o "$action" = boot ]; then
- pathToConfig="$(nixBuild '<nixpkgs/nixos>' --no-out-link -A system "${extraBuildFlags[@]}")"
+ if [[ -z $flake ]]; then
+ pathToConfig="$(nixBuild '<nixpkgs/nixos>' --no-out-link -A system "${extraBuildFlags[@]}")"
+ else
+ outLink=$tmpDir/result
+ nix build "$flake#$flakeAttr.config.system.build.toplevel" \
+ "${extraBuildFlags[@]}" "${lockFlags[@]}" --out-link $outLink
+ pathToConfig="$(readlink -f $outLink)"
+ fi
copyToTarget "$pathToConfig"
targetHostCmd nix-env -p "$profile" --set "$pathToConfig"
elif [ "$action" = test -o "$action" = build -o "$action" = dry-build -o "$action" = dry-activate ]; then
- pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A system -k "${extraBuildFlags[@]}")"
+ if [[ -z $flake ]]; then
+ pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A system -k "${extraBuildFlags[@]}")"
+ else
+ nix build "$flake#$flakeAttr.config.system.build.toplevel" "${extraBuildFlags[@]}" "${lockFlags[@]}"
+ pathToConfig="$(readlink -f ./result)"
+ fi
elif [ "$action" = build-vm ]; then
- pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A vm -k "${extraBuildFlags[@]}")"
+ if [[ -z $flake ]]; then
+ pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A vm -k "${extraBuildFlags[@]}")"
+ else
+ echo "$0: 'build-vm' is not supported with '--flake'" >&2
+ exit 1
+ fi
elif [ "$action" = build-vm-with-bootloader ]; then
- pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A vmWithBootLoader -k "${extraBuildFlags[@]}")"
+ if [[ -z $flake ]]; then
+ pathToConfig="$(nixBuild '<nixpkgs/nixos>' -A vmWithBootLoader -k "${extraBuildFlags[@]}")"
+ else
+ echo "$0: 'build-vm-with-bootloader' is not supported with '--flake'" >&2
+ exit 1
+ fi
else
showSyntax
fi
diff --git a/nixpkgs/nixos/modules/installer/tools/nixos-version.sh b/nixpkgs/nixos/modules/installer/tools/nixos-version.sh
index 190c49a33ec..fb0fe26116a 100644
--- a/nixpkgs/nixos/modules/installer/tools/nixos-version.sh
+++ b/nixpkgs/nixos/modules/installer/tools/nixos-version.sh
@@ -6,8 +6,17 @@ case "$1" in
exit 1
;;
--hash|--revision)
+ if ! [[ @revision@ =~ ^[0-9a-f]+$ ]]; then
+ echo "$0: Nixpkgs commit hash is unknown"
+ exit 1
+ fi
echo "@revision@"
;;
+ --json)
+ cat <<EOF
+@json@
+EOF
+ ;;
*)
echo "@version@ (@codeName@)"
;;
diff --git a/nixpkgs/nixos/modules/installer/tools/tools.nix b/nixpkgs/nixos/modules/installer/tools/tools.nix
index 5df9c23e6b6..833865e99bb 100644
--- a/nixpkgs/nixos/modules/installer/tools/tools.nix
+++ b/nixpkgs/nixos/modules/installer/tools/tools.nix
@@ -31,6 +31,7 @@ let
nix = config.nix.package.out;
nix_x86_64_linux = fallback.x86_64-linux;
nix_i686_linux = fallback.i686-linux;
+ path = makeBinPath [ pkgs.jq ];
};
nixos-generate-config = makeProg {
@@ -47,6 +48,14 @@ let
name = "nixos-version";
src = ./nixos-version.sh;
inherit (config.system.nixos) version codeName revision;
+ inherit (config.system) configurationRevision;
+ json = builtins.toJSON ({
+ nixosVersion = config.system.nixos.version;
+ } // optionalAttrs (config.system.nixos.revision != null) {
+ nixpkgsRevision = config.system.nixos.revision;
+ } // optionalAttrs (config.system.configurationRevision != null) {
+ configurationRevision = config.system.configurationRevision;
+ });
};
nixos-enter = makeProg {
diff --git a/nixpkgs/nixos/modules/misc/ids.nix b/nixpkgs/nixos/modules/misc/ids.nix
index bedd87a368e..85e5534e906 100644
--- a/nixpkgs/nixos/modules/misc/ids.nix
+++ b/nixpkgs/nixos/modules/misc/ids.nix
@@ -133,7 +133,7 @@ in
tcpcryptd = 93; # tcpcryptd uses a hard-coded uid. We patch it in Nixpkgs to match this choice.
firebird = 95;
#keys = 96; # unused
- #haproxy = 97; # DynamicUser as of 2019-11-08
+ #haproxy = 97; # dynamically allocated as of 2020-03-11
mongodb = 98;
openldap = 99;
#users = 100; # unused
@@ -299,7 +299,7 @@ in
couchpotato = 267;
gogs = 268;
pdns-recursor = 269;
- kresd = 270;
+ #kresd = 270; # switched to "knot-resolver" with dynamic ID
rpc = 271;
geoip = 272;
fcron = 273;
@@ -448,7 +448,7 @@ in
#tcpcryptd = 93; # unused
firebird = 95;
keys = 96;
- #haproxy = 97; # DynamicUser as of 2019-11-08
+ #haproxy = 97; # dynamically allocated as of 2020-03-11
#mongodb = 98; # unused
openldap = 99;
munin = 102;
@@ -600,7 +600,7 @@ in
headphones = 266;
couchpotato = 267;
gogs = 268;
- kresd = 270;
+ #kresd = 270; # switched to "knot-resolver" with dynamic ID
#rpc = 271; # unused
#geoip = 272; # unused
fcron = 273;
diff --git a/nixpkgs/nixos/modules/misc/locate.nix b/nixpkgs/nixos/modules/misc/locate.nix
index 552535c253e..dc668796c78 100644
--- a/nixpkgs/nixos/modules/misc/locate.nix
+++ b/nixpkgs/nixos/modules/misc/locate.nix
@@ -131,13 +131,6 @@ in {
++ optional (isFindutils && cfg.pruneNames != []) "findutils locate does not support pruning by directory component"
++ optional (isFindutils && cfg.pruneBindMounts) "findutils locate does not support skipping bind mounts";
- # directory creation needs to be separated from main service
- # because ReadWritePaths fails when the directory doesn't already exist
- systemd.tmpfiles.rules =
- let dir = dirOf cfg.output; in
- mkIf (dir != "/var/cache")
- [ "d ${dir} 0755 root root -" ];
-
systemd.services.update-locatedb =
{ description = "Update Locate Database";
path = mkIf (!isMLocate) [ pkgs.su ];
diff --git a/nixpkgs/nixos/modules/misc/nixpkgs.nix b/nixpkgs/nixos/modules/misc/nixpkgs.nix
index afb74581e23..011d493c153 100644
--- a/nixpkgs/nixos/modules/misc/nixpkgs.nix
+++ b/nixpkgs/nixos/modules/misc/nixpkgs.nix
@@ -216,6 +216,14 @@ in
Ignored when <code>nixpkgs.pkgs</code> is set.
'';
};
+
+ initialSystem = mkOption {
+ type = types.str;
+ internal = true;
+ description = ''
+ Preserved value of <literal>system</literal> passed to <literal>eval-config.nix</literal>.
+ '';
+ };
};
config = {
diff --git a/nixpkgs/nixos/modules/misc/version.nix b/nixpkgs/nixos/modules/misc/version.nix
index 8a85035ceb7..9557def622d 100644
--- a/nixpkgs/nixos/modules/misc/version.nix
+++ b/nixpkgs/nixos/modules/misc/version.nix
@@ -4,10 +4,6 @@ with lib;
let
cfg = config.system.nixos;
-
- gitRepo = "${toString pkgs.path}/.git";
- gitRepoValid = lib.pathIsGitRepo gitRepo;
- gitCommitId = lib.substring 0 7 (commitIdFromGitRepo gitRepo);
in
{
@@ -42,8 +38,8 @@ in
nixos.revision = mkOption {
internal = true;
- type = types.str;
- default = trivial.revisionWithDefault "master";
+ type = types.nullOr types.str;
+ default = trivial.revisionWithDefault null;
description = "The Git revision from which this NixOS configuration was built.";
};
@@ -84,6 +80,12 @@ in
description = "Default NixOS channel to which the root user is subscribed.";
};
+ configurationRevision = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description = "The Git revision of the top-level flake from which this configuration was built.";
+ };
+
};
config = {
@@ -92,8 +94,6 @@ in
# These defaults are set here rather than up there so that
# changing them would not rebuild the manual
version = mkDefault (cfg.release + cfg.versionSuffix);
- revision = mkIf gitRepoValid (mkDefault gitCommitId);
- versionSuffix = mkIf gitRepoValid (mkDefault (".git." + gitCommitId));
};
# Generate /etc/os-release. See
diff --git a/nixpkgs/nixos/modules/module-list.nix b/nixpkgs/nixos/modules/module-list.nix
index 29dbc39ac7e..60aa10f03a3 100644
--- a/nixpkgs/nixos/modules/module-list.nix
+++ b/nixpkgs/nixos/modules/module-list.nix
@@ -41,7 +41,6 @@
./hardware/acpilight.nix
./hardware/all-firmware.nix
./hardware/bladeRF.nix
- ./hardware/brightnessctl.nix
./hardware/brillo.nix
./hardware/ckb-next.nix
./hardware/cpu/amd-microcode.nix
@@ -98,6 +97,7 @@
./programs/autojump.nix
./programs/bandwhich.nix
./programs/bash/bash.nix
+ ./programs/bash-my-aws.nix
./programs/bcc.nix
./programs/browserpass.nix
./programs/captive-browser.nix
@@ -200,6 +200,7 @@
./security/wrappers/default.nix
./security/sudo.nix
./security/systemd-confinement.nix
+ ./security/tpm2.nix
./services/admin/oxidized.nix
./services/admin/salt/master.nix
./services/admin/salt/minion.nix
@@ -228,6 +229,8 @@
./services/backup/restic.nix
./services/backup/restic-rest-server.nix
./services/backup/rsnapshot.nix
+ ./services/backup/sanoid.nix
+ ./services/backup/syncoid.nix
./services/backup/tarsnap.nix
./services/backup/tsm.nix
./services/backup/zfs-replication.nix
@@ -245,12 +248,13 @@
./services/cluster/kubernetes/proxy.nix
./services/cluster/kubernetes/scheduler.nix
./services/computing/boinc/client.nix
- ./services/computing/torque/server.nix
- ./services/computing/torque/mom.nix
+ ./services/computing/foldingathome/client.nix
./services/computing/slurm/slurm.nix
+ ./services/computing/torque/mom.nix
+ ./services/computing/torque/server.nix
./services/continuous-integration/buildbot/master.nix
./services/continuous-integration/buildbot/worker.nix
- ./services/continuous-integration/buildkite-agent.nix
+ ./services/continuous-integration/buildkite-agents.nix
./services/continuous-integration/hail.nix
./services/continuous-integration/hydra/default.nix
./services/continuous-integration/gitlab-runner.nix
@@ -295,6 +299,7 @@
./services/desktops/geoclue2.nix
./services/desktops/gsignond.nix
./services/desktops/gvfs.nix
+ ./services/desktops/malcontent.nix
./services/desktops/pipewire.nix
./services/desktops/gnome3/at-spi2-core.nix
./services/desktops/gnome3/chrome-gnome-shell.nix
@@ -400,8 +405,10 @@
./services/mail/rspamd.nix
./services/mail/rss2email.nix
./services/mail/roundcube.nix
+ ./services/mail/sympa.nix
./services/mail/nullmailer.nix
./services/misc/airsonic.nix
+ ./services/misc/ankisyncd.nix
./services/misc/apache-kafka.nix
./services/misc/autofs.nix
./services/misc/autorandr.nix
@@ -427,7 +434,6 @@
./services/misc/ethminer.nix
./services/misc/exhibitor.nix
./services/misc/felix.nix
- ./services/misc/folding-at-home.nix
./services/misc/freeswitch.nix
./services/misc/fstrim.nix
./services/misc/gammu-smsd.nix
@@ -529,6 +535,7 @@
./services/monitoring/prometheus/alertmanager.nix
./services/monitoring/prometheus/exporters.nix
./services/monitoring/prometheus/pushgateway.nix
+ ./services/monitoring/prometheus/xmpp-alerts.nix
./services/monitoring/riemann.nix
./services/monitoring/riemann-dash.nix
./services/monitoring/riemann-tools.nix
@@ -590,7 +597,7 @@
./services/networking/dhcpd.nix
./services/networking/dnscache.nix
./services/networking/dnschain.nix
- ./services/networking/dnscrypt-proxy.nix
+ ./services/networking/dnscrypt-proxy2.nix
./services/networking/dnscrypt-wrapper.nix
./services/networking/dnsdist.nix
./services/networking/dnsmasq.nix
@@ -657,6 +664,7 @@
./services/networking/ngircd.nix
./services/networking/nghttpx/default.nix
./services/networking/nix-serve.nix
+ ./services/networking/nix-store-gcs-proxy.nix
./services/networking/nixops-dns.nix
./services/networking/nntp-proxy.nix
./services/networking/nsd.nix
@@ -703,6 +711,7 @@
./services/networking/shorewall6.nix
./services/networking/shout.nix
./services/networking/sniproxy.nix
+ ./services/networking/smartdns.nix
./services/networking/smokeping.nix
./services/networking/softether.nix
./services/networking/spacecookie.nix
@@ -720,6 +729,7 @@
./services/networking/syncthing.nix
./services/networking/syncthing-relay.nix
./services/networking/syncplay.nix
+ ./services/networking/tailscale.nix
./services/networking/tcpcrypt.nix
./services/networking/teamspeak3.nix
./services/networking/tedicross.nix
@@ -804,6 +814,7 @@
./services/ttys/agetty.nix
./services/ttys/gpm.nix
./services/ttys/kmscon.nix
+ ./services/wayland/cage.nix
./services/web-apps/atlassian/confluence.nix
./services/web-apps/atlassian/crowd.nix
./services/web-apps/atlassian/jira.nix
@@ -813,9 +824,11 @@
./services/web-apps/dokuwiki.nix
./services/web-apps/frab.nix
./services/web-apps/gotify-server.nix
+ ./services/web-apps/grocy.nix
./services/web-apps/icingaweb2/icingaweb2.nix
./services/web-apps/icingaweb2/module-monitoring.nix
./services/web-apps/ihatemoney
+ ./services/web-apps/jirafeau.nix
./services/web-apps/limesurvey.nix
./services/web-apps/mattermost.nix
./services/web-apps/mediawiki.nix
diff --git a/nixpkgs/nixos/modules/programs/bash-my-aws.nix b/nixpkgs/nixos/modules/programs/bash-my-aws.nix
new file mode 100644
index 00000000000..15e429a7549
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/bash-my-aws.nix
@@ -0,0 +1,25 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+ prg = config.programs;
+ cfg = prg.bash-my-aws;
+
+ initScript = ''
+ eval $(${pkgs.bash-my-aws}/bin/bma-init)
+ '';
+in
+ {
+ options = {
+ programs.bash-my-aws = {
+ enable = mkEnableOption "bash-my-aws";
+ };
+ };
+
+ config = mkIf cfg.enable {
+ environment.systemPackages = with pkgs; [ bash-my-aws ];
+
+ programs.bash.interactiveShellInit = initScript;
+ };
+ }
diff --git a/nixpkgs/nixos/modules/programs/bash/bash.nix b/nixpkgs/nixos/modules/programs/bash/bash.nix
index 366c07c0a35..be964ce7f3f 100644
--- a/nixpkgs/nixos/modules/programs/bash/bash.nix
+++ b/nixpkgs/nixos/modules/programs/bash/bash.nix
@@ -32,6 +32,10 @@ let
fi
'';
+ lsColors = optionalString cfg.enableLsColors ''
+ eval "$(${pkgs.coreutils}/bin/dircolors -b)"
+ '';
+
bashAliases = concatStringsSep "\n" (
mapAttrsFlatten (k: v: "alias ${k}=${escapeShellArg v}")
(filterAttrs (k: v: v != null) cfg.shellAliases)
@@ -127,6 +131,14 @@ in
type = types.bool;
};
+ enableLsColors = mkOption {
+ default = true;
+ description = ''
+ Enable extra colors in directory listings.
+ '';
+ type = types.bool;
+ };
+
};
};
@@ -156,6 +168,7 @@ in
${cfg.promptInit}
${bashCompletion}
+ ${lsColors}
${bashAliases}
${cfge.interactiveShellInit}
diff --git a/nixpkgs/nixos/modules/programs/firejail.nix b/nixpkgs/nixos/modules/programs/firejail.nix
index 74c3e4425a7..484f9eb4440 100644
--- a/nixpkgs/nixos/modules/programs/firejail.nix
+++ b/nixpkgs/nixos/modules/programs/firejail.nix
@@ -5,28 +5,34 @@ with lib;
let
cfg = config.programs.firejail;
- wrappedBins = pkgs.stdenv.mkDerivation {
- name = "firejail-wrapped-binaries";
- nativeBuildInputs = with pkgs; [ makeWrapper ];
- buildCommand = ''
+ wrappedBins = pkgs.runCommand "firejail-wrapped-binaries"
+ { preferLocalBuild = true;
+ allowSubstitutes = false;
+ }
+ ''
mkdir -p $out/bin
${lib.concatStringsSep "\n" (lib.mapAttrsToList (command: binary: ''
- cat <<_EOF >$out/bin/${command}
- #!${pkgs.stdenv.shell} -e
- /run/wrappers/bin/firejail ${binary} "\$@"
- _EOF
- chmod 0755 $out/bin/${command}
+ cat <<_EOF >$out/bin/${command}
+ #! ${pkgs.runtimeShell} -e
+ exec /run/wrappers/bin/firejail ${binary} "\$@"
+ _EOF
+ chmod 0755 $out/bin/${command}
'') cfg.wrappedBinaries)}
'';
- };
in {
options.programs.firejail = {
enable = mkEnableOption "firejail";
wrappedBinaries = mkOption {
- type = types.attrs;
+ type = types.attrsOf types.path;
default = {};
+ example = literalExample ''
+ {
+ firefox = "''${lib.getBin pkgs.firefox}/bin/firefox";
+ mpv = "''${lib.getBin pkgs.mpv}/bin/mpv";
+ }
+ '';
description = ''
Wrap the binaries in firejail and place them in the global path.
</para>
@@ -41,7 +47,7 @@ in {
config = mkIf cfg.enable {
security.wrappers.firejail.source = "${lib.getBin pkgs.firejail}/bin/firejail";
- environment.systemPackages = [ wrappedBins ];
+ environment.systemPackages = [ pkgs.firejail ] ++ [ wrappedBins ];
};
meta.maintainers = with maintainers; [ peterhoeg ];
diff --git a/nixpkgs/nixos/modules/programs/fish_completion-generator.patch b/nixpkgs/nixos/modules/programs/fish_completion-generator.patch
index a8c797d185a..997f38c5066 100644
--- a/nixpkgs/nixos/modules/programs/fish_completion-generator.patch
+++ b/nixpkgs/nixos/modules/programs/fish_completion-generator.patch
@@ -1,11 +1,13 @@
--- a/create_manpage_completions.py
+++ b/create_manpage_completions.py
-@@ -776,8 +776,6 @@ def parse_manpage_at_path(manpage_path, output_directory):
-
+@@ -844,10 +844,6 @@ def parse_manpage_at_path(manpage_path, output_directory):
+
built_command_output.insert(0, "# " + CMDNAME)
-
+
- # Output the magic word Autogenerated so we can tell if we can overwrite this
-- built_command_output.insert(1, "# Autogenerated from man page " + manpage_path)
+- built_command_output.insert(
+- 1, "# Autogenerated from man page " + manpage_path
+- )
# built_command_output.insert(2, "# using " + parser.__class__.__name__) # XXX MISATTRIBUTES THE CULPABILE PARSER! Was really using Type2 but reporting TypeDeroffManParser
-
+
for line in built_command_output:
diff --git a/nixpkgs/nixos/modules/programs/sway.nix b/nixpkgs/nixos/modules/programs/sway.nix
index 7e646f8737d..364debddb0f 100644
--- a/nixpkgs/nixos/modules/programs/sway.nix
+++ b/nixpkgs/nixos/modules/programs/sway.nix
@@ -88,10 +88,10 @@ in {
default = with pkgs; [
swaylock swayidle
xwayland alacritty dmenu
- rxvt_unicode # For backward compatibility (old default terminal)
+ rxvt-unicode # For backward compatibility (old default terminal)
];
defaultText = literalExample ''
- with pkgs; [ swaylock swayidle xwayland rxvt_unicode dmenu ];
+ with pkgs; [ swaylock swayidle xwayland rxvt-unicode dmenu ];
'';
example = literalExample ''
with pkgs; [
diff --git a/nixpkgs/nixos/modules/programs/tmux.nix b/nixpkgs/nixos/modules/programs/tmux.nix
index ed077e3daa7..c39908751d2 100644
--- a/nixpkgs/nixos/modules/programs/tmux.nix
+++ b/nixpkgs/nixos/modules/programs/tmux.nix
@@ -52,7 +52,7 @@ let
set -s escape-time ${toString cfg.escapeTime}
set -g history-limit ${toString cfg.historyLimit}
- ${cfg.extraTmuxConf}
+ ${cfg.extraConfig}
'';
in {
@@ -102,7 +102,7 @@ in {
description = "Time in milliseconds for which tmux waits after an escape is input.";
};
- extraTmuxConf = mkOption {
+ extraConfig = mkOption {
default = "";
description = ''
Additional contents of /etc/tmux.conf
@@ -181,4 +181,8 @@ in {
};
};
};
+
+ imports = [
+ (lib.mkRenamedOptionModule [ "programs" "tmux" "extraTmuxConf" ] [ "programs" "tmux" "extraConfig" ])
+ ];
}
diff --git a/nixpkgs/nixos/modules/programs/zsh/zsh.nix b/nixpkgs/nixos/modules/programs/zsh/zsh.nix
index c66c29ed45f..930cc1987a3 100644
--- a/nixpkgs/nixos/modules/programs/zsh/zsh.nix
+++ b/nixpkgs/nixos/modules/programs/zsh/zsh.nix
@@ -15,6 +15,24 @@ let
(filterAttrs (k: v: v != null) cfg.shellAliases)
);
+ zshStartupNotes = ''
+ # Note that generated /etc/zprofile and /etc/zshrc files do a lot of
+ # non-standard setup to make zsh usable with no configuration by default.
+ #
+ # Which means that unless you explicitly meticulously override everything
+ # generated, interactions between your ~/.zshrc and these files are likely
+ # to be rather surprising.
+ #
+ # Note however, that you can disable loading of the generated /etc/zprofile
+ # and /etc/zshrc (you can't disable loading of /etc/zshenv, but it is
+ # designed to not set anything surprising) by setting `no_global_rcs` option
+ # in ~/.zshenv:
+ #
+ # echo setopt no_global_rcs >> ~/.zshenv
+ #
+ # See "STARTUP/SHUTDOWN FILES" section of zsh(1) for more info.
+ '';
+
in
{
@@ -69,6 +87,10 @@ in
promptInit = mkOption {
default = ''
+ # Note that to manually override this in ~/.zshrc you should run `prompt off`
+ # before setting your PS1 and etc. Otherwise this will likely to interact with
+ # your ~/.zshrc configuration in unexpected ways as the default prompt sets
+ # a lot of different prompt variables.
autoload -U promptinit && promptinit && prompt walters && setopt prompt_sp
'';
description = ''
@@ -100,7 +122,8 @@ in
];
example = [ "EXTENDED_HISTORY" "RM_STAR_WAIT" ];
description = ''
- Configure zsh options.
+ Configure zsh options. See
+ <citerefentry><refentrytitle>zshoptions</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
'';
};
@@ -139,14 +162,21 @@ in
# This file is read for all shells.
# Only execute this file once per shell.
- # But don't clobber the environment of interactive non-login children!
if [ -n "$__ETC_ZSHENV_SOURCED" ]; then return; fi
- export __ETC_ZSHENV_SOURCED=1
+ __ETC_ZSHENV_SOURCED=1
if [ -z "$__NIXOS_SET_ENVIRONMENT_DONE" ]; then
. ${config.system.build.setEnvironment}
fi
+ HELPDIR="${pkgs.zsh}/share/zsh/$ZSH_VERSION/help"
+
+ # Tell zsh how to find installed completions.
+ for p in ''${(z)NIX_PROFILES}; do
+ fpath+=($p/share/zsh/site-functions $p/share/zsh/$ZSH_VERSION/functions $p/share/zsh/vendor-completions)
+ done
+
+ # Setup custom shell init stuff.
${cfge.shellInit}
${cfg.shellInit}
@@ -161,11 +191,14 @@ in
''
# /etc/zprofile: DO NOT EDIT -- this file has been generated automatically.
# This file is read for login shells.
+ #
+ ${zshStartupNotes}
# Only execute this file once per shell.
if [ -n "$__ETC_ZPROFILE_SOURCED" ]; then return; fi
__ETC_ZPROFILE_SOURCED=1
+ # Setup custom login shell init stuff.
${cfge.loginShellInit}
${cfg.loginShellInit}
@@ -180,38 +213,44 @@ in
''
# /etc/zshrc: DO NOT EDIT -- this file has been generated automatically.
# This file is read for interactive shells.
+ #
+ ${zshStartupNotes}
# Only execute this file once per shell.
if [ -n "$__ETC_ZSHRC_SOURCED" -o -n "$NOSYSZSHRC" ]; then return; fi
__ETC_ZSHRC_SOURCED=1
- . /etc/zinputrc
+ ${optionalString (cfg.setOptions != []) ''
+ # Set zsh options.
+ setopt ${concatStringsSep " " cfg.setOptions}
+ ''}
- # Don't export these, otherwise other shells (bash) will try to use same histfile
+ # Setup command line history.
+ # Don't export these, otherwise other shells (bash) will try to use same HISTFILE.
SAVEHIST=${toString cfg.histSize}
HISTSIZE=${toString cfg.histSize}
HISTFILE=${cfg.histFile}
- HELPDIR="${pkgs.zsh}/share/zsh/$ZSH_VERSION/help"
-
- # Tell zsh how to find installed completions
- for p in ''${(z)NIX_PROFILES}; do
- fpath+=($p/share/zsh/site-functions $p/share/zsh/$ZSH_VERSION/functions $p/share/zsh/vendor-completions)
- done
+ # Configure sane keyboard defaults.
+ . /etc/zinputrc
- ${optionalString cfg.enableGlobalCompInit "autoload -U compinit && compinit"}
+ ${optionalString cfg.enableGlobalCompInit ''
+ # Enable autocompletion.
+ autoload -U compinit && compinit
+ ''}
+ # Setup custom interactive shell init stuff.
${cfge.interactiveShellInit}
${cfg.interactiveShellInit}
- ${optionalString (cfg.setOptions != []) "setopt ${concatStringsSep " " cfg.setOptions}"}
-
+ # Setup aliases.
${zshAliases}
+ # Setup prompt.
${cfg.promptInit}
- # Need to disable features to support TRAMP
+ # Disable some features to support TRAMP.
if [ "$TERM" = dumb ]; then
unsetopt zle prompt_cr prompt_subst
unset RPS1 RPROMPT
diff --git a/nixpkgs/nixos/modules/rename.nix b/nixpkgs/nixos/modules/rename.nix
index dbe687d8e22..410db8fd84e 100644
--- a/nixpkgs/nixos/modules/rename.nix
+++ b/nixpkgs/nixos/modules/rename.nix
@@ -21,12 +21,12 @@ with lib;
(mkRemovedOptionModule [ "services" "firefox" "syncserver" "group" ] "")
(mkRemovedOptionModule [ "services" "winstone" ] "The corresponding package was removed from nixpkgs.")
(mkRemovedOptionModule [ "networking" "vpnc" ] "Use environment.etc.\"vpnc/service.conf\" instead.")
- (mkRemovedOptionModule [ "environment.blcr.enable" ] "The BLCR module has been removed")
- (mkRemovedOptionModule [ "services.beegfsEnable" ] "The BeeGFS module has been removed")
- (mkRemovedOptionModule [ "services.beegfs" ] "The BeeGFS module has been removed")
- (mkRemovedOptionModule [ "services.osquery" ] "The osquery module has been removed")
- (mkRemovedOptionModule [ "services.fourStore" ] "The fourStore module has been removed")
- (mkRemovedOptionModule [ "services.fourStoreEndpoint" ] "The fourStoreEndpoint module has been removed")
+ (mkRemovedOptionModule [ "environment" "blcr" "enable" ] "The BLCR module has been removed")
+ (mkRemovedOptionModule [ "services" "beegfsEnable" ] "The BeeGFS module has been removed")
+ (mkRemovedOptionModule [ "services" "beegfs" ] "The BeeGFS module has been removed")
+ (mkRemovedOptionModule [ "services" "osquery" ] "The osquery module has been removed")
+ (mkRemovedOptionModule [ "services" "fourStore" ] "The fourStore module has been removed")
+ (mkRemovedOptionModule [ "services" "fourStoreEndpoint" ] "The fourStoreEndpoint module has been removed")
(mkRemovedOptionModule [ "programs" "way-cooler" ] ("way-cooler is abandoned by its author: " +
"https://way-cooler.org/blog/2020/01/09/way-cooler-post-mortem.html"))
(mkRemovedOptionModule [ "services" "xserver" "multitouch" ] ''
@@ -41,6 +41,13 @@ with lib;
LightDM. Please use the services.xserver.displayManager.lightdm.autoLogin options
instead, or any other display manager in NixOS as they all support auto-login.
'')
+ (mkRemovedOptionModule [ "services" "dnscrypt-proxy" ] "Use services.dnscrypt-proxy2 instead")
+ (mkRemovedOptionModule ["hardware" "brightnessctl" ] ''
+ The brightnessctl module was removed because newer versions of
+ brightnessctl don't require the udev rules anymore (they can use the
+ systemd-logind API). Instead of using the module you can now
+ simply add the brightnessctl package to environment.systemPackages.
+ '')
# Do NOT add any option renames here, see top of the file
];
diff --git a/nixpkgs/nixos/modules/security/acme.nix b/nixpkgs/nixos/modules/security/acme.nix
index 890c421b0ea..b787a767539 100644
--- a/nixpkgs/nixos/modules/security/acme.nix
+++ b/nixpkgs/nixos/modules/security/acme.nix
@@ -1,7 +1,5 @@
{ config, lib, pkgs, ... }:
-
with lib;
-
let
cfg = config.security.acme;
@@ -9,7 +7,8 @@ let
certOpts = { name, ... }: {
options = {
webroot = mkOption {
- type = types.str;
+ type = types.nullOr types.str;
+ default = null;
example = "/var/lib/acme/acme-challenges";
description = ''
Where the webroot of the HTTP vhost is located.
@@ -38,7 +37,7 @@ let
email = mkOption {
type = types.nullOr types.str;
- default = null;
+ default = cfg.email;
description = "Contact email address for the CA to be able to reach you.";
};
@@ -76,20 +75,6 @@ let
'';
};
- plugins = mkOption {
- type = types.listOf (types.enum [
- "cert.der" "cert.pem" "chain.pem" "external.sh"
- "fullchain.pem" "full.pem" "key.der" "key.pem" "account_key.json" "account_reg.json"
- ]);
- default = [ "fullchain.pem" "full.pem" "key.pem" "account_key.json" "account_reg.json" ];
- description = ''
- Plugins to enable. With default settings simp_le will
- store public certificate bundle in <filename>fullchain.pem</filename>,
- private key in <filename>key.pem</filename> and those two previous
- files combined in <filename>full.pem</filename> in its state directory.
- '';
- };
-
directory = mkOption {
type = types.str;
readOnly = true;
@@ -111,6 +96,67 @@ let
own server roots if needed.
'';
};
+
+ keyType = mkOption {
+ type = types.str;
+ default = "ec384";
+ description = ''
+ Key type to use for private keys.
+ For an up to date list of supported values check the --key-type option
+ at https://go-acme.github.io/lego/usage/cli/#usage.
+ '';
+ };
+
+ dnsProvider = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "route53";
+ description = ''
+ DNS Challenge provider. For a list of supported providers, see the "code"
+ field of the DNS providers listed at https://go-acme.github.io/lego/dns/.
+ '';
+ };
+
+ credentialsFile = mkOption {
+ type = types.path;
+ description = ''
+ Path to an EnvironmentFile for the cert's service containing any required and
+ optional environment variables for your selected dnsProvider.
+ To find out what values you need to set, consult the documentation at
+ https://go-acme.github.io/lego/dns/ for the corresponding dnsProvider.
+ '';
+ example = "/var/src/secrets/example.org-route53-api-token";
+ };
+
+ dnsPropagationCheck = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Toggles lego DNS propagation check, which is used alongside DNS-01
+ challenge to ensure the DNS entries required are available.
+ '';
+ };
+
+ ocspMustStaple = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Turns on the OCSP Must-Staple TLS extension.
+ Make sure you know what you're doing! See:
+ <itemizedlist>
+ <listitem><para><link xlink:href="https://blog.apnic.net/2019/01/15/is-the-web-ready-for-ocsp-must-staple/" /></para></listitem>
+ <listitem><para><link xlink:href="https://blog.hboeck.de/archives/886-The-Problem-with-OCSP-Stapling-and-Must-Staple-and-why-Certificate-Revocation-is-still-broken.html" /></para></listitem>
+ </itemizedlist>
+ '';
+ };
+
+ extraLegoRenewFlags = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ description = ''
+ Additional flags to pass to lego renew.
+ '';
+ };
};
};
@@ -130,19 +176,26 @@ in
(mkRemovedOptionModule [ "security" "acme" "directory"] "ACME Directory is now hardcoded to /var/lib/acme and its permisisons are managed by systemd. See https://github.com/NixOS/nixpkgs/issues/53852 for more info.")
(mkRemovedOptionModule [ "security" "acme" "preDelay"] "This option has been removed. If you want to make sure that something executes before certificates are provisioned, add a RequiredBy=acme-\${cert}.service to the service you want to execute before the cert renewal")
(mkRemovedOptionModule [ "security" "acme" "activationDelay"] "This option has been removed. If you want to make sure that something executes before certificates are provisioned, add a RequiredBy=acme-\${cert}.service to the service you want to execute before the cert renewal")
+ (mkChangedOptionModule [ "security" "acme" "validMin"] [ "security" "acme" "validMinDays"] (config: config.security.acme.validMin / (24 * 3600)))
];
options = {
security.acme = {
- validMin = mkOption {
+ validMinDays = mkOption {
type = types.int;
- default = 30 * 24 * 3600;
- description = "Minimum remaining validity before renewal in seconds.";
+ default = 30;
+ description = "Minimum remaining validity before renewal in days.";
+ };
+
+ email = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description = "Contact email address for the CA to be able to reach you.";
};
renewInterval = mkOption {
type = types.str;
- default = "weekly";
+ default = "daily";
description = ''
Systemd calendar expression when to check for renewal. See
<citerefentry><refentrytitle>systemd.time</refentrytitle>
@@ -173,6 +226,15 @@ in
'';
};
+ acceptTerms = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Accept the CA's terms of service. The default provier is Let's Encrypt,
+ you can find their ToS at https://letsencrypt.org/repository/
+ '';
+ };
+
certs = mkOption {
default = { };
type = with types; attrsOf (submodule certOpts);
@@ -204,27 +266,59 @@ in
config = mkMerge [
(mkIf (cfg.certs != { }) {
+ assertions = let
+ certs = (mapAttrsToList (k: v: v) cfg.certs);
+ in [
+ {
+ assertion = all (certOpts: certOpts.dnsProvider == null || certOpts.webroot == null) certs;
+ message = ''
+ Options `security.acme.certs.<name>.dnsProvider` and
+ `security.acme.certs.<name>.webroot` are mutually exclusive.
+ '';
+ }
+ {
+ assertion = cfg.email != null || all (certOpts: certOpts.email != null) certs;
+ message = ''
+ You must define `security.acme.certs.<name>.email` or
+ `security.acme.email` to register with the CA.
+ '';
+ }
+ {
+ assertion = cfg.acceptTerms;
+ message = ''
+ You must accept the CA's terms of service before using
+ the ACME module by setting `security.acme.acceptTerms`
+ to `true`. For Let's Encrypt's ToS see https://letsencrypt.org/repository/
+ '';
+ }
+ ];
+
systemd.services = let
services = concatLists servicesLists;
servicesLists = mapAttrsToList certToServices cfg.certs;
certToServices = cert: data:
let
+ # StateDirectory must be relative, and will be created under /var/lib by systemd
lpath = "acme/${cert}";
- rights = if data.allowKeysForGroup then "750" else "700";
- cmdline = [ "-v" "-d" data.domain "--default_root" data.webroot "--valid_min" cfg.validMin ]
- ++ optionals (data.email != null) [ "--email" data.email ]
- ++ concatMap (p: [ "-f" p ]) data.plugins
- ++ concatLists (mapAttrsToList (name: root: [ "-d" (if root == null then name else "${name}:${root}")]) data.extraDomains)
+ apath = "/var/lib/${lpath}";
+ spath = "/var/lib/acme/.lego";
+ fileMode = if data.allowKeysForGroup then "640" else "600";
+ globalOpts = [ "-d" data.domain "--email" data.email "--path" "." "--key-type" data.keyType ]
+ ++ optionals (cfg.acceptTerms) [ "--accept-tos" ]
+ ++ optionals (data.dnsProvider != null && !data.dnsPropagationCheck) [ "--dns.disable-cp" ]
+ ++ concatLists (mapAttrsToList (name: root: [ "-d" name ]) data.extraDomains)
+ ++ (if data.dnsProvider != null then [ "--dns" data.dnsProvider ] else [ "--http" "--http.webroot" data.webroot ])
++ optionals (cfg.server != null || data.server != null) ["--server" (if data.server == null then cfg.server else data.server)];
+ certOpts = optionals data.ocspMustStaple [ "--must-staple" ];
+ runOpts = escapeShellArgs (globalOpts ++ [ "run" ] ++ certOpts);
+ renewOpts = escapeShellArgs (globalOpts ++
+ [ "renew" "--days" (toString cfg.validMinDays) ] ++
+ certOpts ++ data.extraLegoRenewFlags);
acmeService = {
description = "Renew ACME Certificate for ${cert}";
after = [ "network.target" "network-online.target" ];
wants = [ "network-online.target" ];
- # simp_le uses requests, which uses certifi under the hood,
- # which doesn't respect the system trust store.
- # At least in the acme test, we provision a fake CA, impersonating the LE endpoint.
- # REQUESTS_CA_BUNDLE is a way to teach python requests to use something else
- environment.REQUESTS_CA_BUNDLE = "/etc/ssl/certs/ca-certificates.crt";
+ wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
# With RemainAfterExit the service is considered active even
@@ -233,18 +327,38 @@ in
# the permissions of the StateDirectory get adjusted
# according to the specified group
RemainAfterExit = true;
- SuccessExitStatus = [ "0" "1" ];
User = data.user;
Group = data.group;
PrivateTmp = true;
- StateDirectory = lpath;
- StateDirectoryMode = rights;
- WorkingDirectory = "/var/lib/${lpath}";
- ExecStart = "${pkgs.simp_le}/bin/simp_le ${escapeShellArgs cmdline}";
+ StateDirectory = "acme/.lego ${lpath}";
+ StateDirectoryMode = if data.allowKeysForGroup then "750" else "700";
+ WorkingDirectory = spath;
+ # Only try loading the credentialsFile if the dns challenge is enabled
+ EnvironmentFile = if data.dnsProvider != null then data.credentialsFile else null;
+ ExecStart = pkgs.writeScript "acme-start" ''
+ #!${pkgs.runtimeShell} -e
+ ${pkgs.lego}/bin/lego ${renewOpts} || ${pkgs.lego}/bin/lego ${runOpts}
+ '';
ExecStartPost =
let
+ keyName = builtins.replaceStrings ["*"] ["_"] data.domain;
script = pkgs.writeScript "acme-post-start" ''
#!${pkgs.runtimeShell} -e
+ cd ${apath}
+
+ # Test that existing cert is older than new cert
+ KEY=${spath}/certificates/${keyName}.key
+ if [ -e $KEY -a $KEY -nt key.pem ]; then
+ cp -p ${spath}/certificates/${keyName}.key key.pem
+ cp -p ${spath}/certificates/${keyName}.crt fullchain.pem
+ cp -p ${spath}/certificates/${keyName}.issuer.crt chain.pem
+ ln -sf fullchain.pem cert.pem
+ cat key.pem fullchain.pem > full.pem
+ fi
+
+ chmod ${fileMode} *.pem
+ chown '${data.user}:${data.group}' *.pem
+
${data.postRun}
'';
in
@@ -276,17 +390,17 @@ in
-out $workdir/server.crt
# Copy key to destination
- cp $workdir/server.key /var/lib/${lpath}/key.pem
+ cp $workdir/server.key ${apath}/key.pem
# Create fullchain.pem (same format as "simp_le ... -f fullchain.pem" creates)
- cat $workdir/{server.crt,ca.crt} > "/var/lib/${lpath}/fullchain.pem"
+ cat $workdir/{server.crt,ca.crt} > "${apath}/fullchain.pem"
# Create full.pem for e.g. lighttpd
- cat $workdir/{server.key,server.crt,ca.crt} > "/var/lib/${lpath}/full.pem"
+ cat $workdir/{server.key,server.crt,ca.crt} > "${apath}/full.pem"
# Give key acme permissions
- chown '${data.user}:${data.group}' "/var/lib/${lpath}/"{key,fullchain,full}.pem
- chmod ${rights} "/var/lib/${lpath}/"{key,fullchain,full}.pem
+ chown '${data.user}:${data.group}' "${apath}/"{key,fullchain,full}.pem
+ chmod ${fileMode} "${apath}/"{key,fullchain,full}.pem
'';
serviceConfig = {
Type = "oneshot";
@@ -297,7 +411,7 @@ in
};
unitConfig = {
# Do not create self-signed key when key already exists
- ConditionPathExists = "!/var/lib/${lpath}/key.pem";
+ ConditionPathExists = "!${apath}/key.pem";
};
};
in (
@@ -309,10 +423,19 @@ in
servicesAttr;
systemd.tmpfiles.rules =
- flip mapAttrsToList cfg.certs
- (cert: data: "d ${data.webroot}/.well-known/acme-challenge - ${data.user} ${data.group}");
-
- systemd.timers = flip mapAttrs' cfg.certs (cert: data: nameValuePair
+ map (data: "d ${data.webroot}/.well-known/acme-challenge - ${data.user} ${data.group}") (filter (data: data.webroot != null) (attrValues cfg.certs));
+
+ systemd.timers = let
+ # Allow systemd to pick a convenient time within the day
+ # to run the check.
+ # This allows the coalescing of multiple timer jobs.
+ # We divide by the number of certificates so that if you
+ # have many certificates, the renewals are distributed over
+ # the course of the day to avoid rate limits.
+ numCerts = length (attrNames cfg.certs);
+ _24hSecs = 60 * 60 * 24;
+ AccuracySec = "${toString (_24hSecs / numCerts)}s";
+ in flip mapAttrs' cfg.certs (cert: data: nameValuePair
("acme-${cert}")
({
description = "Renew ACME Certificate for ${cert}";
@@ -321,8 +444,9 @@ in
OnCalendar = cfg.renewInterval;
Unit = "acme-${cert}.service";
Persistent = "yes";
- AccuracySec = "5m";
- RandomizedDelaySec = "1h";
+ inherit AccuracySec;
+ # Skew randomly within the day, per https://letsencrypt.org/docs/integration-guide/.
+ RandomizedDelaySec = "24h";
};
})
);
@@ -334,7 +458,7 @@ in
];
meta = {
- maintainers = with lib.maintainers; [ abbradar fpletz globin ];
+ maintainers = with lib.maintainers; [ abbradar fpletz globin m1cr0man ];
doc = ./acme.xml;
};
}
diff --git a/nixpkgs/nixos/modules/security/acme.xml b/nixpkgs/nixos/modules/security/acme.xml
index 9d0a1995e0f..2b29c117484 100644
--- a/nixpkgs/nixos/modules/security/acme.xml
+++ b/nixpkgs/nixos/modules/security/acme.xml
@@ -7,7 +7,7 @@
<para>
NixOS supports automatic domain validation &amp; certificate retrieval and
renewal using the ACME protocol. This is currently only implemented by and
- for Let's Encrypt. The alternative ACME client <literal>simp_le</literal> is
+ for Let's Encrypt. The alternative ACME client <literal>lego</literal> is
used under the hood.
</para>
<section xml:id="module-security-acme-prerequisites">
diff --git a/nixpkgs/nixos/modules/security/duosec.nix b/nixpkgs/nixos/modules/security/duosec.nix
index 78a82b7154e..c686a6861d0 100644
--- a/nixpkgs/nixos/modules/security/duosec.nix
+++ b/nixpkgs/nixos/modules/security/duosec.nix
@@ -12,7 +12,7 @@ let
ikey=${cfg.ikey}
skey=${cfg.skey}
host=${cfg.host}
- ${optionalString (cfg.group != "") ("group="+cfg.group)}
+ ${optionalString (cfg.groups != "") ("groups="+cfg.groups)}
failmode=${cfg.failmode}
pushinfo=${boolToStr cfg.pushinfo}
autopush=${boolToStr cfg.autopush}
@@ -42,6 +42,10 @@ let
};
in
{
+ imports = [
+ (mkRenamedOptionModule [ "security" "duosec" "group" ] [ "security" "duosec" "groups" ])
+ ];
+
options = {
security.duosec = {
ssh.enable = mkOption {
@@ -71,10 +75,16 @@ in
description = "Duo API hostname.";
};
- group = mkOption {
+ groups = mkOption {
type = types.str;
default = "";
- description = "Use Duo authentication for users only in this group.";
+ example = "users,!wheel,!*admin guests";
+ description = ''
+ If specified, Duo authentication is required only for users
+ whose primary group or supplementary group list matches one
+ of the space-separated pattern lists. Refer to
+ <link xlink:href="https://duo.com/docs/duounix"/> for details.
+ '';
};
failmode = mkOption {
diff --git a/nixpkgs/nixos/modules/security/google_oslogin.nix b/nixpkgs/nixos/modules/security/google_oslogin.nix
index 246419b681a..6f9962e1d62 100644
--- a/nixpkgs/nixos/modules/security/google_oslogin.nix
+++ b/nixpkgs/nixos/modules/security/google_oslogin.nix
@@ -59,10 +59,8 @@ in
exec ${package}/bin/google_authorized_keys "$@"
'';
};
- services.openssh.extraConfig = ''
- AuthorizedKeysCommand /etc/ssh/authorized_keys_command_google_oslogin %u
- AuthorizedKeysCommandUser nobody
- '';
+ services.openssh.authorizedKeysCommand = "/etc/ssh/authorized_keys_command_google_oslogin %u";
+ services.openssh.authorizedKeysCommandUser = "nobody";
};
}
diff --git a/nixpkgs/nixos/modules/security/rngd.nix b/nixpkgs/nixos/modules/security/rngd.nix
index d9d6d9c9f25..cffa1a5849f 100644
--- a/nixpkgs/nixos/modules/security/rngd.nix
+++ b/nixpkgs/nixos/modules/security/rngd.nix
@@ -37,14 +37,24 @@ in
after = [ "dev-random.device" ];
+ # Clean shutdown without DefaultDependencies
+ conflicts = [ "shutdown.target" ];
+ before = [
+ "sysinit.target"
+ "shutdown.target"
+ ];
+
description = "Hardware RNG Entropy Gatherer Daemon";
+ # rngd may have to start early to avoid entropy starvation during boot with encrypted swap
+ unitConfig.DefaultDependencies = false;
serviceConfig = {
ExecStart = "${pkgs.rng-tools}/sbin/rngd -f"
+ optionalString cfg.debug " -d";
+ # PrivateTmp would introduce a circular dependency if /tmp is on tmpfs and swap is encrypted,
+ # thus depending on rngd before swap, while swap depends on rngd to avoid entropy starvation.
NoNewPrivileges = true;
PrivateNetwork = true;
- PrivateTmp = true;
ProtectSystem = "full";
ProtectHome = true;
};
diff --git a/nixpkgs/nixos/modules/security/sudo.nix b/nixpkgs/nixos/modules/security/sudo.nix
index d899806ef05..e3e43177def 100644
--- a/nixpkgs/nixos/modules/security/sudo.nix
+++ b/nixpkgs/nixos/modules/security/sudo.nix
@@ -71,23 +71,25 @@ in
this is the case when configuration options are merged.
'';
default = [];
- example = [
- # Allow execution of any command by all users in group sudo,
- # requiring a password.
- { groups = [ "sudo" ]; commands = [ "ALL" ]; }
-
- # Allow execution of "/home/root/secret.sh" by user `backup`, `database`
- # and the group with GID `1006` without a password.
- { users = [ "backup" "database" ]; groups = [ 1006 ];
- commands = [ { command = "/home/root/secret.sh"; options = [ "SETENV" "NOPASSWD" ]; } ]; }
-
- # Allow all users of group `bar` to run two executables as user `foo`
- # with arguments being pre-set.
- { groups = [ "bar" ]; runAs = "foo";
- commands =
- [ "/home/baz/cmd1.sh hello-sudo"
- { command = ''/home/baz/cmd2.sh ""''; options = [ "SETENV" ]; } ]; }
- ];
+ example = literalExample ''
+ [
+ # Allow execution of any command by all users in group sudo,
+ # requiring a password.
+ { groups = [ "sudo" ]; commands = [ "ALL" ]; }
+
+ # Allow execution of "/home/root/secret.sh" by user `backup`, `database`
+ # and the group with GID `1006` without a password.
+ { users = [ "backup" "database" ]; groups = [ 1006 ];
+ commands = [ { command = "/home/root/secret.sh"; options = [ "SETENV" "NOPASSWD" ]; } ]; }
+
+ # Allow all users of group `bar` to run two executables as user `foo`
+ # with arguments being pre-set.
+ { groups = [ "bar" ]; runAs = "foo";
+ commands =
+ [ "/home/baz/cmd1.sh hello-sudo"
+ { command = '''/home/baz/cmd2.sh ""'''; options = [ "SETENV" ]; } ]; }
+ ]
+ '';
type = with types; listOf (submodule {
options = {
users = mkOption {
diff --git a/nixpkgs/nixos/modules/security/tpm2.nix b/nixpkgs/nixos/modules/security/tpm2.nix
new file mode 100644
index 00000000000..13804fb82cb
--- /dev/null
+++ b/nixpkgs/nixos/modules/security/tpm2.nix
@@ -0,0 +1,185 @@
+{ lib, pkgs, config, ... }:
+let
+ cfg = config.security.tpm2;
+
+ # This snippet is taken from tpm2-tss/dist/tpm-udev.rules, but modified to allow custom user/groups
+ # The idea is that the tssUser is allowed to acess the TPM and kernel TPM resource manager, while
+ # the tssGroup is only allowed to access the kernel resource manager
+ # Therefore, if either of the two are null, the respective part isn't generated
+ udevRules = tssUser: tssGroup: ''
+ ${lib.optionalString (tssUser != null) ''KERNEL=="tpm[0-9]*", MODE="0660", OWNER="${tssUser}"''}
+ ${lib.optionalString (tssUser != null || tssGroup != null)
+ ''KERNEL=="tpmrm[0-9]*", MODE="0660"''
+ + lib.optionalString (tssUser != null) '', OWNER="${tssUser}"''
+ + lib.optionalString (tssGroup != null) '', GROUP="${tssGroup}"''
+ }
+ '';
+
+in {
+ options.security.tpm2 = {
+ enable = lib.mkEnableOption "Trusted Platform Module 2 support";
+
+ tssUser = lib.mkOption {
+ description = ''
+ Name of the tpm device-owner and service user, set if applyUdevRules is
+ set.
+ '';
+ type = lib.types.nullOr lib.types.str;
+ default = if cfg.abrmd.enable then "tss" else "root";
+ defaultText = ''"tss" when using the userspace resource manager,'' +
+ ''"root" otherwise'';
+ };
+
+ tssGroup = lib.mkOption {
+ description = ''
+ Group of the tpm kernel resource manager (tpmrm) device-group, set if
+ applyUdevRules is set.
+ '';
+ type = lib.types.nullOr lib.types.str;
+ default = "tss";
+ };
+
+ applyUdevRules = lib.mkOption {
+ description = ''
+ Whether to make the /dev/tpm[0-9] devices accessible by the tssUser, or
+ the /dev/tpmrm[0-9] by tssGroup respectively
+ '';
+ type = lib.types.bool;
+ default = true;
+ };
+
+ abrmd = {
+ enable = lib.mkEnableOption ''
+ Trusted Platform 2 userspace resource manager daemon
+ '';
+
+ package = lib.mkOption {
+ description = "tpm2-abrmd package to use";
+ type = lib.types.package;
+ default = pkgs.tpm2-abrmd;
+ defaultText = "pkgs.tpm2-abrmd";
+ };
+ };
+
+ pkcs11 = {
+ enable = lib.mkEnableOption ''
+ TPM2 PKCS#11 tool and shared library in system path
+ (<literal>/run/current-system/sw/lib/libtpm2_pkcs11.so</literal>)
+ '';
+
+ package = lib.mkOption {
+ description = "tpm2-pkcs11 package to use";
+ type = lib.types.package;
+ default = pkgs.tpm2-pkcs11;
+ defaultText = "pkgs.tpm2-pkcs11";
+ };
+ };
+
+ tctiEnvironment = {
+ enable = lib.mkOption {
+ description = ''
+ Set common TCTI environment variables to the specified value.
+ The variables are
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>TPM2TOOLS_TCTI</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>TPM2_PKCS11_TCTI</literal>
+ </para>
+ </listitem>
+ </itemizedlist>
+ '';
+ type = lib.types.bool;
+ default = false;
+ };
+
+ interface = lib.mkOption {
+ description = ''
+ The name of the TPM command transmission interface (TCTI) library to
+ use.
+ '';
+ type = lib.types.enum [ "tabrmd" "device" ];
+ default = "device";
+ };
+
+ deviceConf = lib.mkOption {
+ description = ''
+ Configuration part of the device TCTI, e.g. the path to the TPM device.
+ Applies if interface is set to "device".
+ The format is specified in the
+ <link xlink:href="https://github.com/tpm2-software/tpm2-tools/blob/master/man/common/tcti.md#tcti-options">
+ tpm2-tools repository</link>.
+ '';
+ type = lib.types.str;
+ default = "/dev/tpmrm0";
+ };
+
+ tabrmdConf = lib.mkOption {
+ description = ''
+ Configuration part of the tabrmd TCTI, like the D-Bus bus name.
+ Applies if interface is set to "tabrmd".
+ The format is specified in the
+ <link xlink:href="https://github.com/tpm2-software/tpm2-tools/blob/master/man/common/tcti.md#tcti-options">
+ tpm2-tools repository</link>.
+ '';
+ type = lib.types.str;
+ default = "bus_name=com.intel.tss2.Tabrmd";
+ };
+ };
+ };
+
+ config = lib.mkIf cfg.enable (lib.mkMerge [
+ {
+ # PKCS11 tools and library
+ environment.systemPackages = lib.mkIf cfg.pkcs11.enable [
+ (lib.getBin cfg.pkcs11.package)
+ (lib.getLib cfg.pkcs11.package)
+ ];
+
+ services.udev.extraRules = lib.mkIf cfg.applyUdevRules
+ (udevRules cfg.tssUser cfg.tssGroup);
+
+ # Create the tss user and group only if the default value is used
+ users.users.${cfg.tssUser} = lib.mkIf (cfg.tssUser == "tss") {
+ isSystemUser = true;
+ };
+ users.groups.${cfg.tssGroup} = lib.mkIf (cfg.tssGroup == "tss") {};
+
+ environment.variables = lib.mkIf cfg.tctiEnvironment.enable (
+ lib.attrsets.genAttrs [
+ "TPM2TOOLS_TCTI"
+ "TPM2_PKCS11_TCTI"
+ ] (_: ''${cfg.tctiEnvironment.interface}:${
+ if cfg.tctiEnvironment.interface == "tabrmd" then
+ cfg.tctiEnvironment.tabrmdConf
+ else
+ cfg.tctiEnvironment.deviceConf
+ }'')
+ );
+ }
+
+ (lib.mkIf cfg.abrmd.enable {
+ systemd.services."tpm2-abrmd" = {
+ wantedBy = [ "multi-user.target" ];
+ serviceConfig = {
+ Type = "dbus";
+ Restart = "always";
+ RestartSec = 30;
+ BusName = "com.intel.tss2.Tabrmd";
+ StandardOutput = "syslog";
+ ExecStart = "${cfg.abrmd.package}/bin/tpm2-abrmd";
+ User = "tss";
+ Group = "nogroup";
+ };
+ };
+
+ services.dbus.packages = lib.singleton cfg.abrmd.package;
+ })
+ ]);
+
+ meta.maintainers = with lib.maintainers; [ lschuermann ];
+}
diff --git a/nixpkgs/nixos/modules/services/audio/alsa.nix b/nixpkgs/nixos/modules/services/audio/alsa.nix
index 990398e6546..3fe76a16540 100644
--- a/nixpkgs/nixos/modules/services/audio/alsa.nix
+++ b/nixpkgs/nixos/modules/services/audio/alsa.nix
@@ -91,11 +91,7 @@ in
environment.systemPackages = [ alsaUtils ];
environment.etc = mkIf (!pulseaudioEnabled && config.sound.extraConfig != "")
- [
- { source = pkgs.writeText "asound.conf" config.sound.extraConfig;
- target = "asound.conf";
- }
- ];
+ { "asound.conf".text = config.sound.extraConfig; };
# ALSA provides a udev rule for restoring volume settings.
services.udev.packages = [ alsaUtils ];
diff --git a/nixpkgs/nixos/modules/services/audio/mopidy.nix b/nixpkgs/nixos/modules/services/audio/mopidy.nix
index a534b692f17..d30c227db42 100644
--- a/nixpkgs/nixos/modules/services/audio/mopidy.nix
+++ b/nixpkgs/nixos/modules/services/audio/mopidy.nix
@@ -13,11 +13,11 @@ let
mopidyEnv = buildEnv {
name = "mopidy-with-extensions-${mopidy.version}";
paths = closePropagation cfg.extensionPackages;
- pathsToLink = [ "/${python.sitePackages}" ];
+ pathsToLink = [ "/${python3.sitePackages}" ];
buildInputs = [ makeWrapper ];
postBuild = ''
makeWrapper ${mopidy}/bin/mopidy $out/bin/mopidy \
- --prefix PYTHONPATH : $out/${python.sitePackages}
+ --prefix PYTHONPATH : $out/${python3.sitePackages}
'';
};
in {
diff --git a/nixpkgs/nixos/modules/services/backup/restic.nix b/nixpkgs/nixos/modules/services/backup/restic.nix
index 7e8e91e4b9c..2388f1d6ca1 100644
--- a/nixpkgs/nixos/modules/services/backup/restic.nix
+++ b/nixpkgs/nixos/modules/services/backup/restic.nix
@@ -103,6 +103,34 @@ in
Create the repository if it doesn't exist.
'';
};
+
+ pruneOpts = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ description = ''
+ A list of options (--keep-* et al.) for 'restic forget
+ --prune', to automatically prune old snapshots. The
+ 'forget' command is run *after* the 'backup' command, so
+ keep that in mind when constructing the --keep-* options.
+ '';
+ example = [
+ "--keep-daily 7"
+ "--keep-weekly 5"
+ "--keep-monthly 12"
+ "--keep-yearly 75"
+ ];
+ };
+
+ dynamicFilesFrom = mkOption {
+ type = with types; nullOr str;
+ default = null;
+ description = ''
+ A script that produces a list of files to back up. The
+ results of this command are given to the '--files-from'
+ option.
+ '';
+ example = "find /home/matt/git -type d -name .git";
+ };
};
}));
default = {};
@@ -134,25 +162,41 @@ in
let
extraOptions = concatMapStrings (arg: " -o ${arg}") backup.extraOptions;
resticCmd = "${pkgs.restic}/bin/restic${extraOptions}";
+ filesFromTmpFile = "/run/restic-backups-${name}/includes";
+ backupPaths = if (backup.dynamicFilesFrom == null)
+ then concatStringsSep " " backup.paths
+ else "--files-from ${filesFromTmpFile}";
+ pruneCmd = optionals (builtins.length backup.pruneOpts > 0) [
+ ( resticCmd + " forget --prune " + (concatStringsSep " " backup.pruneOpts) )
+ ( resticCmd + " check" )
+ ];
in nameValuePair "restic-backups-${name}" ({
environment = {
RESTIC_PASSWORD_FILE = backup.passwordFile;
RESTIC_REPOSITORY = backup.repository;
};
- path = with pkgs; [
- openssh
- ];
+ path = [ pkgs.openssh ];
restartIfChanged = false;
serviceConfig = {
Type = "oneshot";
- ExecStart = "${resticCmd} backup ${concatStringsSep " " backup.extraBackupArgs} ${concatStringsSep " " backup.paths}";
+ ExecStart = [ "${resticCmd} backup ${concatStringsSep " " backup.extraBackupArgs} ${backupPaths}" ] ++ pruneCmd;
User = backup.user;
+ RuntimeDirectory = "restic-backups-${name}";
} // optionalAttrs (backup.s3CredentialsFile != null) {
EnvironmentFile = backup.s3CredentialsFile;
};
- } // optionalAttrs backup.initialize {
+ } // optionalAttrs (backup.initialize || backup.dynamicFilesFrom != null) {
preStart = ''
- ${resticCmd} snapshots || ${resticCmd} init
+ ${optionalString (backup.initialize) ''
+ ${resticCmd} snapshots || ${resticCmd} init
+ ''}
+ ${optionalString (backup.dynamicFilesFrom != null) ''
+ ${pkgs.writeScript "dynamicFilesFromScript" backup.dynamicFilesFrom} > ${filesFromTmpFile}
+ ''}
+ '';
+ } // optionalAttrs (backup.dynamicFilesFrom != null) {
+ postStart = ''
+ rm ${filesFromTmpFile}
'';
})
) config.services.restic.backups;
diff --git a/nixpkgs/nixos/modules/services/backup/sanoid.nix b/nixpkgs/nixos/modules/services/backup/sanoid.nix
new file mode 100644
index 00000000000..0472fb4ba1e
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/backup/sanoid.nix
@@ -0,0 +1,213 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.sanoid;
+
+ datasetSettingsType = with types;
+ (attrsOf (nullOr (oneOf [ str int bool (listOf str) ]))) // {
+ description = "dataset/template options";
+ };
+
+ # Default values from https://github.com/jimsalterjrs/sanoid/blob/master/sanoid.defaults.conf
+
+ commonOptions = {
+ hourly = mkOption {
+ description = "Number of hourly snapshots.";
+ type = types.ints.unsigned;
+ default = 48;
+ };
+
+ daily = mkOption {
+ description = "Number of daily snapshots.";
+ type = types.ints.unsigned;
+ default = 90;
+ };
+
+ monthly = mkOption {
+ description = "Number of monthly snapshots.";
+ type = types.ints.unsigned;
+ default = 6;
+ };
+
+ yearly = mkOption {
+ description = "Number of yearly snapshots.";
+ type = types.ints.unsigned;
+ default = 0;
+ };
+
+ autoprune = mkOption {
+ description = "Whether to automatically prune old snapshots.";
+ type = types.bool;
+ default = true;
+ };
+
+ autosnap = mkOption {
+ description = "Whether to automatically take snapshots.";
+ type = types.bool;
+ default = true;
+ };
+
+ settings = mkOption {
+ description = ''
+ Free-form settings for this template/dataset. See
+ <link xlink:href="https://github.com/jimsalterjrs/sanoid/blob/master/sanoid.defaults.conf"/>
+ for allowed values.
+ '';
+ type = datasetSettingsType;
+ };
+ };
+
+ commonConfig = config: {
+ settings = {
+ hourly = mkDefault config.hourly;
+ daily = mkDefault config.daily;
+ monthly = mkDefault config.monthly;
+ yearly = mkDefault config.yearly;
+ autoprune = mkDefault config.autoprune;
+ autosnap = mkDefault config.autosnap;
+ };
+ };
+
+ datasetOptions = {
+ useTemplate = mkOption {
+ description = "Names of the templates to use for this dataset.";
+ type = (types.listOf (types.enum (attrNames cfg.templates))) // {
+ description = "list of template names";
+ };
+ default = [];
+ };
+
+ recursive = mkOption {
+ description = "Whether to recursively snapshot dataset children.";
+ type = types.bool;
+ default = false;
+ };
+
+ processChildrenOnly = mkOption {
+ description = "Whether to only snapshot child datasets if recursing.";
+ type = types.bool;
+ default = false;
+ };
+ };
+
+ datasetConfig = config: {
+ settings = {
+ use_template = mkDefault config.useTemplate;
+ recursive = mkDefault config.recursive;
+ process_children_only = mkDefault config.processChildrenOnly;
+ };
+ };
+
+ # Extract pool names from configured datasets
+ pools = unique (map (d: head (builtins.match "([^/]+).*" d)) (attrNames cfg.datasets));
+
+ configFile = let
+ mkValueString = v:
+ if builtins.isList v then concatStringsSep "," v
+ else generators.mkValueStringDefault {} v;
+
+ mkKeyValue = k: v: if v == null then ""
+ else generators.mkKeyValueDefault { inherit mkValueString; } "=" k v;
+ in generators.toINI { inherit mkKeyValue; } cfg.settings;
+
+ configDir = pkgs.writeTextDir "sanoid.conf" configFile;
+
+in {
+
+ # Interface
+
+ options.services.sanoid = {
+ enable = mkEnableOption "Sanoid ZFS snapshotting service";
+
+ interval = mkOption {
+ type = types.str;
+ default = "hourly";
+ example = "daily";
+ description = ''
+ Run sanoid at this interval. The default is to run hourly.
+
+ The format is described in
+ <citerefentry><refentrytitle>systemd.time</refentrytitle>
+ <manvolnum>7</manvolnum></citerefentry>.
+ '';
+ };
+
+ datasets = mkOption {
+ type = types.attrsOf (types.submodule ({ config, ... }: {
+ options = commonOptions // datasetOptions;
+ config = mkMerge [ (commonConfig config) (datasetConfig config) ];
+ }));
+ default = {};
+ description = "Datasets to snapshot.";
+ };
+
+ templates = mkOption {
+ type = types.attrsOf (types.submodule ({ config, ... }: {
+ options = commonOptions;
+ config = commonConfig config;
+ }));
+ default = {};
+ description = "Templates for datasets.";
+ };
+
+ settings = mkOption {
+ type = types.attrsOf datasetSettingsType;
+ description = ''
+ Free-form settings written directly to the config file. See
+ <link xlink:href="https://github.com/jimsalterjrs/sanoid/blob/master/sanoid.defaults.conf"/>
+ for allowed values.
+ '';
+ };
+
+ extraArgs = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ example = [ "--verbose" "--readonly" "--debug" ];
+ description = ''
+ Extra arguments to pass to sanoid. See
+ <link xlink:href="https://github.com/jimsalterjrs/sanoid/#sanoid-command-line-options"/>
+ for allowed options.
+ '';
+ };
+ };
+
+ # Implementation
+
+ config = mkIf cfg.enable {
+ services.sanoid.settings = mkMerge [
+ (mapAttrs' (d: v: nameValuePair ("template_" + d) v.settings) cfg.templates)
+ (mapAttrs (d: v: v.settings) cfg.datasets)
+ ];
+
+ systemd.services.sanoid = {
+ description = "Sanoid snapshot service";
+ serviceConfig = {
+ ExecStartPre = map (pool: lib.escapeShellArgs [
+ "+/run/booted-system/sw/bin/zfs" "allow"
+ "sanoid" "snapshot,mount,destroy" pool
+ ]) pools;
+ ExecStart = lib.escapeShellArgs ([
+ "${pkgs.sanoid}/bin/sanoid"
+ "--cron"
+ "--configdir" configDir
+ ] ++ cfg.extraArgs);
+ ExecStopPost = map (pool: lib.escapeShellArgs [
+ "+/run/booted-system/sw/bin/zfs" "unallow" "sanoid" pool
+ ]) pools;
+ User = "sanoid";
+ Group = "sanoid";
+ DynamicUser = true;
+ RuntimeDirectory = "sanoid";
+ CacheDirectory = "sanoid";
+ };
+ # Prevents missing snapshots during DST changes
+ environment.TZ = "UTC";
+ after = [ "zfs.target" ];
+ startAt = cfg.interval;
+ };
+ };
+
+ meta.maintainers = with maintainers; [ lopsided98 ];
+ }
diff --git a/nixpkgs/nixos/modules/services/backup/syncoid.nix b/nixpkgs/nixos/modules/services/backup/syncoid.nix
new file mode 100644
index 00000000000..53787a0182a
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/backup/syncoid.nix
@@ -0,0 +1,168 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.syncoid;
+in {
+
+ # Interface
+
+ options.services.syncoid = {
+ enable = mkEnableOption "Syncoid ZFS synchronization service";
+
+ interval = mkOption {
+ type = types.str;
+ default = "hourly";
+ example = "*-*-* *:15:00";
+ description = ''
+ Run syncoid at this interval. The default is to run hourly.
+
+ The format is described in
+ <citerefentry><refentrytitle>systemd.time</refentrytitle>
+ <manvolnum>7</manvolnum></citerefentry>.
+ '';
+ };
+
+ user = mkOption {
+ type = types.str;
+ default = "root";
+ example = "backup";
+ description = ''
+ The user for the service. Sudo or ZFS privilege delegation must be
+ configured to use a user other than root.
+ '';
+ };
+
+ sshKey = mkOption {
+ type = types.nullOr types.path;
+ # Prevent key from being copied to store
+ apply = mapNullable toString;
+ default = null;
+ description = ''
+ SSH private key file to use to login to the remote system. Can be
+ overridden in individual commands.
+ '';
+ };
+
+ commonArgs = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ example = [ "--no-sync-snap" ];
+ description = ''
+ Arguments to add to every syncoid command, unless disabled for that
+ command. See
+ <link xlink:href="https://github.com/jimsalterjrs/sanoid/#syncoid-command-line-options"/>
+ for available options.
+ '';
+ };
+
+ commands = mkOption {
+ type = types.attrsOf (types.submodule ({ name, ... }: {
+ options = {
+ source = mkOption {
+ type = types.str;
+ example = "pool/dataset";
+ description = ''
+ Source ZFS dataset. Can be either local or remote. Defaults to
+ the attribute name.
+ '';
+ };
+
+ target = mkOption {
+ type = types.str;
+ example = "user@server:pool/dataset";
+ description = ''
+ Target ZFS dataset. Can be either local
+ (<replaceable>pool/dataset</replaceable>) or remote
+ (<replaceable>user@server:pool/dataset</replaceable>).
+ '';
+ };
+
+ recursive = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to also transfer child datasets.
+ '';
+ };
+
+ sshKey = mkOption {
+ type = types.nullOr types.path;
+ # Prevent key from being copied to store
+ apply = mapNullable toString;
+ description = ''
+ SSH private key file to use to login to the remote system.
+ Defaults to <option>services.syncoid.sshKey</option> option.
+ '';
+ };
+
+ sendOptions = mkOption {
+ type = types.separatedString " ";
+ default = "";
+ example = "Lc e";
+ description = ''
+ Advanced options to pass to zfs send. Options are specified
+ without their leading dashes and separated by spaces.
+ '';
+ };
+
+ recvOptions = mkOption {
+ type = types.separatedString " ";
+ default = "";
+ example = "ux recordsize o compression=lz4";
+ description = ''
+ Advanced options to pass to zfs recv. Options are specified
+ without their leading dashes and separated by spaces.
+ '';
+ };
+
+ useCommonArgs = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether to add the configured common arguments to this command.
+ '';
+ };
+
+ extraArgs = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ example = [ "--sshport 2222" ];
+ description = "Extra syncoid arguments for this command.";
+ };
+ };
+ config = {
+ source = mkDefault name;
+ sshKey = mkDefault cfg.sshKey;
+ };
+ }));
+ default = {};
+ example."pool/test".target = "root@target:pool/test";
+ description = "Syncoid commands to run.";
+ };
+ };
+
+ # Implementation
+
+ config = mkIf cfg.enable {
+ systemd.services.syncoid = {
+ description = "Syncoid ZFS synchronization service";
+ script = concatMapStringsSep "\n" (c: lib.escapeShellArgs
+ ([ "${pkgs.sanoid}/bin/syncoid" ]
+ ++ (optionals c.useCommonArgs cfg.commonArgs)
+ ++ (optional c.recursive "-r")
+ ++ (optionals (c.sshKey != null) [ "--sshkey" c.sshKey ])
+ ++ c.extraArgs
+ ++ [ "--sendoptions" c.sendOptions
+ "--recvoptions" c.recvOptions
+ c.source c.target
+ ])) (attrValues cfg.commands);
+ after = [ "zfs.target" ];
+ serviceConfig.User = cfg.user;
+ startAt = cfg.interval;
+ };
+ };
+
+ meta.maintainers = with maintainers; [ lopsided98 ];
+ }
diff --git a/nixpkgs/nixos/modules/services/computing/foldingathome/client.nix b/nixpkgs/nixos/modules/services/computing/foldingathome/client.nix
new file mode 100644
index 00000000000..9f99af48c48
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/computing/foldingathome/client.nix
@@ -0,0 +1,81 @@
+{ config, lib, pkgs, ... }:
+with lib;
+let
+ cfg = config.services.foldingathome;
+
+ args =
+ ["--team" "${toString cfg.team}"]
+ ++ lib.optionals (cfg.user != null) ["--user" cfg.user]
+ ++ cfg.extraArgs
+ ;
+in
+{
+ imports = [
+ (mkRenamedOptionModule [ "services" "foldingAtHome" ] [ "services" "foldingathome" ])
+ (mkRenamedOptionModule [ "services" "foldingathome" "nickname" ] [ "services" "foldingathome" "user" ])
+ (mkRemovedOptionModule [ "services" "foldingathome" "config" ] ''
+ Use <literal>services.foldingathome.extraArgs instead<literal>
+ '')
+ ];
+ options.services.foldingathome = {
+ enable = mkEnableOption "Enable the Folding@home client";
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.fahclient;
+ defaultText = "pkgs.fahclient";
+ description = ''
+ Which Folding@home client to use.
+ '';
+ };
+
+ user = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description = ''
+ The user associated with the reported computation results. This will
+ be used in the ranking statistics.
+ '';
+ };
+
+ team = mkOption {
+ type = types.int;
+ default = 236565;
+ description = ''
+ The team ID associated with the reported computation results. This
+ will be used in the ranking statistics.
+
+ By default, use the NixOS folding@home team ID is being used.
+ '';
+ };
+
+ extraArgs = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ description = ''
+ Extra startup options for the FAHClient. Run
+ <literal>FAHClient --help</literal> to find all the available options.
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ systemd.services.foldingathome = {
+ description = "Folding@home client";
+ after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ script = ''
+ exec ${cfg.package}/bin/FAHClient ${lib.escapeShellArgs args}
+ '';
+ serviceConfig = {
+ DynamicUser = true;
+ StateDirectory = "foldingathome";
+ WorkingDirectory = "%S/foldingathome";
+ };
+ };
+ };
+
+ meta = {
+ maintainers = with lib.maintainers; [ zimbatm ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/computing/slurm/slurm.nix b/nixpkgs/nixos/modules/services/computing/slurm/slurm.nix
index c70d999ca96..050872e933f 100644
--- a/nixpkgs/nixos/modules/services/computing/slurm/slurm.nix
+++ b/nixpkgs/nixos/modules/services/computing/slurm/slurm.nix
@@ -355,6 +355,7 @@ in
ExecStart = "${wrappedSlurm}/bin/slurmd";
PIDFile = "/run/slurmd.pid";
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+ LimitMEMLOCK = "infinity";
};
preStart = ''
diff --git a/nixpkgs/nixos/modules/services/continuous-integration/buildkite-agent.nix b/nixpkgs/nixos/modules/services/continuous-integration/buildkite-agents.nix
index 58bce654941..c17d89c387a 100644
--- a/nixpkgs/nixos/modules/services/continuous-integration/buildkite-agent.nix
+++ b/nixpkgs/nixos/modules/services/continuous-integration/buildkite-agents.nix
@@ -3,7 +3,7 @@
with lib;
let
- cfg = config.services.buildkite-agent;
+ cfg = config.services.buildkite-agents;
mkHookOption = { name, description, example ? null }: {
inherit name;
@@ -15,7 +15,7 @@ let
};
mkHookOptions = hooks: listToAttrs (map mkHookOption hooks);
- hooksDir = let
+ hooksDir = cfg: let
mkHookEntry = name: value: ''
cat > $out/${name} <<'EOF'
#! ${pkgs.runtimeShell}
@@ -29,12 +29,13 @@ let
${concatStringsSep "\n" (mapAttrsToList mkHookEntry (filterAttrs (n: v: v != null) cfg.hooks))}
'';
-in
-
-{
- options = {
- services.buildkite-agent = {
- enable = mkEnableOption "buildkite-agent";
+ buildkiteOptions = { name ? "", config, ... }: {
+ options = {
+ enable = mkOption {
+ default = true;
+ type = types.bool;
+ description = "Whether to enable this buildkite agent";
+ };
package = mkOption {
default = pkgs.buildkite-agent;
@@ -44,7 +45,7 @@ in
};
dataDir = mkOption {
- default = "/var/lib/buildkite-agent";
+ default = "/var/lib/buildkite-agent-${name}";
description = "The workdir for the agent";
type = types.str;
};
@@ -68,9 +69,9 @@ in
name = mkOption {
type = types.str;
- default = "%hostname-%n";
+ default = "%hostname-${name}-%n";
description = ''
- The name of the agent.
+ The name of the agent as seen in the buildkite dashboard.
'';
};
@@ -166,11 +167,11 @@ in
hooksPath = mkOption {
type = types.path;
- default = hooksDir;
- defaultText = "generated from services.buildkite-agent.hooks";
+ default = hooksDir config;
+ defaultText = "generated from services.buildkite-agents.<name>.hooks";
description = ''
Path to the directory storing the hooks.
- Consider using <option>services.buildkite-agent.hooks.&lt;name&gt;</option>
+ Consider using <option>services.buildkite-agents.&lt;name&gt;.hooks.&lt;name&gt;</option>
instead.
'';
};
@@ -184,24 +185,38 @@ in
};
};
};
+ enabledAgents = lib.filterAttrs (n: v: v.enable) cfg;
+ mapAgents = function: lib.mkMerge (lib.mapAttrsToList function enabledAgents);
+in
+{
+ options.services.buildkite-agents = mkOption {
+ type = types.attrsOf (types.submodule buildkiteOptions);
+ default = {};
+ description = ''
+ Attribute set of buildkite agents.
+ The attribute key is combined with the hostname and a unique integer to
+ create the final agent name. This can be overridden by setting the `name`
+ attribute.
+ '';
+ };
- config = mkIf config.services.buildkite-agent.enable {
- users.users.buildkite-agent = {
- name = "buildkite-agent";
+ config.users.users = mapAgents (name: cfg: {
+ "buildkite-agent-${name}" = {
+ name = "buildkite-agent-${name}";
home = cfg.dataDir;
createHome = true;
description = "Buildkite agent user";
extraGroups = [ "keys" ];
isSystemUser = true;
};
+ });
- environment.systemPackages = [ cfg.package ];
-
- systemd.services.buildkite-agent =
+ config.systemd.services = mapAgents (name: cfg: {
+ "buildkite-agent-${name}" =
{ description = "Buildkite Agent";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
- path = cfg.runtimePackages ++ [ pkgs.coreutils ];
+ path = cfg.runtimePackages ++ [ cfg.package pkgs.coreutils ];
environment = config.networking.proxy.envVars // {
HOME = cfg.dataDir;
NIX_REMOTE = "daemon";
@@ -230,8 +245,8 @@ in
'';
serviceConfig =
- { ExecStart = "${cfg.package}/bin/buildkite-agent start --config /var/lib/buildkite-agent/buildkite-agent.cfg";
- User = "buildkite-agent";
+ { ExecStart = "${cfg.package}/bin/buildkite-agent start --config ${cfg.dataDir}/buildkite-agent.cfg";
+ User = "buildkite-agent-${name}";
RestartSec = 5;
Restart = "on-failure";
TimeoutSec = 10;
@@ -240,22 +255,18 @@ in
KillMode = "mixed";
};
};
+ });
- assertions = [
- { assertion = cfg.hooksPath == hooksDir || all (v: v == null) (attrValues cfg.hooks);
+ config.assertions = mapAgents (name: cfg: [
+ { assertion = cfg.hooksPath == (hooksDir cfg) || all (v: v == null) (attrValues cfg.hooks);
message = ''
- Options `services.buildkite-agent.hooksPath' and
- `services.buildkite-agent.hooks.<name>' are mutually exclusive.
+ Options `services.buildkite-agents.${name}.hooksPath' and
+ `services.buildkite-agents.${name}.hooks.<name>' are mutually exclusive.
'';
}
- ];
- };
+ ]);
+
imports = [
- (mkRenamedOptionModule [ "services" "buildkite-agent" "token" ] [ "services" "buildkite-agent" "tokenPath" ])
- (mkRenamedOptionModule [ "services" "buildkite-agent" "openssh" "privateKey" ] [ "services" "buildkite-agent" "privateSshKeyPath" ])
- (mkRenamedOptionModule [ "services" "buildkite-agent" "openssh" "privateKeyPath" ] [ "services" "buildkite-agent" "privateSshKeyPath" ])
- (mkRemovedOptionModule [ "services" "buildkite-agent" "openssh" "publicKey" ] "SSH public keys aren't necessary to clone private repos.")
- (mkRemovedOptionModule [ "services" "buildkite-agent" "openssh" "publicKeyPath" ] "SSH public keys aren't necessary to clone private repos.")
- (mkRenamedOptionModule [ "services" "buildkite-agent" "meta-data"] [ "services" "buildkite-agent" "tags" ])
+ (mkRemovedOptionModule [ "services" "buildkite-agent"] "services.buildkite-agent has been upgraded from version 2 to version 3 and moved to an attribute set at services.buildkite-agents. Please consult the 20.03 release notes for more information.")
];
}
diff --git a/nixpkgs/nixos/modules/services/databases/mysql.nix b/nixpkgs/nixos/modules/services/databases/mysql.nix
index 8d520b82fb5..248bf0ebc91 100644
--- a/nixpkgs/nixos/modules/services/databases/mysql.nix
+++ b/nixpkgs/nixos/modules/services/databases/mysql.nix
@@ -21,6 +21,11 @@ let
installOptions =
"${mysqldOptions} ${lib.optionalString isMysqlAtLeast57 "--insecure"}";
+ settingsFile = pkgs.writeText "my.cnf" (
+ generators.toINI { listsAsDuplicateKeys = true; } cfg.settings +
+ optionalString (cfg.extraOptions != null) "[mysqld]\n${cfg.extraOptions}"
+ );
+
in
{
@@ -76,9 +81,64 @@ in
description = "Location where MySQL stores its table files";
};
+ configFile = mkOption {
+ type = types.path;
+ default = settingsFile;
+ defaultText = "settingsFile";
+ description = ''
+ Override the configuration file used by MySQL. By default,
+ NixOS generates one automatically from <option>services.mysql.settings</option>.
+ '';
+ example = literalExample ''
+ pkgs.writeText "my.cnf" '''
+ [mysqld]
+ datadir = /var/lib/mysql
+ bind-address = 127.0.0.1
+ port = 3336
+ plugin-load-add = auth_socket.so
+
+ !includedir /etc/mysql/conf.d/
+ ''';
+ '';
+ };
+
+ settings = mkOption {
+ type = with types; attrsOf (attrsOf (oneOf [ bool int str (listOf str) ]));
+ default = {};
+ description = ''
+ MySQL configuration. Refer to
+ <link xlink:href="https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html"/>,
+ <link xlink:href="https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html"/>,
+ and <link xlink:href="https://mariadb.com/kb/en/server-system-variables/"/>
+ for details on supported values.
+
+ <note>
+ <para>
+ MySQL configuration options such as <literal>--quick</literal> should be treated as
+ boolean options and provided values such as <literal>true</literal>, <literal>false</literal>,
+ <literal>1</literal>, or <literal>0</literal>. See the provided example below.
+ </para>
+ </note>
+ '';
+ example = literalExample ''
+ {
+ mysqld = {
+ key_buffer_size = "6G";
+ table_cache = 1600;
+ log-error = "/var/log/mysql_err.log";
+ plugin-load-add = [ "server_audit" "ed25519=auth_ed25519" ];
+ };
+ mysqldump = {
+ quick = true;
+ max_allowed_packet = "16M";
+ };
+ }
+ '';
+ };
+
extraOptions = mkOption {
- type = types.lines;
- default = "";
+ type = with types; nullOr lines;
+ default = null;
example = ''
key_buffer_size = 6G
table_cache = 1600
@@ -252,10 +312,27 @@ in
config = mkIf config.services.mysql.enable {
+ warnings = optional (cfg.extraOptions != null) "services.mysql.`extraOptions` is deprecated, please use services.mysql.`settings`.";
+
services.mysql.dataDir =
mkDefault (if versionAtLeast config.system.stateVersion "17.09" then "/var/lib/mysql"
else "/var/mysql");
+ services.mysql.settings.mysqld = mkMerge [
+ {
+ datadir = cfg.dataDir;
+ bind-address = mkIf (cfg.bind != null) cfg.bind;
+ port = cfg.port;
+ plugin-load-add = optional (cfg.ensureUsers != []) "auth_socket.so";
+ }
+ (mkIf (cfg.replication.role == "master" || cfg.replication.role == "slave") {
+ log-bin = "mysql-bin-${toString cfg.replication.serverId}";
+ log-bin-index = "mysql-bin-${toString cfg.replication.serverId}.index";
+ relay-log = "mysql-relay-bin";
+ server-id = cfg.replication.serverId;
+ })
+ ];
+
users.users.mysql = {
description = "MySQL server user";
group = "mysql";
@@ -266,25 +343,7 @@ in
environment.systemPackages = [mysql];
- environment.etc."my.cnf".text =
- ''
- [mysqld]
- port = ${toString cfg.port}
- datadir = ${cfg.dataDir}
- ${optionalString (cfg.bind != null) "bind-address = ${cfg.bind}" }
- ${optionalString (cfg.replication.role == "master" || cfg.replication.role == "slave")
- ''
- log-bin=mysql-bin-${toString cfg.replication.serverId}
- log-bin-index=mysql-bin-${toString cfg.replication.serverId}.index
- relay-log=mysql-relay-bin
- server-id = ${toString cfg.replication.serverId}
- ''}
- ${optionalString (cfg.ensureUsers != [])
- ''
- plugin-load-add = auth_socket.so
- ''}
- ${cfg.extraOptions}
- '';
+ environment.etc."my.cnf".source = cfg.configFile;
systemd.tmpfiles.rules = [
"d '${cfg.dataDir}' 0700 ${cfg.user} mysql -"
@@ -297,7 +356,7 @@ in
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
- restartTriggers = [ config.environment.etc."my.cnf".source ];
+ restartTriggers = [ cfg.configFile ];
unitConfig.RequiresMountsFor = "${cfg.dataDir}";
diff --git a/nixpkgs/nixos/modules/services/databases/postgresql.nix b/nixpkgs/nixos/modules/services/databases/postgresql.nix
index c8fdd89d0d8..0b79a996dc7 100644
--- a/nixpkgs/nixos/modules/services/databases/postgresql.nix
+++ b/nixpkgs/nixos/modules/services/databases/postgresql.nix
@@ -20,7 +20,9 @@ let
listen_addresses = '${if cfg.enableTCPIP then "*" else "localhost"}'
port = ${toString cfg.port}
${cfg.extraConfig}
- '';
+ '';
+
+ groupAccessAvailable = versionAtLeast postgresql.version "11.0";
in
@@ -88,6 +90,16 @@ in
'';
};
+ initdbArgs = mkOption {
+ type = with types; listOf str;
+ default = [];
+ example = [ "--data-checksums" "--allow-group-access" ];
+ description = ''
+ Additional arguments passed to <literal>initdb</literal> during data dir
+ initialisation.
+ '';
+ };
+
initialScript = mkOption {
type = types.nullOr types.path;
default = null;
@@ -220,7 +232,7 @@ in
###### implementation
- config = mkIf config.services.postgresql.enable {
+ config = mkIf cfg.enable {
services.postgresql.package =
# Note: when changing the default, make it conditional on
@@ -232,13 +244,14 @@ in
else throw "postgresql_9_4 was removed, please upgrade your postgresql version.");
services.postgresql.dataDir =
- mkDefault (if versionAtLeast config.system.stateVersion "17.09" then "/var/lib/postgresql/${config.services.postgresql.package.psqlSchema}"
- else "/var/db/postgresql");
+ mkDefault (if versionAtLeast config.system.stateVersion "17.09"
+ then "/var/lib/postgresql/${cfg.package.psqlSchema}"
+ else "/var/db/postgresql");
services.postgresql.authentication = mkAfter
''
# Generated file; do not edit!
- local all all ident
+ local all all peer
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
'';
@@ -284,7 +297,7 @@ in
''
# Initialise the database.
if ! test -e ${cfg.dataDir}/PG_VERSION; then
- initdb -U ${cfg.superUser}
+ initdb -U ${cfg.superUser} ${concatStringsSep " " cfg.initdbArgs}
# See postStart!
touch "${cfg.dataDir}/.first_startup"
fi
@@ -293,8 +306,12 @@ in
ln -sfn "${pkgs.writeText "recovery.conf" cfg.recoveryConfig}" \
"${cfg.dataDir}/recovery.conf"
''}
+ ${optionalString (!groupAccessAvailable) ''
+ # postgresql pre 11.0 doesn't start if state directory mode is group accessible
+ chmod 0700 "${cfg.dataDir}"
+ ''}
- exec postgres
+ exec postgres
'';
serviceConfig =
@@ -303,7 +320,7 @@ in
Group = "postgres";
PermissionsStartOnly = true;
RuntimeDirectory = "postgresql";
- Type = if lib.versionAtLeast cfg.package.version "9.6"
+ Type = if versionAtLeast cfg.package.version "9.6"
then "notify"
else "simple";
@@ -352,5 +369,5 @@ in
};
meta.doc = ./postgresql.xml;
- meta.maintainers = with lib.maintainers; [ thoughtpolice ];
+ meta.maintainers = with lib.maintainers; [ thoughtpolice danbst ];
}
diff --git a/nixpkgs/nixos/modules/services/databases/redis.nix b/nixpkgs/nixos/modules/services/databases/redis.nix
index 70895fa53e4..5c817422aae 100644
--- a/nixpkgs/nixos/modules/services/databases/redis.nix
+++ b/nixpkgs/nixos/modules/services/databases/redis.nix
@@ -150,10 +150,20 @@ in
requirePass = mkOption {
type = with types; nullOr str;
default = null;
- description = "Password for database (STORED PLAIN TEXT, WORLD-READABLE IN NIX STORE)";
+ description = ''
+ Password for database (STORED PLAIN TEXT, WORLD-READABLE IN NIX STORE).
+ Use requirePassFile to store it outside of the nix store in a dedicated file.
+ '';
example = "letmein!";
};
+ requirePassFile = mkOption {
+ type = with types; nullOr path;
+ default = null;
+ description = "File with password for the database.";
+ example = "/run/keys/redis-password";
+ };
+
appendOnly = mkOption {
type = types.bool;
default = false;
@@ -192,6 +202,10 @@ in
###### implementation
config = mkIf config.services.redis.enable {
+ assertions = [{
+ assertion = cfg.requirePass != null -> cfg.requirePassFile == null;
+ message = "You can only set one services.redis.requirePass or services.redis.requirePassFile";
+ }];
boot.kernel.sysctl = (mkMerge [
{ "vm.nr_hugepages" = "0"; }
( mkIf cfg.vmOverCommit { "vm.overcommit_memory" = "1"; } )
@@ -208,21 +222,26 @@ in
environment.systemPackages = [ cfg.package ];
- systemd.services.redis =
- { description = "Redis Server";
+ systemd.services.redis = {
+ description = "Redis Server";
- wantedBy = [ "multi-user.target" ];
- after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network.target" ];
- serviceConfig = {
- ExecStart = "${cfg.package}/bin/redis-server ${redisConfig}";
- RuntimeDirectory = "redis";
- StateDirectory = "redis";
- Type = "notify";
- User = "redis";
- };
- };
+ preStart = ''
+ install -m 600 ${redisConfig} /run/redis/redis.conf
+ '' + optionalString (cfg.requirePassFile != null) ''
+ password=$(cat ${escapeShellArg cfg.requirePassFile})
+ echo "requirePass $password" >> /run/redis/redis.conf
+ '';
+ serviceConfig = {
+ ExecStart = "${cfg.package}/bin/redis-server /run/redis/redis.conf";
+ RuntimeDirectory = "redis";
+ StateDirectory = "redis";
+ Type = "notify";
+ User = "redis";
+ };
+ };
};
-
}
diff --git a/nixpkgs/nixos/modules/services/desktops/malcontent.nix b/nixpkgs/nixos/modules/services/desktops/malcontent.nix
new file mode 100644
index 00000000000..416464cbe08
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/desktops/malcontent.nix
@@ -0,0 +1,32 @@
+# Malcontent daemon.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+
+ ###### interface
+
+ options = {
+
+ services.malcontent = {
+
+ enable = mkEnableOption "Malcontent";
+
+ };
+
+ };
+
+
+ ###### implementation
+
+ config = mkIf config.services.malcontent.enable {
+
+ environment.systemPackages = [ pkgs.malcontent ];
+
+ services.dbus.packages = [ pkgs.malcontent ];
+
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/development/jupyter/default.nix b/nixpkgs/nixos/modules/services/development/jupyter/default.nix
index f20860af6e1..e598b018645 100644
--- a/nixpkgs/nixos/modules/services/development/jupyter/default.nix
+++ b/nixpkgs/nixos/modules/services/development/jupyter/default.nix
@@ -118,15 +118,15 @@ in {
in {
displayName = "Python 3 for machine learning";
argv = [
- "$ {env.interpreter}"
+ "''${env.interpreter}"
"-m"
"ipykernel_launcher"
"-f"
"{connection_file}"
];
language = "python";
- logo32 = "$ {env.sitePackages}/ipykernel/resources/logo-32x32.png";
- logo64 = "$ {env.sitePackages}/ipykernel/resources/logo-64x64.png";
+ logo32 = "''${env.sitePackages}/ipykernel/resources/logo-32x32.png";
+ logo64 = "''${env.sitePackages}/ipykernel/resources/logo-64x64.png";
};
}
'';
diff --git a/nixpkgs/nixos/modules/services/hardware/fwupd.nix b/nixpkgs/nixos/modules/services/hardware/fwupd.nix
index 51877970a8b..e586af25c2b 100644
--- a/nixpkgs/nixos/modules/services/hardware/fwupd.nix
+++ b/nixpkgs/nixos/modules/services/hardware/fwupd.nix
@@ -53,7 +53,7 @@ in {
blacklistPlugins = mkOption {
type = types.listOf types.str;
- default = [ "test" ];
+ default = [];
example = [ "udev" ];
description = ''
Allow blacklisting specific plugins
@@ -91,6 +91,9 @@ in {
###### implementation
config = mkIf cfg.enable {
+ # Disable test related plug-ins implicitly so that users do not have to care about them.
+ services.fwupd.blacklistPlugins = cfg.package.defaultBlacklistedPlugins;
+
environment.systemPackages = [ cfg.package ];
environment.etc = {
diff --git a/nixpkgs/nixos/modules/services/hardware/irqbalance.nix b/nixpkgs/nixos/modules/services/hardware/irqbalance.nix
index b139154432c..c79e0eb83ec 100644
--- a/nixpkgs/nixos/modules/services/hardware/irqbalance.nix
+++ b/nixpkgs/nixos/modules/services/hardware/irqbalance.nix
@@ -13,18 +13,12 @@ in
config = mkIf cfg.enable {
- systemd.services = {
- irqbalance = {
- description = "irqbalance daemon";
- path = [ pkgs.irqbalance ];
- serviceConfig =
- { ExecStart = "${pkgs.irqbalance}/bin/irqbalance --foreground"; };
- wantedBy = [ "multi-user.target" ];
- };
- };
-
environment.systemPackages = [ pkgs.irqbalance ];
+ systemd.services.irqbalance.wantedBy = ["multi-user.target"];
+
+ systemd.packages = [ pkgs.irqbalance ];
+
};
}
diff --git a/nixpkgs/nixos/modules/services/hardware/tlp.nix b/nixpkgs/nixos/modules/services/hardware/tlp.nix
index 955a6067799..3962d7b1598 100644
--- a/nixpkgs/nixos/modules/services/hardware/tlp.nix
+++ b/nixpkgs/nixos/modules/services/hardware/tlp.nix
@@ -1,39 +1,26 @@
{ config, lib, pkgs, ... }:
-
with lib;
-
let
-
-cfg = config.services.tlp;
-
-enableRDW = config.networking.networkmanager.enable;
-
-tlp = pkgs.tlp.override {
- inherit enableRDW;
-};
-
-# XXX: We can't use writeTextFile + readFile here because it triggers
-# TLP build to get the .drv (even on --dry-run).
-confFile = pkgs.runCommand "tlp"
- { config = cfg.extraConfig;
- passAsFile = [ "config" ];
- preferLocalBuild = true;
- }
- ''
- cat ${tlp}/etc/default/tlp > $out
- cat $configPath >> $out
- '';
-
+ cfg = config.services.tlp;
+ enableRDW = config.networking.networkmanager.enable;
+ tlp = pkgs.tlp.override { inherit enableRDW; };
+ # TODO: Use this for having proper parameters in the future
+ mkTlpConfig = tlpConfig: generators.toKeyValue {
+ mkKeyValue = generators.mkKeyValueDefault {
+ mkValueString = val:
+ if isInt val then toString val
+ else if isString val then val
+ else if true == val then "1"
+ else if false == val then "0"
+ else if isList val then "\"" + (concatStringsSep " " val) + "\""
+ else err "invalid value provided to mkTlpConfig:" (toString val);
+ } "=";
+ } tlpConfig;
in
-
{
-
###### interface
-
options = {
-
services.tlp = {
-
enable = mkOption {
type = types.bool;
default = false;
@@ -45,77 +32,64 @@ in
default = "";
description = "Additional configuration variables for TLP";
};
-
};
-
};
-
###### implementation
-
config = mkIf cfg.enable {
+ boot.kernelModules = [ "msr" ];
- powerManagement.scsiLinkPolicy = null;
- powerManagement.cpuFreqGovernor = null;
- powerManagement.cpufreq.max = null;
- powerManagement.cpufreq.min = null;
+ environment.etc = {
+ "tlp.conf".text = cfg.extraConfig;
+ } // optionalAttrs enableRDW {
+ "NetworkManager/dispatcher.d/99tlp-rdw-nm".source =
+ "${tlp}/etc/NetworkManager/dispatcher.d/99tlp-rdw-nm";
+ };
- systemd.sockets.systemd-rfkill.enable = false;
+ environment.systemPackages = [ tlp ];
- systemd.services = {
- "systemd-rfkill@".enable = false;
- systemd-rfkill.enable = false;
+ # FIXME: When the config is parametrized we need to move these into a
+ # conditional on the relevant options being enabled.
+ powerManagement = {
+ scsiLinkPolicy = null;
+ cpuFreqGovernor = null;
+ cpufreq.max = null;
+ cpufreq.min = null;
+ };
- tlp = {
- description = "TLP system startup/shutdown";
+ services.udev.packages = [ tlp ];
- after = [ "multi-user.target" ];
+ systemd = {
+ packages = [ tlp ];
+ # XXX: These must always be disabled/masked according to [1].
+ #
+ # [1]: https://github.com/linrunner/TLP/blob/a9ada09e0821f275ce5f93dc80a4d81a7ff62ae4/tlp-stat.in#L319
+ sockets.systemd-rfkill.enable = false;
+ services.systemd-rfkill.enable = false;
+
+ services.tlp = {
+ # XXX: The service should reload whenever the configuration changes,
+ # otherwise newly set power options remain inactive until reboot (or
+ # manual unit restart.)
+ restartTriggers = [ config.environment.etc."tlp.conf".source ];
+ # XXX: When using systemd.packages (which we do above) the [Install]
+ # section of systemd units does not work (citation needed) so we manually
+ # enforce it here.
wantedBy = [ "multi-user.target" ];
- before = [ "shutdown.target" ];
- restartTriggers = [ confFile ];
-
- serviceConfig = {
- Type = "oneshot";
- RemainAfterExit = true;
- ExecStart = "${tlp}/bin/tlp init start";
- ExecStop = "${tlp}/bin/tlp init stop";
- };
};
- tlp-sleep = {
- description = "TLP suspend/resume";
-
- wantedBy = [ "sleep.target" ];
+ services.tlp-sleep = {
+ # XXX: When using systemd.packages (which we do above) the [Install]
+ # section of systemd units does not work (citation needed) so we manually
+ # enforce it here.
before = [ "sleep.target" ];
-
- unitConfig = {
- StopWhenUnneeded = true;
- };
-
- serviceConfig = {
- Type = "oneshot";
- RemainAfterExit = true;
- ExecStart = "${tlp}/bin/tlp suspend";
- ExecStop = "${tlp}/bin/tlp resume";
- };
+ wantedBy = [ "sleep.target" ];
+ # XXX: `tlp suspend` requires /var/lib/tlp to exist in order to save
+ # some stuff in there. There is no way, that I know of, to do this in
+ # the package itself, so we do it here instead making sure the unit
+ # won't fail due to the save dir not existing.
+ serviceConfig.StateDirectory = "tlp";
};
};
-
- services.udev.packages = [ tlp ];
-
- environment.etc =
- {
- "default/tlp".source = confFile;
- } // optionalAttrs enableRDW {
- "NetworkManager/dispatcher.d/99tlp-rdw-nm" = {
- source = "${tlp}/etc/NetworkManager/dispatcher.d/99tlp-rdw-nm";
- };
- };
-
- environment.systemPackages = [ tlp ];
-
- boot.kernelModules = [ "msr" ];
-
};
-
}
diff --git a/nixpkgs/nixos/modules/services/mail/dovecot.nix b/nixpkgs/nixos/modules/services/mail/dovecot.nix
index b5ed2c594f7..230a2ae3f82 100644
--- a/nixpkgs/nixos/modules/services/mail/dovecot.nix
+++ b/nixpkgs/nixos/modules/services/mail/dovecot.nix
@@ -14,18 +14,34 @@ let
base_dir = ${baseDir}
protocols = ${concatStringsSep " " cfg.protocols}
sendmail_path = /run/wrappers/bin/sendmail
+ # defining mail_plugins must be done before the first protocol {} filter because of https://doc.dovecot.org/configuration_manual/config_file/config_file_syntax/#variable-expansion
+ mail_plugins = $mail_plugins ${concatStringsSep " " cfg.mailPlugins.globally.enable}
''
- (if cfg.sslServerCert == null then ''
- ssl = no
- disable_plaintext_auth = no
- '' else ''
- ssl_cert = <${cfg.sslServerCert}
- ssl_key = <${cfg.sslServerKey}
- ${optionalString (cfg.sslCACert != null) ("ssl_ca = <" + cfg.sslCACert)}
- ssl_dh = <${config.security.dhparams.params.dovecot2.path}
- disable_plaintext_auth = yes
- '')
+ (
+ concatStringsSep "\n" (
+ mapAttrsToList (
+ protocol: plugins: ''
+ protocol ${protocol} {
+ mail_plugins = $mail_plugins ${concatStringsSep " " plugins.enable}
+ }
+ ''
+ ) cfg.mailPlugins.perProtocol
+ )
+ )
+
+ (
+ if cfg.sslServerCert == null then ''
+ ssl = no
+ disable_plaintext_auth = no
+ '' else ''
+ ssl_cert = <${cfg.sslServerCert}
+ ssl_key = <${cfg.sslServerKey}
+ ${optionalString (cfg.sslCACert != null) ("ssl_ca = <" + cfg.sslCACert)}
+ ssl_dh = <${config.security.dhparams.params.dovecot2.path}
+ disable_plaintext_auth = yes
+ ''
+ )
''
default_internal_user = ${cfg.user}
@@ -45,55 +61,58 @@ let
}
''
- (optionalString cfg.enablePAM ''
- userdb {
- driver = passwd
- }
-
- passdb {
- driver = pam
- args = ${optionalString cfg.showPAMFailure "failure_show_msg=yes"} dovecot2
- }
- '')
+ (
+ optionalString cfg.enablePAM ''
+ userdb {
+ driver = passwd
+ }
- (optionalString (cfg.sieveScripts != {}) ''
- plugin {
- ${concatStringsSep "\n" (mapAttrsToList (to: from: "sieve_${to} = ${stateDir}/sieve/${to}") cfg.sieveScripts)}
- }
- '')
+ passdb {
+ driver = pam
+ args = ${optionalString cfg.showPAMFailure "failure_show_msg=yes"} dovecot2
+ }
+ ''
+ )
- (optionalString (cfg.mailboxes != []) ''
- protocol imap {
- namespace inbox {
- inbox=yes
- ${concatStringsSep "\n" (map mailboxConfig cfg.mailboxes)}
+ (
+ optionalString (cfg.sieveScripts != {}) ''
+ plugin {
+ ${concatStringsSep "\n" (mapAttrsToList (to: from: "sieve_${to} = ${stateDir}/sieve/${to}") cfg.sieveScripts)}
}
- }
- '')
-
- (optionalString cfg.enableQuota ''
- mail_plugins = $mail_plugins quota
- service quota-status {
- executable = ${dovecotPkg}/libexec/dovecot/quota-status -p postfix
- inet_listener {
- port = ${cfg.quotaPort}
+ ''
+ )
+
+ (
+ optionalString (cfg.mailboxes != []) ''
+ protocol imap {
+ namespace inbox {
+ inbox=yes
+ ${concatStringsSep "\n" (map mailboxConfig cfg.mailboxes)}
+ }
+ }
+ ''
+ )
+
+ (
+ optionalString cfg.enableQuota ''
+ service quota-status {
+ executable = ${dovecotPkg}/libexec/dovecot/quota-status -p postfix
+ inet_listener {
+ port = ${cfg.quotaPort}
+ }
+ client_limit = 1
}
- client_limit = 1
- }
-
- protocol imap {
- mail_plugins = $mail_plugins imap_quota
- }
- plugin {
- quota_rule = *:storage=${cfg.quotaGlobalPerUser}
- quota = maildir:User quota # per virtual mail user quota # BUG/FIXME broken, we couldn't get this working
- quota_status_success = DUNNO
- quota_status_nouser = DUNNO
- quota_status_overquota = "552 5.2.2 Mailbox is full"
- quota_grace = 10%%
- }
- '')
+ plugin {
+ quota_rule = *:storage=${cfg.quotaGlobalPerUser}
+ quota = maildir:User quota # per virtual mail user quota # BUG/FIXME broken, we couldn't get this working
+ quota_status_success = DUNNO
+ quota_status_nouser = DUNNO
+ quota_status_overquota = "552 5.2.2 Mailbox is full"
+ quota_grace = 10%%
+ }
+ ''
+ )
cfg.extraConfig
];
@@ -107,7 +126,7 @@ let
mailbox "${mailbox.name}" {
auto = ${toString mailbox.auto}
'' + optionalString (mailbox.specialUse != null) ''
- special_use = \${toString mailbox.specialUse}
+ special_use = \${toString mailbox.specialUse}
'' + "}";
mailboxes = { ... }: {
@@ -160,7 +179,7 @@ in
protocols = mkOption {
type = types.listOf types.str;
- default = [ ];
+ default = [];
description = "Additional listeners to start when Dovecot is enabled.";
};
@@ -183,6 +202,43 @@ in
description = "Additional entries to put verbatim into Dovecot's config file.";
};
+ mailPlugins =
+ let
+ plugins = hint: types.submodule {
+ options = {
+ enable = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ description = "mail plugins to enable as a list of strings to append to the ${hint} <literal>$mail_plugins</literal> configuration variable";
+ };
+ };
+ };
+ in
+ mkOption {
+ type = with types; submodule {
+ options = {
+ globally = mkOption {
+ description = "Additional entries to add to the mail_plugins variable for all protocols";
+ type = plugins "top-level";
+ example = { enable = [ "virtual" ]; };
+ default = { enable = []; };
+ };
+ perProtocol = mkOption {
+ description = "Additional entries to add to the mail_plugins variable, per protocol";
+ type = attrsOf (plugins "corresponding per-protocol");
+ default = {};
+ example = { imap = [ "imap_acl" ]; };
+ };
+ };
+ };
+ description = "Additional entries to add to the mail_plugins variable, globally and per protocol";
+ example = {
+ globally.enable = [ "acl" ];
+ perProtocol.imap.enable = [ "imap_acl" ];
+ };
+ default = { globally.enable = []; perProtocol = {}; };
+ };
+
configFile = mkOption {
type = types.nullOr types.path;
default = null;
@@ -305,27 +361,33 @@ in
enable = true;
params.dovecot2 = {};
};
- services.dovecot2.protocols =
- optional cfg.enableImap "imap"
- ++ optional cfg.enablePop3 "pop3"
- ++ optional cfg.enableLmtp "lmtp";
+ services.dovecot2.protocols =
+ optional cfg.enableImap "imap"
+ ++ optional cfg.enablePop3 "pop3"
+ ++ optional cfg.enableLmtp "lmtp";
+
+ services.dovecot2.mailPlugins = mkIf cfg.enableQuota {
+ globally.enable = [ "quota" ];
+ perProtocol.imap.enable = [ "imap_quota" ];
+ };
users.users = {
dovenull =
- { uid = config.ids.uids.dovenull2;
+ {
+ uid = config.ids.uids.dovenull2;
description = "Dovecot user for untrusted logins";
group = "dovenull";
};
} // optionalAttrs (cfg.user == "dovecot2") {
dovecot2 =
- { uid = config.ids.uids.dovecot2;
- description = "Dovecot user";
- group = cfg.group;
- };
+ {
+ uid = config.ids.uids.dovecot2;
+ description = "Dovecot user";
+ group = cfg.group;
+ };
} // optionalAttrs (cfg.createMailUser && cfg.mailUser != null) {
${cfg.mailUser} =
- { description = "Virtual Mail User"; } //
- optionalAttrs (cfg.mailGroup != null)
+ { description = "Virtual Mail User"; } // optionalAttrs (cfg.mailGroup != null)
{ group = cfg.mailGroup; };
};
@@ -334,7 +396,7 @@ in
} // optionalAttrs (cfg.group == "dovecot2") {
dovecot2.gid = config.ids.gids.dovecot2;
} // optionalAttrs (cfg.createMailUser && cfg.mailGroup != null) {
- ${cfg.mailGroup} = { };
+ ${cfg.mailGroup} = {};
};
environment.etc."dovecot/modules".source = modulesDir;
@@ -363,15 +425,19 @@ in
rm -rf ${stateDir}/sieve
'' + optionalString (cfg.sieveScripts != {}) ''
mkdir -p ${stateDir}/sieve
- ${concatStringsSep "\n" (mapAttrsToList (to: from: ''
- if [ -d '${from}' ]; then
- mkdir '${stateDir}/sieve/${to}'
- cp -p "${from}/"*.sieve '${stateDir}/sieve/${to}'
- else
- cp -p '${from}' '${stateDir}/sieve/${to}'
- fi
- ${pkgs.dovecot_pigeonhole}/bin/sievec '${stateDir}/sieve/${to}'
- '') cfg.sieveScripts)}
+ ${concatStringsSep "\n" (
+ mapAttrsToList (
+ to: from: ''
+ if [ -d '${from}' ]; then
+ mkdir '${stateDir}/sieve/${to}'
+ cp -p "${from}/"*.sieve '${stateDir}/sieve/${to}'
+ else
+ cp -p '${from}' '${stateDir}/sieve/${to}'
+ fi
+ ${pkgs.dovecot_pigeonhole}/bin/sievec '${stateDir}/sieve/${to}'
+ ''
+ ) cfg.sieveScripts
+ )}
chown -R '${cfg.mailUser}:${cfg.mailGroup}' '${stateDir}/sieve'
'';
};
@@ -379,17 +445,21 @@ in
environment.systemPackages = [ dovecotPkg ];
assertions = [
- { assertion = intersectLists cfg.protocols [ "pop3" "imap" ] != [];
+ {
+ assertion = intersectLists cfg.protocols [ "pop3" "imap" ] != [];
message = "dovecot needs at least one of the IMAP or POP3 listeners enabled";
}
- { assertion = (cfg.sslServerCert == null) == (cfg.sslServerKey == null)
- && (cfg.sslCACert != null -> !(cfg.sslServerCert == null || cfg.sslServerKey == null));
+ {
+ assertion = (cfg.sslServerCert == null) == (cfg.sslServerKey == null)
+ && (cfg.sslCACert != null -> !(cfg.sslServerCert == null || cfg.sslServerKey == null));
message = "dovecot needs both sslServerCert and sslServerKey defined for working crypto";
}
- { assertion = cfg.showPAMFailure -> cfg.enablePAM;
+ {
+ assertion = cfg.showPAMFailure -> cfg.enablePAM;
message = "dovecot is configured with showPAMFailure while enablePAM is disabled";
}
- { assertion = cfg.sieveScripts != {} -> (cfg.mailUser != null && cfg.mailGroup != null);
+ {
+ assertion = cfg.sieveScripts != {} -> (cfg.mailUser != null && cfg.mailGroup != null);
message = "dovecot requires mailUser and mailGroup to be set when sieveScripts is set";
}
];
diff --git a/nixpkgs/nixos/modules/services/mail/mailman.nix b/nixpkgs/nixos/modules/services/mail/mailman.nix
index 43dc185cdd7..f5e78b18293 100644
--- a/nixpkgs/nixos/modules/services/mail/mailman.nix
+++ b/nixpkgs/nixos/modules/services/mail/mailman.nix
@@ -265,6 +265,11 @@ in {
'';
serviceConfig = {
Type = "oneshot";
+ # RemainAfterExit makes restartIfChanged work for this service, so
+ # downstream services will get updated automatically when things like
+ # services.mailman.hyperkitty.baseUrl change. Otherwise users have to
+ # restart things manually, which is confusing.
+ RemainAfterExit = "yes";
};
};
@@ -282,6 +287,9 @@ in {
serviceConfig = {
User = cfg.webUser;
Type = "oneshot";
+ # Similar to mailman-settings.service, this makes restartTriggers work
+ # properly for this service.
+ RemainAfterExit = "yes";
WorkingDirectory = "/var/lib/mailman-web";
};
};
diff --git a/nixpkgs/nixos/modules/services/mail/sympa.nix b/nixpkgs/nixos/modules/services/mail/sympa.nix
new file mode 100644
index 00000000000..c3ae9d4255b
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/mail/sympa.nix
@@ -0,0 +1,596 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.sympa;
+ dataDir = "/var/lib/sympa";
+ user = "sympa";
+ group = "sympa";
+ pkg = pkgs.sympa;
+ fqdns = attrNames cfg.domains;
+ usingNginx = cfg.web.enable && cfg.web.server == "nginx";
+ mysqlLocal = cfg.database.createLocally && cfg.database.type == "MySQL";
+ pgsqlLocal = cfg.database.createLocally && cfg.database.type == "PostgreSQL";
+
+ sympaSubServices = [
+ "sympa-archive.service"
+ "sympa-bounce.service"
+ "sympa-bulk.service"
+ "sympa-task.service"
+ ];
+
+ # common for all services including wwsympa
+ commonServiceConfig = {
+ StateDirectory = "sympa";
+ ProtectHome = true;
+ ProtectSystem = "full";
+ ProtectKernelTunables = true;
+ ProtectKernelModules = true;
+ ProtectControlGroups = true;
+ };
+
+ # wwsympa has its own service config
+ sympaServiceConfig = srv: {
+ Type = "simple";
+ Restart = "always";
+ ExecStart = "${pkg}/bin/${srv}.pl --foreground";
+ PIDFile = "/run/sympa/${srv}.pid";
+ User = user;
+ Group = group;
+
+ # avoid duplicating log messageges in journal
+ StandardError = "null";
+ } // commonServiceConfig;
+
+ configVal = value:
+ if isBool value then
+ if value then "on" else "off"
+ else toString value;
+ configGenerator = c: concatStrings (flip mapAttrsToList c (key: val: "${key}\t${configVal val}\n"));
+
+ mainConfig = pkgs.writeText "sympa.conf" (configGenerator cfg.settings);
+ robotConfig = fqdn: domain: pkgs.writeText "${fqdn}-robot.conf" (configGenerator domain.settings);
+
+ transport = pkgs.writeText "transport.sympa" (concatStringsSep "\n" (flip map fqdns (domain: ''
+ ${domain} error:User unknown in recipient table
+ sympa@${domain} sympa:sympa@${domain}
+ listmaster@${domain} sympa:listmaster@${domain}
+ bounce@${domain} sympabounce:sympa@${domain}
+ abuse-feedback-report@${domain} sympabounce:sympa@${domain}
+ '')));
+
+ virtual = pkgs.writeText "virtual.sympa" (concatStringsSep "\n" (flip map fqdns (domain: ''
+ sympa-request@${domain} postmaster@localhost
+ sympa-owner@${domain} postmaster@localhost
+ '')));
+
+ listAliases = pkgs.writeText "list_aliases.tt2" ''
+ #--- [% list.name %]@[% list.domain %]: list transport map created at [% date %]
+ [% list.name %]@[% list.domain %] sympa:[% list.name %]@[% list.domain %]
+ [% list.name %]-request@[% list.domain %] sympa:[% list.name %]-request@[% list.domain %]
+ [% list.name %]-editor@[% list.domain %] sympa:[% list.name %]-editor@[% list.domain %]
+ #[% list.name %]-subscribe@[% list.domain %] sympa:[% list.name %]-subscribe@[%list.domain %]
+ [% list.name %]-unsubscribe@[% list.domain %] sympa:[% list.name %]-unsubscribe@[% list.domain %]
+ [% list.name %][% return_path_suffix %]@[% list.domain %] sympabounce:[% list.name %]@[% list.domain %]
+ '';
+
+ enabledFiles = filterAttrs (n: v: v.enable) cfg.settingsFile;
+in
+{
+
+ ###### interface
+ options.services.sympa = with types; {
+
+ enable = mkEnableOption "Sympa mailing list manager";
+
+ lang = mkOption {
+ type = str;
+ default = "en_US";
+ example = "cs";
+ description = ''
+ Default Sympa language.
+ See <link xlink:href='https://github.com/sympa-community/sympa/tree/sympa-6.2/po/sympa' />
+ for available options.
+ '';
+ };
+
+ listMasters = mkOption {
+ type = listOf str;
+ example = [ "postmaster@sympa.example.org" ];
+ description = ''
+ The list of the email addresses of the listmasters
+ (users authorized to perform global server commands).
+ '';
+ };
+
+ mainDomain = mkOption {
+ type = nullOr str;
+ default = null;
+ example = "lists.example.org";
+ description = ''
+ Main domain to be used in <filename>sympa.conf</filename>.
+ If <literal>null</literal>, one of the <option>services.sympa.domains</option> is chosen for you.
+ '';
+ };
+
+ domains = mkOption {
+ type = attrsOf (submodule ({ name, config, ... }: {
+ options = {
+ webHost = mkOption {
+ type = nullOr str;
+ default = null;
+ example = "archive.example.org";
+ description = ''
+ Domain part of the web interface URL (no web interface for this domain if <literal>null</literal>).
+ DNS record of type A (or AAAA or CNAME) has to exist with this value.
+ '';
+ };
+ webLocation = mkOption {
+ type = str;
+ default = "/";
+ example = "/sympa";
+ description = "URL path part of the web interface.";
+ };
+ settings = mkOption {
+ type = attrsOf (oneOf [ str int bool ]);
+ default = {};
+ example = {
+ default_max_list_members = 3;
+ };
+ description = ''
+ The <filename>robot.conf</filename> configuration file as key value set.
+ See <link xlink:href='https://sympa-community.github.io/gpldoc/man/sympa.conf.5.html' />
+ for list of configuration parameters.
+ '';
+ };
+ };
+
+ config.settings = mkIf (cfg.web.enable && config.webHost != null) {
+ wwsympa_url = mkDefault "https://${config.webHost}${strings.removeSuffix "/" config.webLocation}";
+ };
+ }));
+
+ description = ''
+ Email domains handled by this instance. There have
+ to be MX records for keys of this attribute set.
+ '';
+ example = literalExample ''
+ {
+ "lists.example.org" = {
+ webHost = "lists.example.org";
+ webLocation = "/";
+ };
+ "sympa.example.com" = {
+ webHost = "example.com";
+ webLocation = "/sympa";
+ };
+ }
+ '';
+ };
+
+ database = {
+ type = mkOption {
+ type = enum [ "SQLite" "PostgreSQL" "MySQL" ];
+ default = "SQLite";
+ example = "MySQL";
+ description = "Database engine to use.";
+ };
+
+ host = mkOption {
+ type = nullOr str;
+ default = null;
+ description = ''
+ Database host address.
+
+ For MySQL, use <literal>localhost</literal> to connect using Unix domain socket.
+
+ For PostgreSQL, use path to directory (e.g. <filename>/run/postgresql</filename>)
+ to connect using Unix domain socket located in this directory.
+
+ Use <literal>null</literal> to fall back on Sympa default, or when using
+ <option>services.sympa.database.createLocally</option>.
+ '';
+ };
+
+ port = mkOption {
+ type = nullOr port;
+ default = null;
+ description = "Database port. Use <literal>null</literal> for default port.";
+ };
+
+ name = mkOption {
+ type = str;
+ default = if cfg.database.type == "SQLite" then "${dataDir}/sympa.sqlite" else "sympa";
+ defaultText = ''if database.type == "SQLite" then "${dataDir}/sympa.sqlite" else "sympa"'';
+ description = ''
+ Database name. When using SQLite this must be an absolute
+ path to the database file.
+ '';
+ };
+
+ user = mkOption {
+ type = nullOr str;
+ default = user;
+ description = "Database user. The system user name is used as a default.";
+ };
+
+ passwordFile = mkOption {
+ type = nullOr path;
+ default = null;
+ example = "/run/keys/sympa-dbpassword";
+ description = ''
+ A file containing the password for <option>services.sympa.database.user</option>.
+ '';
+ };
+
+ createLocally = mkOption {
+ type = bool;
+ default = true;
+ description = "Whether to create a local database automatically.";
+ };
+ };
+
+ web = {
+ enable = mkOption {
+ type = bool;
+ default = true;
+ description = "Whether to enable Sympa web interface.";
+ };
+
+ server = mkOption {
+ type = enum [ "nginx" "none" ];
+ default = "nginx";
+ description = ''
+ The webserver used for the Sympa web interface. Set it to `none` if you want to configure it yourself.
+ Further nginx configuration can be done by adapting
+ <option>services.nginx.virtualHosts.<replaceable>name</replaceable></option>.
+ '';
+ };
+
+ https = mkOption {
+ type = bool;
+ default = true;
+ description = ''
+ Whether to use HTTPS. When nginx integration is enabled, this option forces SSL and enables ACME.
+ Please note that Sympa web interface always uses https links even when this option is disabled.
+ '';
+ };
+
+ fcgiProcs = mkOption {
+ type = ints.positive;
+ default = 2;
+ description = "Number of FastCGI processes to fork.";
+ };
+ };
+
+ mta = {
+ type = mkOption {
+ type = enum [ "postfix" "none" ];
+ default = "postfix";
+ description = ''
+ Mail transfer agent (MTA) integration. Use <literal>none</literal> if you want to configure it yourself.
+
+ The <literal>postfix</literal> integration sets up local Postfix instance that will pass incoming
+ messages from configured domains to Sympa. You still need to configure at least outgoing message
+ handling using e.g. <option>services.postfix.relayHost</option>.
+ '';
+ };
+ };
+
+ settings = mkOption {
+ type = attrsOf (oneOf [ str int bool ]);
+ default = {};
+ example = literalExample ''
+ {
+ default_home = "lists";
+ viewlogs_page_size = 50;
+ }
+ '';
+ description = ''
+ The <filename>sympa.conf</filename> configuration file as key value set.
+ See <link xlink:href='https://sympa-community.github.io/gpldoc/man/sympa.conf.5.html' />
+ for list of configuration parameters.
+ '';
+ };
+
+ settingsFile = mkOption {
+ type = attrsOf (submodule ({ name, config, ... }: {
+ options = {
+ enable = mkOption {
+ type = bool;
+ default = true;
+ description = "Whether this file should be generated. This option allows specific files to be disabled.";
+ };
+ text = mkOption {
+ default = null;
+ type = nullOr lines;
+ description = "Text of the file.";
+ };
+ source = mkOption {
+ type = path;
+ description = "Path of the source file.";
+ };
+ };
+
+ config.source = mkIf (config.text != null) (mkDefault (pkgs.writeText "sympa-${baseNameOf name}" config.text));
+ }));
+ default = {};
+ example = literalExample ''
+ {
+ "list_data/lists.example.org/help" = {
+ text = "subject This list provides help to users";
+ };
+ }
+ '';
+ description = "Set of files to be linked in <filename>${dataDir}</filename>.";
+ };
+ };
+
+ ###### implementation
+
+ config = mkIf cfg.enable {
+
+ services.sympa.settings = (mapAttrs (_: v: mkDefault v) {
+ domain = if cfg.mainDomain != null then cfg.mainDomain else head fqdns;
+ listmaster = concatStringsSep "," cfg.listMasters;
+ lang = cfg.lang;
+
+ home = "${dataDir}/list_data";
+ arc_path = "${dataDir}/arc";
+ bounce_path = "${dataDir}/bounce";
+
+ sendmail = "${pkgs.system-sendmail}/bin/sendmail";
+
+ db_type = cfg.database.type;
+ db_name = cfg.database.name;
+ }
+ // (optionalAttrs (cfg.database.host != null) {
+ db_host = cfg.database.host;
+ })
+ // (optionalAttrs mysqlLocal {
+ db_host = "localhost"; # use unix domain socket
+ })
+ // (optionalAttrs pgsqlLocal {
+ db_host = "/run/postgresql"; # use unix domain socket
+ })
+ // (optionalAttrs (cfg.database.port != null) {
+ db_port = cfg.database.port;
+ })
+ // (optionalAttrs (cfg.database.user != null) {
+ db_user = cfg.database.user;
+ })
+ // (optionalAttrs (cfg.mta.type == "postfix") {
+ sendmail_aliases = "${dataDir}/sympa_transport";
+ aliases_program = "${pkgs.postfix}/bin/postmap";
+ aliases_db_type = "hash";
+ })
+ // (optionalAttrs cfg.web.enable {
+ static_content_path = "${dataDir}/static_content";
+ css_path = "${dataDir}/static_content/css";
+ pictures_path = "${dataDir}/static_content/pictures";
+ mhonarc = "${pkgs.perlPackages.MHonArc}/bin/mhonarc";
+ }));
+
+ services.sympa.settingsFile = {
+ "virtual.sympa" = mkDefault { source = virtual; };
+ "transport.sympa" = mkDefault { source = transport; };
+ "etc/list_aliases.tt2" = mkDefault { source = listAliases; };
+ }
+ // (flip mapAttrs' cfg.domains (fqdn: domain:
+ nameValuePair "etc/${fqdn}/robot.conf" (mkDefault { source = robotConfig fqdn domain; })));
+
+ environment = {
+ systemPackages = [ pkg ];
+ };
+
+ users.users.${user} = {
+ description = "Sympa mailing list manager user";
+ group = group;
+ home = dataDir;
+ createHome = false;
+ isSystemUser = true;
+ };
+
+ users.groups.${group} = {};
+
+ assertions = [
+ { assertion = cfg.database.createLocally -> cfg.database.user == user;
+ message = "services.sympa.database.user must be set to ${user} if services.sympa.database.createLocally is set to true";
+ }
+ { assertion = cfg.database.createLocally -> cfg.database.passwordFile == null;
+ message = "a password cannot be specified if services.sympa.database.createLocally is set to true";
+ }
+ ];
+
+ systemd.tmpfiles.rules = [
+ "d ${dataDir} 0711 ${user} ${group} - -"
+ "d ${dataDir}/etc 0700 ${user} ${group} - -"
+ "d ${dataDir}/spool 0700 ${user} ${group} - -"
+ "d ${dataDir}/list_data 0700 ${user} ${group} - -"
+ "d ${dataDir}/arc 0700 ${user} ${group} - -"
+ "d ${dataDir}/bounce 0700 ${user} ${group} - -"
+ "f ${dataDir}/sympa_transport 0600 ${user} ${group} - -"
+
+ # force-copy static_content so it's up to date with package
+ # set permissions for wwsympa which needs write access (...)
+ "R ${dataDir}/static_content - - - - -"
+ "C ${dataDir}/static_content 0711 ${user} ${group} - ${pkg}/static_content"
+ "e ${dataDir}/static_content/* 0711 ${user} ${group} - -"
+
+ "d /run/sympa 0755 ${user} ${group} - -"
+ ]
+ ++ (flip concatMap fqdns (fqdn: [
+ "d ${dataDir}/etc/${fqdn} 0700 ${user} ${group} - -"
+ "d ${dataDir}/list_data/${fqdn} 0700 ${user} ${group} - -"
+ ]))
+ #++ (flip mapAttrsToList enabledFiles (k: v:
+ # "L+ ${dataDir}/${k} - - - - ${v.source}"
+ #))
+ ++ (concatLists (flip mapAttrsToList enabledFiles (k: v: [
+ # sympa doesn't handle symlinks well (e.g. fails to create locks)
+ # force-copy instead
+ "R ${dataDir}/${k} - - - - -"
+ "C ${dataDir}/${k} 0700 ${user} ${group} - ${v.source}"
+ ])));
+
+ systemd.services.sympa = {
+ description = "Sympa mailing list manager";
+
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network-online.target" ];
+ wants = sympaSubServices;
+ before = sympaSubServices;
+ serviceConfig = sympaServiceConfig "sympa_msg";
+
+ preStart = ''
+ umask 0077
+
+ cp -f ${mainConfig} ${dataDir}/etc/sympa.conf
+ ${optionalString (cfg.database.passwordFile != null) ''
+ chmod u+w ${dataDir}/etc/sympa.conf
+ echo -n "db_passwd " >> ${dataDir}/etc/sympa.conf
+ cat ${cfg.database.passwordFile} >> ${dataDir}/etc/sympa.conf
+ ''}
+
+ ${optionalString (cfg.mta.type == "postfix") ''
+ ${pkgs.postfix}/bin/postmap hash:${dataDir}/virtual.sympa
+ ${pkgs.postfix}/bin/postmap hash:${dataDir}/transport.sympa
+ ''}
+ ${pkg}/bin/sympa_newaliases.pl
+ ${pkg}/bin/sympa.pl --health_check
+ '';
+ };
+ systemd.services.sympa-archive = {
+ description = "Sympa mailing list manager (archiving)";
+ bindsTo = [ "sympa.service" ];
+ serviceConfig = sympaServiceConfig "archived";
+ };
+ systemd.services.sympa-bounce = {
+ description = "Sympa mailing list manager (bounce processing)";
+ bindsTo = [ "sympa.service" ];
+ serviceConfig = sympaServiceConfig "bounced";
+ };
+ systemd.services.sympa-bulk = {
+ description = "Sympa mailing list manager (message distribution)";
+ bindsTo = [ "sympa.service" ];
+ serviceConfig = sympaServiceConfig "bulk";
+ };
+ systemd.services.sympa-task = {
+ description = "Sympa mailing list manager (task management)";
+ bindsTo = [ "sympa.service" ];
+ serviceConfig = sympaServiceConfig "task_manager";
+ };
+
+ systemd.services.wwsympa = mkIf usingNginx {
+ wantedBy = [ "multi-user.target" ];
+ after = [ "sympa.service" ];
+ serviceConfig = {
+ Type = "forking";
+ PIDFile = "/run/sympa/wwsympa.pid";
+ Restart = "always";
+ ExecStart = ''${pkgs.spawn_fcgi}/bin/spawn-fcgi \
+ -u ${user} \
+ -g ${group} \
+ -U nginx \
+ -M 0600 \
+ -F ${toString cfg.web.fcgiProcs} \
+ -P /run/sympa/wwsympa.pid \
+ -s /run/sympa/wwsympa.socket \
+ -- ${pkg}/bin/wwsympa.fcgi
+ '';
+
+ } // commonServiceConfig;
+ };
+
+ services.nginx.enable = mkIf usingNginx true;
+ services.nginx.virtualHosts = mkIf usingNginx (let
+ vHosts = unique (remove null (mapAttrsToList (_k: v: v.webHost) cfg.domains));
+ hostLocations = host: map (v: v.webLocation) (filter (v: v.webHost == host) (attrValues cfg.domains));
+ httpsOpts = optionalAttrs cfg.web.https { forceSSL = mkDefault true; enableACME = mkDefault true; };
+ in
+ genAttrs vHosts (host: {
+ locations = genAttrs (hostLocations host) (loc: {
+ extraConfig = ''
+ include ${config.services.nginx.package}/conf/fastcgi_params;
+
+ fastcgi_pass unix:/run/sympa/wwsympa.socket;
+ fastcgi_split_path_info ^(${loc})(.*)$;
+
+ fastcgi_param PATH_INFO $fastcgi_path_info;
+ fastcgi_param SCRIPT_FILENAME ${pkg}/bin/wwsympa.fcgi;
+ '';
+ }) // {
+ "/static-sympa/".alias = "${dataDir}/static_content/";
+ };
+ } // httpsOpts));
+
+ services.postfix = mkIf (cfg.mta.type == "postfix") {
+ enable = true;
+ recipientDelimiter = "+";
+ config = {
+ virtual_alias_maps = [ "hash:${dataDir}/virtual.sympa" ];
+ virtual_mailbox_maps = [
+ "hash:${dataDir}/transport.sympa"
+ "hash:${dataDir}/sympa_transport"
+ "hash:${dataDir}/virtual.sympa"
+ ];
+ virtual_mailbox_domains = [ "hash:${dataDir}/transport.sympa" ];
+ transport_maps = [
+ "hash:${dataDir}/transport.sympa"
+ "hash:${dataDir}/sympa_transport"
+ ];
+ };
+ masterConfig = {
+ "sympa" = {
+ type = "unix";
+ privileged = true;
+ chroot = false;
+ command = "pipe";
+ args = [
+ "flags=hqRu"
+ "user=${user}"
+ "argv=${pkg}/bin/queue"
+ "\${nexthop}"
+ ];
+ };
+ "sympabounce" = {
+ type = "unix";
+ privileged = true;
+ chroot = false;
+ command = "pipe";
+ args = [
+ "flags=hqRu"
+ "user=${user}"
+ "argv=${pkg}/bin/bouncequeue"
+ "\${nexthop}"
+ ];
+ };
+ };
+ };
+
+ services.mysql = optionalAttrs mysqlLocal {
+ enable = true;
+ package = mkDefault pkgs.mariadb;
+ ensureDatabases = [ cfg.database.name ];
+ ensureUsers = [
+ { name = cfg.database.user;
+ ensurePermissions = { "${cfg.database.name}.*" = "ALL PRIVILEGES"; };
+ }
+ ];
+ };
+
+ services.postgresql = optionalAttrs pgsqlLocal {
+ enable = true;
+ ensureDatabases = [ cfg.database.name ];
+ ensureUsers = [
+ { name = cfg.database.user;
+ ensurePermissions = { "DATABASE ${cfg.database.name}" = "ALL PRIVILEGES"; };
+ }
+ ];
+ };
+
+ };
+
+ meta.maintainers = with maintainers; [ mmilata sorki ];
+}
diff --git a/nixpkgs/nixos/modules/services/misc/ankisyncd.nix b/nixpkgs/nixos/modules/services/misc/ankisyncd.nix
new file mode 100644
index 00000000000..5fc19649d3d
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/misc/ankisyncd.nix
@@ -0,0 +1,79 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.ankisyncd;
+
+ name = "ankisyncd";
+
+ stateDir = "/var/lib/${name}";
+
+ authDbPath = "${stateDir}/auth.db";
+
+ sessionDbPath = "${stateDir}/session.db";
+
+ configFile = pkgs.writeText "ankisyncd.conf" (lib.generators.toINI {} {
+ sync_app = {
+ host = cfg.host;
+ port = cfg.port;
+ data_root = stateDir;
+ auth_db_path = authDbPath;
+ session_db_path = sessionDbPath;
+
+ base_url = "/sync/";
+ base_media_url = "/msync/";
+ };
+ });
+in
+ {
+ options.services.ankisyncd = {
+ enable = mkEnableOption "ankisyncd";
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.ankisyncd;
+ defaultText = literalExample "pkgs.ankisyncd";
+ description = "The package to use for the ankisyncd command.";
+ };
+
+ host = mkOption {
+ type = types.str;
+ default = "localhost";
+ description = "ankisyncd host";
+ };
+
+ port = mkOption {
+ type = types.int;
+ default = 27701;
+ description = "ankisyncd port";
+ };
+
+ openFirewall = mkOption {
+ default = false;
+ type = types.bool;
+ description = "Whether to open the firewall for the specified port.";
+ };
+ };
+
+ config = mkIf cfg.enable {
+ networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ];
+
+ environment.etc."ankisyncd/ankisyncd.conf".source = configFile;
+
+ systemd.services.ankisyncd = {
+ description = "ankisyncd - Anki sync server";
+ after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ path = [ cfg.package ];
+
+ serviceConfig = {
+ Type = "simple";
+ DynamicUser = true;
+ StateDirectory = name;
+ ExecStart = "${cfg.package}/bin/ankisyncd";
+ Restart = "always";
+ };
+ };
+ };
+ }
diff --git a/nixpkgs/nixos/modules/services/misc/autorandr.nix b/nixpkgs/nixos/modules/services/misc/autorandr.nix
index 4708e16e2a6..cf7fb5f78d3 100644
--- a/nixpkgs/nixos/modules/services/misc/autorandr.nix
+++ b/nixpkgs/nixos/modules/services/misc/autorandr.nix
@@ -48,5 +48,5 @@ in {
};
- meta.maintainers = with maintainers; [ gnidorah ma27 ];
+ meta.maintainers = with maintainers; [ gnidorah ];
}
diff --git a/nixpkgs/nixos/modules/services/misc/disnix.nix b/nixpkgs/nixos/modules/services/misc/disnix.nix
index c21cb2afc3c..b7b6eb7cd66 100644
--- a/nixpkgs/nixos/modules/services/misc/disnix.nix
+++ b/nixpkgs/nixos/modules/services/misc/disnix.nix
@@ -61,10 +61,7 @@ in
++ optional cfg.useWebServiceInterface "${pkgs.dbus_java}/share/java/dbus.jar";
services.tomcat.webapps = optional cfg.useWebServiceInterface pkgs.DisnixWebService;
- users.groups = singleton
- { name = "disnix";
- gid = config.ids.gids.disnix;
- };
+ users.groups.disnix.gid = config.ids.gids.disnix;
systemd.services = {
disnix = mkIf cfg.enableMultiUser {
diff --git a/nixpkgs/nixos/modules/services/misc/folding-at-home.nix b/nixpkgs/nixos/modules/services/misc/folding-at-home.nix
deleted file mode 100644
index fd2ea3948f6..00000000000
--- a/nixpkgs/nixos/modules/services/misc/folding-at-home.nix
+++ /dev/null
@@ -1,67 +0,0 @@
-{ config, lib, pkgs, ... }:
-with lib;
-let
- stateDir = "/var/lib/foldingathome";
- cfg = config.services.foldingAtHome;
- fahUser = "foldingathome";
-in {
-
- ###### interface
-
- options = {
-
- services.foldingAtHome = {
-
- enable = mkOption {
- default = false;
- description = ''
- Whether to enable the Folding@Home to use idle CPU time.
- '';
- };
-
- nickname = mkOption {
- default = "Anonymous";
- description = ''
- A unique handle for statistics.
- '';
- };
-
- config = mkOption {
- default = "";
- description = ''
- Extra configuration. Contents will be added verbatim to the
- configuration file.
- '';
- };
-
- };
-
- };
-
- ###### implementation
-
- config = mkIf cfg.enable {
-
- users.users.${fahUser} =
- { uid = config.ids.uids.foldingathome;
- description = "Folding@Home user";
- home = stateDir;
- };
-
- systemd.services.foldingathome = {
- after = [ "network.target" ];
- wantedBy = [ "multi-user.target" ];
- preStart = ''
- mkdir -m 0755 -p ${stateDir}
- chown ${fahUser} ${stateDir}
- cp -f ${pkgs.writeText "client.cfg" cfg.config} ${stateDir}/client.cfg
- '';
- script = "${pkgs.su}/bin/su -s ${pkgs.runtimeShell} ${fahUser} -c 'cd ${stateDir}; ${pkgs.foldingathome}/bin/fah6'";
- };
-
- services.foldingAtHome.config = ''
- [settings]
- username=${cfg.nickname}
- '';
- };
-}
diff --git a/nixpkgs/nixos/modules/services/misc/home-assistant.nix b/nixpkgs/nixos/modules/services/misc/home-assistant.nix
index d63f38e93b8..86033d02bf3 100644
--- a/nixpkgs/nixos/modules/services/misc/home-assistant.nix
+++ b/nixpkgs/nixos/modules/services/misc/home-assistant.nix
@@ -96,7 +96,20 @@ in {
config = mkOption {
default = null;
- type = with types; nullOr attrs;
+ # Migrate to new option types later: https://github.com/NixOS/nixpkgs/pull/75584
+ type = with lib.types; let
+ valueType = nullOr (oneOf [
+ bool
+ int
+ float
+ str
+ (lazyAttrsOf valueType)
+ (listOf valueType)
+ ]) // {
+ description = "Yaml value";
+ emptyValue.value = {};
+ };
+ in valueType;
example = literalExample ''
{
homeassistant = {
diff --git a/nixpkgs/nixos/modules/services/misc/matrix-synapse.nix b/nixpkgs/nixos/modules/services/misc/matrix-synapse.nix
index 750f4a292fb..d02fa13bb99 100644
--- a/nixpkgs/nixos/modules/services/misc/matrix-synapse.nix
+++ b/nixpkgs/nixos/modules/services/misc/matrix-synapse.nix
@@ -111,6 +111,9 @@ app_service_config_files: ${builtins.toJSON cfg.app_service_config_files}
${cfg.extraConfig}
'';
+
+ hasLocalPostgresDB = let args = cfg.database_args; in
+ usePostgresql && (!(args ? host) || (elem args.host [ "localhost" "127.0.0.1" "::1" ]));
in {
options = {
services.matrix-synapse = {
@@ -354,13 +357,6 @@ in {
The database engine name. Can be sqlite or psycopg2.
'';
};
- create_local_database = mkOption {
- type = types.bool;
- default = true;
- description = ''
- Whether to create a local database automatically.
- '';
- };
database_name = mkOption {
type = types.str;
default = "matrix-synapse";
@@ -657,6 +653,25 @@ in {
};
config = mkIf cfg.enable {
+ assertions = [
+ { assertion = hasLocalPostgresDB -> config.services.postgresql.enable;
+ message = ''
+ Cannot deploy matrix-synapse with a configuration for a local postgresql database
+ and a missing postgresql service. Since 20.03 it's mandatory to manually configure the
+ database (please read the thread in https://github.com/NixOS/nixpkgs/pull/80447 for
+ further reference).
+
+ If you
+ - try to deploy a fresh synapse, you need to configure the database yourself. An example
+ for this can be found in <nixpkgs/nixos/tests/matrix-synapse.nix>
+ - update your existing matrix-synapse instance, you simply need to add `services.postgresql.enable = true`
+ to your configuration.
+
+ For further information about this update, please read the release-notes of 20.03 carefully.
+ '';
+ }
+ ];
+
users.users.matrix-synapse = {
group = "matrix-synapse";
home = cfg.dataDir;
@@ -669,18 +684,9 @@ in {
gid = config.ids.gids.matrix-synapse;
};
- services.postgresql = mkIf (usePostgresql && cfg.create_local_database) {
- enable = mkDefault true;
- ensureDatabases = [ cfg.database_name ];
- ensureUsers = [{
- name = cfg.database_user;
- ensurePermissions = { "DATABASE \"${cfg.database_name}\"" = "ALL PRIVILEGES"; };
- }];
- };
-
systemd.services.matrix-synapse = {
description = "Synapse Matrix homeserver";
- after = [ "network.target" ] ++ lib.optional config.services.postgresql.enable "postgresql.service" ;
+ after = [ "network.target" ] ++ optional hasLocalPostgresDB "postgresql.service";
wantedBy = [ "multi-user.target" ];
preStart = ''
${cfg.package}/bin/homeserver \
@@ -709,6 +715,12 @@ in {
The `trusted_third_party_id_servers` option as been removed in `matrix-synapse` v1.4.0
as the behavior is now obsolete.
'')
+ (mkRemovedOptionModule [ "services" "matrix-synapse" "create_local_database" ] ''
+ Database configuration must be done manually. An exemplary setup is demonstrated in
+ <nixpkgs/nixos/tests/matrix-synapse.nix>
+ '')
];
+ meta.doc = ./matrix-synapse.xml;
+
}
diff --git a/nixpkgs/nixos/doc/manual/configuration/matrix.xml b/nixpkgs/nixos/modules/services/misc/matrix-synapse.xml
index ef8d5cbda88..053a3b2a563 100644
--- a/nixpkgs/nixos/doc/manual/configuration/matrix.xml
+++ b/nixpkgs/nixos/modules/services/misc/matrix-synapse.xml
@@ -40,26 +40,35 @@ let
in join config.networking.hostName config.networking.domain;
in {
networking = {
- hostName = "myhostname";
- domain = "example.org";
+ <link linkend="opt-networking.hostName">hostName</link> = "myhostname";
+ <link linkend="opt-networking.domain">domain</link> = "example.org";
};
- networking.firewall.allowedTCPPorts = [ 80 443 ];
+ <link linkend="opt-networking.firewall.allowedTCPPorts">networking.firewall.allowedTCPPorts</link> = [ 80 443 ];
+
+ <link linkend="opt-services.postgresql.enable">services.postgresql.enable</link> = true;
+ <link linkend="opt-services.postgresql.initialScript">services.postgresql.initialScript</link> = ''
+ CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
+ CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
+ TEMPLATE template0
+ LC_COLLATE = "C"
+ LC_CTYPE = "C";
+ '';
services.nginx = {
- enable = true;
+ <link linkend="opt-services.nginx.enable">enable</link> = true;
# only recommendedProxySettings and recommendedGzipSettings are strictly required,
# but the rest make sense as well
- recommendedTlsSettings = true;
- recommendedOptimisation = true;
- recommendedGzipSettings = true;
- recommendedProxySettings = true;
+ <link linkend="opt-services.nginx.recommendedTlsSettings">recommendedTlsSettings</link> = true;
+ <link linkend="opt-services.nginx.recommendedOptimisation">recommendedOptimisation</link> = true;
+ <link linkend="opt-services.nginx.recommendedGzipSettings">recommendedGzipSettings</link> = true;
+ <link linkend="opt-services.nginx.recommendedProxySettings">recommendedProxySettings</link> = true;
- virtualHosts = {
+ <link linkend="opt-services.nginx.virtualHosts">virtualHosts</link> = {
# This host section can be placed on a different host than the rest,
# i.e. to delegate from the host being accessible as ${config.networking.domain}
# to another host actually running the Matrix homeserver.
"${config.networking.domain}" = {
- locations."= /.well-known/matrix/server".extraConfig =
+ <link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.extraConfig">locations."= /.well-known/matrix/server".extraConfig</link> =
let
# use 443 instead of the default 8448 port to unite
# the client-server and server-server port for simplicity
@@ -68,7 +77,7 @@ in {
add_header Content-Type application/json;
return 200 '${builtins.toJSON server}';
'';
- locations."= /.well-known/matrix/client".extraConfig =
+ <link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.extraConfig">locations."= /.well-known/matrix/client".extraConfig</link> =
let
client = {
"m.homeserver" = { "base_url" = "https://${fqdn}"; };
@@ -84,34 +93,37 @@ in {
# Reverse proxy for Matrix client-server and server-server communication
${fqdn} = {
- enableACME = true;
- forceSSL = true;
+ <link linkend="opt-services.nginx.virtualHosts._name_.enableACME">enableACME</link> = true;
+ <link linkend="opt-services.nginx.virtualHosts._name_.forceSSL">forceSSL</link> = true;
# Or do a redirect instead of the 404, or whatever is appropriate for you.
# But do not put a Matrix Web client here! See the Riot Web section below.
- locations."/".extraConfig = ''
+ <link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.extraConfig">locations."/".extraConfig</link> = ''
return 404;
'';
# forward all Matrix API calls to the synapse Matrix homeserver
locations."/_matrix" = {
- proxyPass = "http://[::1]:8008"; # without a trailing /
+ <link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.proxyPass">proxyPass</link> = "http://[::1]:8008"; # without a trailing /
};
};
};
};
services.matrix-synapse = {
- enable = true;
- server_name = config.networking.domain;
- listeners = [
+ <link linkend="opt-services.matrix-synapse.enable">enable</link> = true;
+ <link linkend="opt-services.matrix-synapse.server_name">server_name</link> = config.networking.domain;
+ <link linkend="opt-services.matrix-synapse.listeners">listeners</link> = [
{
- port = 8008;
- bind_address = "::1";
- type = "http";
- tls = false;
- x_forwarded = true;
- resources = [
- { names = [ "client" "federation" ]; compress = false; }
+ <link linkend="opt-services.matrix-synapse.listeners._.port">port</link> = 8008;
+ <link linkend="opt-services.matrix-synapse.listeners._.bind_address">bind_address</link> = "::1";
+ <link linkend="opt-services.matrix-synapse.listeners._.type">type</link> = "http";
+ <link linkend="opt-services.matrix-synapse.listeners._.tls">tls</link> = false;
+ <link linkend="opt-services.matrix-synapse.listeners._.x_forwarded">x_forwarded</link> = true;
+ <link linkend="opt-services.matrix-synapse.listeners._.resources">resources</link> = [
+ {
+ <link linkend="opt-services.matrix-synapse.listeners._.resources._.names">names</link> = [ "client" "federation" ];
+ <link linkend="opt-services.matrix-synapse.listeners._.resources._.compress">compress</link> = false;
+ }
];
}
];
@@ -135,10 +147,10 @@ in {
<para>
If you want to run a server with public registration by anybody, you can
- then enable <option>services.matrix-synapse.enable_registration =
- true;</option>. Otherwise, or you can generate a registration secret with
+ then enable <literal><link linkend="opt-services.matrix-synapse.enable_registration">services.matrix-synapse.enable_registration</link> =
+ true;</literal>. Otherwise, or you can generate a registration secret with
<command>pwgen -s 64 1</command> and set it with
- <option>services.matrix-synapse.registration_shared_secret</option>. To
+ <option><link linkend="opt-services.matrix-synapse.registration_shared_secret">services.matrix-synapse.registration_shared_secret</link></option>. To
create a new user or admin, run the following after you have set the secret
and have rebuilt NixOS:
<screen>
@@ -154,8 +166,8 @@ Success!
<literal>@your-username:example.org</literal>. Note that the registration
secret ends up in the nix store and therefore is world-readable by any user
on your machine, so it makes sense to only temporarily activate the
- <option>registration_shared_secret</option> option until a better solution
- for NixOS is in place.
+ <link linkend="opt-services.matrix-synapse.registration_shared_secret">registration_shared_secret</link>
+ option until a better solution for NixOS is in place.
</para>
</section>
<section xml:id="module-services-matrix-riot-web">
@@ -177,15 +189,24 @@ Success!
Matrix Now!</link> for a list of existing clients and their supported
featureset.
<programlisting>
-services.nginx.virtualHosts."riot.${fqdn}" = {
- enableACME = true;
- forceSSL = true;
- serverAliases = [
- "riot.${config.networking.domain}"
- ];
+{
+ services.nginx.virtualHosts."riot.${fqdn}" = {
+ <link linkend="opt-services.nginx.virtualHosts._name_.enableACME">enableACME</link> = true;
+ <link linkend="opt-services.nginx.virtualHosts._name_.forceSSL">forceSSL</link> = true;
+ <link linkend="opt-services.nginx.virtualHosts._name_.serverAliases">serverAliases</link> = [
+ "riot.${config.networking.domain}"
+ ];
- root = pkgs.riot-web;
-};
+ <link linkend="opt-services.nginx.virtualHosts._name_.root">root</link> = pkgs.riot-web.override {
+ conf = {
+ default_server_config."m.homeserver" = {
+ "base_url" = "${config.networking.domain}";
+ "server_name" = "${fqdn}";
+ };
+ };
+ };
+ };
+}
</programlisting>
</para>
diff --git a/nixpkgs/nixos/modules/services/misc/parsoid.nix b/nixpkgs/nixos/modules/services/misc/parsoid.nix
index 61626e78f8b..09b7f977bfb 100644
--- a/nixpkgs/nixos/modules/services/misc/parsoid.nix
+++ b/nixpkgs/nixos/modules/services/misc/parsoid.nix
@@ -6,7 +6,7 @@ let
cfg = config.services.parsoid;
- parsoid = pkgs.nodePackages."parsoid-git://github.com/abbradar/parsoid#stable";
+ parsoid = pkgs.nodePackages.parsoid;
confTree = {
worker_heartbeat_timeout = 300000;
@@ -98,8 +98,29 @@ in
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
- User = "nobody";
ExecStart = "${parsoid}/lib/node_modules/parsoid/bin/server.js -c ${confFile} -n ${toString cfg.workers}";
+
+ DynamicUser = true;
+ User = "parsoid";
+ Group = "parsoid";
+
+ CapabilityBoundingSet = "";
+ NoNewPrivileges = true;
+ ProtectSystem = "strict";
+ ProtectHome = true;
+ PrivateTmp = true;
+ PrivateDevices = true;
+ ProtectHostname = true;
+ ProtectKernelTunables = true;
+ ProtectKernelModules = true;
+ ProtectControlGroups = true;
+ RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+ RestrictNamespaces = true;
+ LockPersonality = true;
+ #MemoryDenyWriteExecute = true;
+ RestrictRealtime = true;
+ RestrictSUIDSGID = true;
+ RemoveIPC = true;
};
};
diff --git a/nixpkgs/nixos/modules/services/misc/sssd.nix b/nixpkgs/nixos/modules/services/misc/sssd.nix
index 6b64045dde8..36008d25741 100644
--- a/nixpkgs/nixos/modules/services/misc/sssd.nix
+++ b/nixpkgs/nixos/modules/services/misc/sssd.nix
@@ -88,9 +88,7 @@ in {
exec ${pkgs.sssd}/bin/sss_ssh_authorizedkeys "$@"
'';
};
- services.openssh.extraConfig = ''
- AuthorizedKeysCommand /etc/ssh/authorized_keys_command
- AuthorizedKeysCommandUser nobody
- '';
+ services.openssh.authorizedKeysCommand = "/etc/ssh/authorized_keys_command";
+ services.openssh.authorizedKeysCommandUser = "nobody";
})];
}
diff --git a/nixpkgs/nixos/modules/services/misc/zoneminder.nix b/nixpkgs/nixos/modules/services/misc/zoneminder.nix
index d7f7324580c..d5b3537068d 100644
--- a/nixpkgs/nixos/modules/services/misc/zoneminder.nix
+++ b/nixpkgs/nixos/modules/services/misc/zoneminder.nix
@@ -77,6 +77,8 @@ in {
`config.services.zoneminder.database.createLocally` to true. Otherwise,
when set to `false` (the default), you will have to create the database
and database user as well as populate the database yourself.
+ Additionally, you will need to run `zmupdate.pl` yourself when
+ upgrading to a newer version.
'';
webserver = mkOption {
@@ -330,6 +332,8 @@ in {
${config.services.mysql.package}/bin/mysql < ${pkg}/share/zoneminder/db/zm_create.sql
touch "/var/lib/${dirName}/db-created"
fi
+
+ ${zoneminder}/bin/zmupdate.pl -nointeractive
'';
serviceConfig = {
User = user;
diff --git a/nixpkgs/nixos/modules/services/monitoring/cadvisor.nix b/nixpkgs/nixos/modules/services/monitoring/cadvisor.nix
index 695a8c42e85..655a6934a26 100644
--- a/nixpkgs/nixos/modules/services/monitoring/cadvisor.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/cadvisor.nix
@@ -135,7 +135,6 @@ in {
serviceConfig.TimeoutStartSec=300;
};
- virtualisation.docker.enable = mkDefault true;
})
];
}
diff --git a/nixpkgs/nixos/modules/services/monitoring/heapster.nix b/nixpkgs/nixos/modules/services/monitoring/heapster.nix
index 585632943fd..0a9dfa12eaa 100644
--- a/nixpkgs/nixos/modules/services/monitoring/heapster.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/heapster.nix
@@ -49,7 +49,7 @@ in {
};
};
- users.users.heapsterrs = {
+ users.users.heapster = {
uid = config.ids.uids.heapster;
description = "Heapster user";
};
diff --git a/nixpkgs/nixos/modules/services/monitoring/nagios.nix b/nixpkgs/nixos/modules/services/monitoring/nagios.nix
index 3ca79dddaf5..9ac6869068f 100644
--- a/nixpkgs/nixos/modules/services/monitoring/nagios.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/nagios.nix
@@ -154,7 +154,7 @@ in
};
virtualHost = mkOption {
- type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix);
+ type = types.submodule (import ../web-servers/apache-httpd/vhost-options.nix);
example = literalExample ''
{ hostName = "example.org";
adminAddr = "webmaster@example.org";
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix
index b67f697ca0d..6b1a4be44d1 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/default.nix
@@ -9,12 +9,13 @@ let
# a wrapper that verifies that the configuration is valid
promtoolCheck = what: name: file:
- pkgs.runCommand
- "${name}-${replaceStrings [" "] [""] what}-checked"
- { buildInputs = [ cfg.package ]; } ''
- ln -s ${file} $out
- promtool ${what} $out
- '';
+ if cfg.checkConfig then
+ pkgs.runCommand
+ "${name}-${replaceStrings [" "] [""] what}-checked"
+ { buildInputs = [ cfg.package ]; } ''
+ ln -s ${file} $out
+ promtool ${what} $out
+ '' else file;
# Pretty-print JSON to a file
writePrettyJSON = name: x:
@@ -601,6 +602,20 @@ in {
if Prometheus is served via a reverse proxy).
'';
};
+
+ checkConfig = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Check configuration with <literal>promtool
+ check</literal>. The call to <literal>promtool</literal> is
+ subject to sandboxing by Nix. When credentials are stored in
+ external files (<literal>password_file</literal>,
+ <literal>bearer_token_file</literal>, etc), they will not be
+ visible to <literal>promtool</literal> and it will report
+ errors, despite a correct configuration.
+ '';
+ };
};
config = mkIf cfg.enable {
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix
index 36ebffa4463..f9ad1457fc8 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters.nix
@@ -29,6 +29,7 @@ let
"fritzbox"
"json"
"mail"
+ "mikrotik"
"minio"
"nextcloud"
"nginx"
@@ -197,13 +198,25 @@ in
config = mkMerge ([{
assertions = [ {
- assertion = (cfg.snmp.configurationPath == null) != (cfg.snmp.configuration == null);
+ assertion = cfg.snmp.enable -> (
+ (cfg.snmp.configurationPath == null) != (cfg.snmp.configuration == null)
+ );
message = ''
Please ensure you have either `services.prometheus.exporters.snmp.configuration'
or `services.prometheus.exporters.snmp.configurationPath' set!
'';
} {
- assertion = (cfg.mail.configFile == null) != (cfg.mail.configuration == {});
+ assertion = cfg.mikrotik.enable -> (
+ (cfg.mikrotik.configFile == null) != (cfg.mikrotik.configuration == null)
+ );
+ message = ''
+ Please specify either `services.prometheus.exporters.mikrotik.configuration'
+ or `services.prometheus.exporters.mikrotik.configFile'.
+ '';
+ } {
+ assertion = cfg.mail.enable -> (
+ (cfg.mail.configFile == null) != (cfg.mail.configuration == null)
+ );
message = ''
Please specify either 'services.prometheus.exporters.mail.configuration'
or 'services.prometheus.exporters.mail.configFile'.
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix
index 8a90afa9984..fe8d905da3f 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix
@@ -61,7 +61,7 @@ in {
ExecStart = ''
${pkgs.prometheus-blackbox-exporter}/bin/blackbox_exporter \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
- --config.file ${adjustedConfigFile} \
+ --config.file ${escapeShellArg adjustedConfigFile} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix
index 1cc34641809..97210463027 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix
@@ -66,7 +66,7 @@ in
serviceConfig = {
ExecStart = ''
${pkgs.prometheus-collectd-exporter}/bin/collectd_exporter \
- -log.format ${cfg.logFormat} \
+ -log.format ${escapeShellArg cfg.logFormat} \
-log.level ${cfg.logLevel} \
-web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
${collectSettingsArgs} \
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix
index e9fa26cb1f5..68afba21d64 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix
@@ -30,7 +30,7 @@ in
${pkgs.prometheus-dnsmasq-exporter}/bin/dnsmasq_exporter \
--listen ${cfg.listenAddress}:${toString cfg.port} \
--dnsmasq ${cfg.dnsmasqListenAddress} \
- --leases_path ${cfg.leasesPath} \
+ --leases_path ${escapeShellArg cfg.leasesPath} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix
index a01074758ff..aba3533e439 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix
@@ -64,7 +64,7 @@ in
${pkgs.prometheus-dovecot-exporter}/bin/dovecot_exporter \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
--web.telemetry-path ${cfg.telemetryPath} \
- --dovecot.socket-path ${cfg.socketPath} \
+ --dovecot.socket-path ${escapeShellArg cfg.socketPath} \
--dovecot.scopes ${concatStringsSep "," cfg.scopes} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/json.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/json.nix
index 82a55bafc98..bd0026b55f7 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/json.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/json.nix
@@ -27,7 +27,7 @@ in
ExecStart = ''
${pkgs.prometheus-json-exporter}/bin/prometheus-json-exporter \
--port ${toString cfg.port} \
- ${cfg.url} ${cfg.configFile} \
+ ${cfg.url} ${escapeShellArg cfg.configFile} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mail.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mail.nix
index 7d8c6fb6140..18c5c4dd162 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mail.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mail.nix
@@ -90,7 +90,7 @@ let
Timeout until mails are considered "didn't make it".
'';
};
- disableFileDelition = mkOption {
+ disableFileDeletion = mkOption {
type = types.bool;
default = false;
description = ''
@@ -127,8 +127,8 @@ in
'';
};
configuration = mkOption {
- type = types.submodule exporterOptions;
- default = {};
+ type = types.nullOr (types.submodule exporterOptions);
+ default = null;
description = ''
Specify the mailexporter configuration file to use.
'';
@@ -147,8 +147,9 @@ in
ExecStart = ''
${pkgs.prometheus-mail-exporter}/bin/mailexporter \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
+ --web.telemetry-path ${cfg.telemetryPath} \
--config.file ${
- if cfg.configuration != {} then configurationFile else cfg.configFile
+ if cfg.configuration != null then configurationFile else (escapeShellArg cfg.configFile)
} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mikrotik.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mikrotik.nix
new file mode 100644
index 00000000000..62c2cc56847
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/mikrotik.nix
@@ -0,0 +1,66 @@
+{ config, lib, pkgs, options }:
+
+with lib;
+
+let
+ cfg = config.services.prometheus.exporters.mikrotik;
+in
+{
+ port = 9436;
+ extraOpts = {
+ configFile = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ description = ''
+ Path to a mikrotik exporter configuration file. Mutually exclusive with
+ <option>configuration</option> option.
+ '';
+ example = literalExample "./mikrotik.yml";
+ };
+
+ configuration = mkOption {
+ type = types.nullOr types.attrs;
+ default = null;
+ description = ''
+ Mikrotik exporter configuration as nix attribute set. Mutually exclusive with
+ <option>configFile</option> option.
+
+ See <link xlink:href="https://github.com/nshttpd/mikrotik-exporter/blob/master/README.md"/>
+ for the description of the configuration file format.
+ '';
+ example = literalExample ''
+ {
+ devices = [
+ {
+ name = "my_router";
+ address = "10.10.0.1";
+ user = "prometheus";
+ password = "changeme";
+ }
+ ];
+ features = {
+ bgp = true;
+ dhcp = true;
+ routes = true;
+ optics = true;
+ };
+ }
+ '';
+ };
+ };
+ serviceOpts = let
+ configFile = if cfg.configFile != null
+ then cfg.configFile
+ else "${pkgs.writeText "mikrotik-exporter.yml" (builtins.toJSON cfg.configuration)}";
+ in {
+ serviceConfig = {
+ # -port is misleading name, it actually accepts address too
+ ExecStart = ''
+ ${pkgs.prometheus-mikrotik-exporter}/bin/mikrotik-exporter \
+ -config-file=${escapeShellArg configFile} \
+ -port=${cfg.listenAddress}:${toString cfg.port} \
+ ${concatStringsSep " \\\n " cfg.extraFlags}
+ '';
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/minio.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/minio.nix
index ab3e3d7d5d5..d6dd62f871b 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/minio.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/minio.nix
@@ -54,8 +54,8 @@ in
${pkgs.prometheus-minio-exporter}/bin/minio-exporter \
-web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
-minio.server ${cfg.minioAddress} \
- -minio.access-key ${cfg.minioAccessKey} \
- -minio.access-secret ${cfg.minioAccessSecret} \
+ -minio.access-key ${escapeShellArg cfg.minioAccessKey} \
+ -minio.access-secret ${escapeShellArg cfg.minioAccessSecret} \
${optionalString cfg.minioBucketStats "-minio.bucket-stats"} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix
index 5f9a52053f7..aee6bd5e66c 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix
@@ -50,7 +50,7 @@ in
-u ${cfg.username} \
-t ${cfg.timeout} \
-l ${cfg.url} \
- -p @${cfg.passwordFile} \
+ -p ${escapeShellArg "@${cfg.passwordFile}"} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix
index ba852fea433..56cddfc55b7 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/nginx.nix
@@ -30,7 +30,17 @@ in
Whether to perform certificate verification for https.
'';
};
-
+ constLabels = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ example = [
+ "label1=value1"
+ "label2=value2"
+ ];
+ description = ''
+ A list of constant labels that will be used in every metric.
+ '';
+ };
};
serviceOpts = {
serviceConfig = {
@@ -40,6 +50,7 @@ in
--nginx.ssl-verify ${toString cfg.sslVerify} \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
--web.telemetry-path ${cfg.telemetryPath} \
+ --prometheus.const-labels ${concatStringsSep "," cfg.constLabels} \
${concatStringsSep " \\\n " cfg.extraFlags}
'';
};
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix
index d50564717ea..3b6ef1631f8 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix
@@ -67,15 +67,15 @@ in
${pkgs.prometheus-postfix-exporter}/bin/postfix_exporter \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
--web.telemetry-path ${cfg.telemetryPath} \
- --postfix.showq_path ${cfg.showqPath} \
+ --postfix.showq_path ${escapeShellArg cfg.showqPath} \
${concatStringsSep " \\\n " (cfg.extraFlags
++ optional cfg.systemd.enable "--systemd.enable"
++ optional cfg.systemd.enable (if cfg.systemd.slice != null
then "--systemd.slice ${cfg.systemd.slice}"
else "--systemd.unit ${cfg.systemd.unit}")
++ optional (cfg.systemd.enable && (cfg.systemd.journalPath != null))
- "--systemd.journal_path ${cfg.systemd.journalPath}"
- ++ optional (!cfg.systemd.enable) "--postfix.logfile_path ${cfg.logfilePath}")}
+ "--systemd.journal_path ${escapeShellArg cfg.systemd.journalPath}"
+ ++ optional (!cfg.systemd.enable) "--postfix.logfile_path ${escapeShellArg cfg.logfilePath}")}
'';
};
};
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix
index fe7ae8a8ac9..045e48a3d0f 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix
@@ -19,7 +19,7 @@ in
configuration = mkOption {
type = types.nullOr types.attrs;
- default = {};
+ default = null;
description = ''
Snmp exporter configuration as nix attribute set. Mutually exclusive with 'configurationPath' option.
'';
@@ -36,15 +36,15 @@ in
};
logFormat = mkOption {
- type = types.str;
- default = "logger:stderr";
+ type = types.enum ["logfmt" "json"];
+ default = "logfmt";
description = ''
- Set the log target and format.
+ Output format of log messages.
'';
};
logLevel = mkOption {
- type = types.enum ["debug" "info" "warn" "error" "fatal"];
+ type = types.enum ["debug" "info" "warn" "error"];
default = "info";
description = ''
Only log messages with the given severity or above.
@@ -54,13 +54,13 @@ in
serviceOpts = let
configFile = if cfg.configurationPath != null
then cfg.configurationPath
- else "${pkgs.writeText "snmp-eporter-conf.yml" (builtins.toJSON cfg.configuration)}";
+ else "${pkgs.writeText "snmp-exporter-conf.yml" (builtins.toJSON cfg.configuration)}";
in {
serviceConfig = {
ExecStart = ''
${pkgs.prometheus-snmp-exporter.bin}/bin/snmp_exporter \
- --config.file=${configFile} \
- --log.format=${cfg.logFormat} \
+ --config.file=${escapeShellArg configFile} \
+ --log.format=${escapeShellArg cfg.logFormat} \
--log.level=${cfg.logLevel} \
--web.listen-address=${cfg.listenAddress}:${toString cfg.port} \
${concatStringsSep " \\\n " cfg.extraFlags}
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix
index 9aa0f1b85aa..8d0e8764001 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix
@@ -55,8 +55,8 @@ in
${pkgs.prometheus-unifi-exporter}/bin/unifi_exporter \
-telemetry.addr ${cfg.listenAddress}:${toString cfg.port} \
-unifi.addr ${cfg.unifiAddress} \
- -unifi.username ${cfg.unifiUsername} \
- -unifi.password ${cfg.unifiPassword} \
+ -unifi.username ${escapeShellArg cfg.unifiUsername} \
+ -unifi.password ${escapeShellArg cfg.unifiPassword} \
-unifi.timeout ${cfg.unifiTimeout} \
${optionalString cfg.unifiInsecure "-unifi.insecure" } \
${concatStringsSep " \\\n " cfg.extraFlags}
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix
index 12153fa021e..5b5a6e18fcd 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix
@@ -74,10 +74,10 @@ in
${pkgs.prometheus-varnish-exporter}/bin/prometheus_varnish_exporter \
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
--web.telemetry-path ${cfg.telemetryPath} \
- --varnishstat-path ${cfg.varnishStatPath} \
+ --varnishstat-path ${escapeShellArg cfg.varnishStatPath} \
${concatStringsSep " \\\n " (cfg.extraFlags
++ optional (cfg.healthPath != null) "--web.health-path ${cfg.healthPath}"
- ++ optional (cfg.instance != null) "-n ${cfg.instance}"
+ ++ optional (cfg.instance != null) "-n ${escapeShellArg cfg.instance}"
++ optional cfg.noExit "--no-exit"
++ optional cfg.withGoMetrics "--with-go-metrics"
++ optional cfg.verbose "--verbose"
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix
index 374f83a2939..04421fc2d25 100644
--- a/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix
@@ -59,7 +59,7 @@ in {
${optionalString cfg.verbose "-v"} \
${optionalString cfg.singleSubnetPerField "-s"} \
${optionalString cfg.withRemoteIp "-r"} \
- ${optionalString (cfg.wireguardConfig != null) "-n ${cfg.wireguardConfig}"}
+ ${optionalString (cfg.wireguardConfig != null) "-n ${escapeShellArg cfg.wireguardConfig}"}
'';
};
};
diff --git a/nixpkgs/nixos/modules/services/monitoring/prometheus/xmpp-alerts.nix b/nixpkgs/nixos/modules/services/monitoring/prometheus/xmpp-alerts.nix
new file mode 100644
index 00000000000..44b15cb2034
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/monitoring/prometheus/xmpp-alerts.nix
@@ -0,0 +1,47 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.prometheus.xmpp-alerts;
+
+ configFile = pkgs.writeText "prometheus-xmpp-alerts.yml" (builtins.toJSON cfg.configuration);
+
+in
+
+{
+ options.services.prometheus.xmpp-alerts = {
+
+ enable = mkEnableOption "XMPP Web hook service for Alertmanager";
+
+ configuration = mkOption {
+ type = types.attrs;
+ description = "Configuration as attribute set which will be converted to YAML";
+ };
+
+ };
+
+ config = mkIf cfg.enable {
+ systemd.services.prometheus-xmpp-alerts = {
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network-online.target" ];
+ wants = [ "network-online.target" ];
+ serviceConfig = {
+ ExecStart = "${pkgs.prometheus-xmpp-alerts}/bin/prometheus-xmpp-alerts --config ${configFile}";
+ Restart = "on-failure";
+ DynamicUser = true;
+ PrivateTmp = true;
+ PrivateDevices = true;
+ ProtectHome = true;
+ ProtectSystem = "strict";
+ ProtectKernelTunables = true;
+ ProtectKernelModules = true;
+ ProtectControlGroups = true;
+ NoNewPrivileges = true;
+ SystemCallArchitectures = "native";
+ RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+ SystemCallFilter = [ "@system-service" ];
+ };
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/monitoring/statsd.nix b/nixpkgs/nixos/modules/services/monitoring/statsd.nix
index 17836e95a6f..30b2916a992 100644
--- a/nixpkgs/nixos/modules/services/monitoring/statsd.nix
+++ b/nixpkgs/nixos/modules/services/monitoring/statsd.nix
@@ -125,7 +125,7 @@ in
message = "Only builtin backends (graphite, console, repeater) or backends enumerated in `pkgs.nodePackages` are allowed!";
}) cfg.backends;
- users.use.statsdrs = {
+ users.users.statsd = {
uid = config.ids.uids.statsd;
description = "Statsd daemon user";
};
diff --git a/nixpkgs/nixos/modules/services/networking/cjdns.nix b/nixpkgs/nixos/modules/services/networking/cjdns.nix
index 3fb85b16cbe..5f8ac96b229 100644
--- a/nixpkgs/nixos/modules/services/networking/cjdns.nix
+++ b/nixpkgs/nixos/modules/services/networking/cjdns.nix
@@ -29,17 +29,13 @@ let
};
# Additional /etc/hosts entries for peers with an associated hostname
- cjdnsExtraHosts = import (pkgs.runCommand "cjdns-hosts" {}
- # Generate a builder that produces an output usable as a Nix string value
- ''
- exec >$out
- echo \'\'
- ${concatStringsSep "\n" (mapAttrsToList (k: v:
- optionalString (v.hostname != "")
- "echo $(${pkgs.cjdns}/bin/publictoip6 ${v.publicKey}) ${v.hostname}")
- (cfg.ETHInterface.connectTo // cfg.UDPInterface.connectTo))}
- echo \'\'
- '');
+ cjdnsExtraHosts = pkgs.runCommandNoCC "cjdns-hosts" {} ''
+ exec >$out
+ ${concatStringsSep "\n" (mapAttrsToList (k: v:
+ optionalString (v.hostname != "")
+ "echo $(${pkgs.cjdns}/bin/publictoip6 ${v.publicKey}) ${v.hostname}")
+ (cfg.ETHInterface.connectTo // cfg.UDPInterface.connectTo))}
+ '';
parseModules = x:
x // { connectTo = mapAttrs (name: value: { inherit (value) password publicKey; }) x.connectTo; };
@@ -144,13 +140,15 @@ in
connectTo = mkOption {
type = types.attrsOf ( types.submodule ( connectToSubmodule ) );
default = { };
- example = {
- "192.168.1.1:27313" = {
- hostname = "homer.hype";
- password = "5kG15EfpdcKNX3f2GSQ0H1HC7yIfxoCoImnO5FHM";
- publicKey = "371zpkgs8ss387tmr81q04mp0hg1skb51hw34vk1cq644mjqhup0.k";
- };
- };
+ example = literalExample ''
+ {
+ "192.168.1.1:27313" = {
+ hostname = "homer.hype";
+ password = "5kG15EfpdcKNX3f2GSQ0H1HC7yIfxoCoImnO5FHM";
+ publicKey = "371zpkgs8ss387tmr81q04mp0hg1skb51hw34vk1cq644mjqhup0.k";
+ };
+ }
+ '';
description = ''
Credentials for making UDP tunnels.
'';
@@ -189,13 +187,15 @@ in
connectTo = mkOption {
type = types.attrsOf ( types.submodule ( connectToSubmodule ) );
default = { };
- example = {
- "01:02:03:04:05:06" = {
- hostname = "homer.hype";
- password = "5kG15EfpdcKNX3f2GSQ0H1HC7yIfxoCoImnO5FHM";
- publicKey = "371zpkgs8ss387tmr81q04mp0hg1skb51hw34vk1cq644mjqhup0.k";
- };
- };
+ example = literalExample ''
+ {
+ "01:02:03:04:05:06" = {
+ hostname = "homer.hype";
+ password = "5kG15EfpdcKNX3f2GSQ0H1HC7yIfxoCoImnO5FHM";
+ publicKey = "371zpkgs8ss387tmr81q04mp0hg1skb51hw34vk1cq644mjqhup0.k";
+ };
+ }
+ '';
description = ''
Credentials for connecting look similar to UDP credientials
except they begin with the mac address.
@@ -278,7 +278,7 @@ in
};
};
- networking.extraHosts = mkIf cfg.addExtraHosts cjdnsExtraHosts;
+ networking.hostFiles = mkIf cfg.addExtraHosts [ cjdnsExtraHosts ];
assertions = [
{ assertion = ( cfg.ETHInterface.bind != "" || cfg.UDPInterface.bind != "" || cfg.confFile != null );
diff --git a/nixpkgs/nixos/modules/services/networking/dhcpcd.nix b/nixpkgs/nixos/modules/services/networking/dhcpcd.nix
index 6972c833cc5..c0619211c2f 100644
--- a/nixpkgs/nixos/modules/services/networking/dhcpcd.nix
+++ b/nixpkgs/nixos/modules/services/networking/dhcpcd.nix
@@ -19,7 +19,7 @@ let
map (i: i.name) (filter (i: if i.useDHCP != null then !i.useDHCP else i.ipv4.addresses != [ ]) interfaces)
++ mapAttrsToList (i: _: i) config.networking.sits
++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bridges))
- ++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.vswitches))
+ ++ flatten (concatMap (i: attrNames (filterAttrs (_: config: config.type != "internal") i.interfaces)) (attrValues config.networking.vswitches))
++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bonds))
++ config.networking.dhcpcd.denyInterfaces;
@@ -190,6 +190,8 @@ in
before = [ "network-online.target" ];
after = [ "systemd-udev-settle.service" ];
+ restartTriggers = [ exitHook ];
+
# Stopping dhcpcd during a reconfiguration is undesirable
# because it brings down the network interfaces configured by
# dhcpcd. So do a "systemctl restart" instead.
diff --git a/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy.nix b/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy.nix
deleted file mode 100644
index 8edcf925dbf..00000000000
--- a/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy.nix
+++ /dev/null
@@ -1,328 +0,0 @@
-{ config, lib, pkgs, ... }:
-with lib;
-
-let
- cfg = config.services.dnscrypt-proxy;
-
- stateDirectory = "/var/lib/dnscrypt-proxy";
-
- # The minisign public key used to sign the upstream resolver list.
- # This is somewhat more flexible than preloading the key as an
- # embedded string.
- upstreamResolverListPubKey = pkgs.fetchurl {
- url = https://raw.githubusercontent.com/dyne/dnscrypt-proxy/master/minisign.pub;
- sha256 = "18lnp8qr6ghfc2sd46nn1rhcpr324fqlvgsp4zaigw396cd7vnnh";
- };
-
- # Internal flag indicating whether the upstream resolver list is used.
- useUpstreamResolverList = cfg.customResolver == null;
-
- # The final local address.
- localAddress = "${cfg.localAddress}:${toString cfg.localPort}";
-
- # The final resolvers list path.
- resolverList = "${stateDirectory}/dnscrypt-resolvers.csv";
-
- # Build daemon command line
-
- resolverArgs =
- if (cfg.customResolver == null)
- then
- [ "-L ${resolverList}"
- "-R ${cfg.resolverName}"
- ]
- else with cfg.customResolver;
- [ "-N ${name}"
- "-k ${key}"
- "-r ${address}:${toString port}"
- ];
-
- daemonArgs =
- [ "-a ${localAddress}" ]
- ++ resolverArgs
- ++ cfg.extraArgs;
-in
-
-{
- meta = {
- maintainers = with maintainers; [ joachifm ];
- doc = ./dnscrypt-proxy.xml;
- };
-
- options = {
- # Before adding another option, consider whether it could
- # equally well be passed via extraArgs.
-
- services.dnscrypt-proxy = {
- enable = mkOption {
- default = false;
- type = types.bool;
- description = "Whether to enable the DNSCrypt client proxy";
- };
-
- localAddress = mkOption {
- default = "127.0.0.1";
- type = types.str;
- description = ''
- Listen for DNS queries to relay on this address. The only reason to
- change this from its default value is to proxy queries on behalf
- of other machines (typically on the local network).
- '';
- };
-
- localPort = mkOption {
- default = 53;
- type = types.int;
- description = ''
- Listen for DNS queries to relay on this port. The default value
- assumes that the DNSCrypt proxy should relay DNS queries directly.
- When running as a forwarder for another DNS client, set this option
- to a different value; otherwise leave the default.
- '';
- };
-
- resolverName = mkOption {
- default = "random";
- example = "dnscrypt.eu-nl";
- type = types.nullOr types.str;
- description = ''
- The name of the DNSCrypt resolver to use, taken from
- <filename>${resolverList}</filename>. The default is to
- pick a random non-logging resolver that supports DNSSEC.
- '';
- };
-
- customResolver = mkOption {
- default = null;
- description = ''
- Use an unlisted resolver (e.g., a private DNSCrypt provider). For
- advanced users only. If specified, this option takes precedence.
- '';
- type = types.nullOr (types.submodule ({ ... }: { options = {
- address = mkOption {
- type = types.str;
- description = "IP address";
- example = "208.67.220.220";
- };
-
- port = mkOption {
- type = types.int;
- description = "Port";
- default = 443;
- };
-
- name = mkOption {
- type = types.str;
- description = "Fully qualified domain name";
- example = "2.dnscrypt-cert.example.com";
- };
-
- key = mkOption {
- type = types.str;
- description = "Public key";
- example = "B735:1140:206F:225D:3E2B:D822:D7FD:691E:A1C3:3CC8:D666:8D0C:BE04:BFAB:CA43:FB79";
- };
- }; }));
- };
-
- extraArgs = mkOption {
- default = [];
- type = types.listOf types.str;
- description = ''
- Additional command-line arguments passed verbatim to the daemon.
- See <citerefentry><refentrytitle>dnscrypt-proxy</refentrytitle>
- <manvolnum>8</manvolnum></citerefentry> for details.
- '';
- example = [ "-X libdcplugin_example_cache.so,--min-ttl=60" ];
- };
- };
- };
-
- config = mkIf cfg.enable (mkMerge [{
- assertions = [
- { assertion = (cfg.customResolver != null) || (cfg.resolverName != null);
- message = "please configure upstream DNSCrypt resolver";
- }
- ];
-
- # make man 8 dnscrypt-proxy work
- environment.systemPackages = [ pkgs.dnscrypt-proxy ];
-
- users.users.dnscrypt-proxy = {
- description = "dnscrypt-proxy daemon user";
- isSystemUser = true;
- group = "dnscrypt-proxy";
- };
- users.groups.dnscrypt-proxy = {};
-
- systemd.sockets.dnscrypt-proxy = {
- description = "dnscrypt-proxy listening socket";
- documentation = [ "man:dnscrypt-proxy(8)" ];
-
- wantedBy = [ "sockets.target" ];
-
- socketConfig = {
- ListenStream = localAddress;
- ListenDatagram = localAddress;
- };
- };
-
- systemd.services.dnscrypt-proxy = {
- description = "dnscrypt-proxy daemon";
- documentation = [ "man:dnscrypt-proxy(8)" ];
-
- before = [ "nss-lookup.target" ];
- after = [ "network.target" ];
- requires = [ "dnscrypt-proxy.socket "];
-
- serviceConfig = {
- NonBlocking = "true";
- ExecStart = "${pkgs.dnscrypt-proxy}/bin/dnscrypt-proxy ${toString daemonArgs}";
- ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
-
- User = "dnscrypt-proxy";
-
- PrivateTmp = true;
- PrivateDevices = true;
- ProtectHome = true;
- };
- };
- }
-
- (mkIf config.security.apparmor.enable {
- systemd.services.dnscrypt-proxy.after = [ "apparmor.service" ];
-
- security.apparmor.profiles = singleton (pkgs.writeText "apparmor-dnscrypt-proxy" ''
- ${pkgs.dnscrypt-proxy}/bin/dnscrypt-proxy {
- /dev/null rw,
- /dev/random r,
- /dev/urandom r,
-
- /etc/passwd r,
- /etc/group r,
- ${config.environment.etc."nsswitch.conf".source} r,
-
- ${getLib pkgs.glibc}/lib/*.so mr,
- ${pkgs.tzdata}/share/zoneinfo/** r,
-
- network inet stream,
- network inet6 stream,
- network inet dgram,
- network inet6 dgram,
-
- ${getLib pkgs.dnscrypt-proxy}/lib/dnscrypt-proxy/libdcplugin*.so mr,
-
- ${getLib pkgs.gcc.cc}/lib/libssp.so.* mr,
- ${getLib pkgs.libsodium}/lib/libsodium.so.* mr,
- ${getLib pkgs.systemd}/lib/libsystemd.so.* mr,
- ${getLib pkgs.utillinuxMinimal.out}/lib/libmount.so.* mr,
- ${getLib pkgs.utillinuxMinimal.out}/lib/libblkid.so.* mr,
- ${getLib pkgs.utillinuxMinimal.out}/lib/libuuid.so.* mr,
- ${getLib pkgs.xz}/lib/liblzma.so.* mr,
- ${getLib pkgs.libgcrypt}/lib/libgcrypt.so.* mr,
- ${getLib pkgs.libgpgerror}/lib/libgpg-error.so.* mr,
- ${getLib pkgs.libcap}/lib/libcap.so.* mr,
- ${getLib pkgs.lz4}/lib/liblz4.so.* mr,
- ${getLib pkgs.attr}/lib/libattr.so.* mr, # */
-
- ${resolverList} r,
-
- /run/systemd/notify rw,
- }
- '');
- })
-
- (mkIf useUpstreamResolverList {
- systemd.services.init-dnscrypt-proxy-statedir = {
- description = "Initialize dnscrypt-proxy state directory";
-
- wantedBy = [ "dnscrypt-proxy.service" ];
- before = [ "dnscrypt-proxy.service" ];
-
- script = ''
- mkdir -pv ${stateDirectory}
- chown -c dnscrypt-proxy:dnscrypt-proxy ${stateDirectory}
- cp -uv \
- ${pkgs.dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv \
- ${stateDirectory}
- '';
-
- serviceConfig = {
- Type = "oneshot";
- RemainAfterExit = true;
- };
- };
-
- systemd.services.update-dnscrypt-resolvers = {
- description = "Update list of DNSCrypt resolvers";
-
- requires = [ "init-dnscrypt-proxy-statedir.service" ];
- after = [ "init-dnscrypt-proxy-statedir.service" ];
-
- path = with pkgs; [ curl diffutils dnscrypt-proxy minisign ];
- script = ''
- cd ${stateDirectory}
- domain=raw.githubusercontent.com
- get="curl -fSs --resolve $domain:443:$(hostip -r 8.8.8.8 $domain | head -1)"
- $get -o dnscrypt-resolvers.csv.tmp \
- https://$domain/dyne/dnscrypt-proxy/master/dnscrypt-resolvers.csv
- $get -o dnscrypt-resolvers.csv.minisig.tmp \
- https://$domain/dyne/dnscrypt-proxy/master/dnscrypt-resolvers.csv.minisig
- mv dnscrypt-resolvers.csv.minisig{.tmp,}
- if ! minisign -q -V -p ${upstreamResolverListPubKey} \
- -m dnscrypt-resolvers.csv.tmp -x dnscrypt-resolvers.csv.minisig ; then
- echo "failed to verify resolver list!" >&2
- exit 1
- fi
- [[ -f dnscrypt-resolvers.csv ]] && mv dnscrypt-resolvers.csv{,.old}
- mv dnscrypt-resolvers.csv{.tmp,}
- if cmp dnscrypt-resolvers.csv{,.old} ; then
- echo "no change"
- else
- echo "resolver list updated"
- fi
- '';
-
- serviceConfig = {
- PrivateTmp = true;
- PrivateDevices = true;
- ProtectHome = true;
- ProtectSystem = "strict";
- ReadWritePaths = "${dirOf stateDirectory} ${stateDirectory}";
- SystemCallFilter = "~@mount";
- };
- };
-
- systemd.timers.update-dnscrypt-resolvers = {
- wantedBy = [ "timers.target" ];
- timerConfig = {
- OnBootSec = "5min";
- OnUnitActiveSec = "6h";
- };
- };
- })
- ]);
-
- imports = [
- (mkRenamedOptionModule [ "services" "dnscrypt-proxy" "port" ] [ "services" "dnscrypt-proxy" "localPort" ])
-
- (mkChangedOptionModule
- [ "services" "dnscrypt-proxy" "tcpOnly" ]
- [ "services" "dnscrypt-proxy" "extraArgs" ]
- (config:
- let val = getAttrFromPath [ "services" "dnscrypt-proxy" "tcpOnly" ] config; in
- optional val "-T"))
-
- (mkChangedOptionModule
- [ "services" "dnscrypt-proxy" "ephemeralKeys" ]
- [ "services" "dnscrypt-proxy" "extraArgs" ]
- (config:
- let val = getAttrFromPath [ "services" "dnscrypt-proxy" "ephemeralKeys" ] config; in
- optional val "-E"))
-
- (mkRemovedOptionModule [ "services" "dnscrypt-proxy" "resolverList" ] ''
- The current resolver listing from upstream is always used
- unless a custom resolver is specified.
- '')
- ];
-}
diff --git a/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy.xml b/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy.xml
deleted file mode 100644
index afc7880392a..00000000000
--- a/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-<chapter xmlns="http://docbook.org/ns/docbook"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:xi="http://www.w3.org/2001/XInclude"
- version="5.0"
- xml:id="sec-dnscrypt-proxy">
- <title>DNSCrypt client proxy</title>
- <para>
- The DNSCrypt client proxy relays DNS queries to a DNSCrypt enabled upstream
- resolver. The traffic between the client and the upstream resolver is
- encrypted and authenticated, mitigating the risk of MITM attacks, DNS
- poisoning attacks, and third-party snooping (assuming the upstream is
- trustworthy).
- </para>
- <sect1 xml:id="sec-dnscrypt-proxy-configuration">
- <title>Basic configuration</title>
-
- <para>
- To enable the client proxy, set
-<programlisting>
-<xref linkend="opt-services.dnscrypt-proxy.enable"/> = true;
-</programlisting>
- </para>
-
- <para>
- Enabling the client proxy does not alter the system nameserver; to relay
- local queries, prepend <literal>127.0.0.1</literal> to
- <option>networking.nameservers</option>.
- </para>
- </sect1>
- <sect1 xml:id="sec-dnscrypt-proxy-forwarder">
- <title>As a forwarder for another DNS client</title>
-
- <para>
- To run the DNSCrypt proxy client as a forwarder for another DNS client,
- change the default proxy listening port to a non-standard value and point
- the other client to it:
-<programlisting>
-<xref linkend="opt-services.dnscrypt-proxy.localPort"/> = 43;
-</programlisting>
- </para>
-
- <sect2 xml:id="sec-dnscrypt-proxy-forwarder-dsnmasq">
- <title>dnsmasq</title>
- <para>
-<programlisting>
-{
- <xref linkend="opt-services.dnsmasq.enable"/> = true;
- <xref linkend="opt-services.dnsmasq.servers"/> = [ "127.0.0.1#43" ];
-}
-</programlisting>
- </para>
- </sect2>
-
- <sect2 xml:id="sec-dnscrypt-proxy-forwarder-unbound">
- <title>unbound</title>
- <para>
-<programlisting>
-{
- <xref linkend="opt-services.unbound.enable"/> = true;
- <xref linkend="opt-services.unbound.forwardAddresses"/> = [ "127.0.0.1@43" ];
-}
-</programlisting>
- </para>
- </sect2>
- </sect1>
-</chapter>
diff --git a/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy2.nix b/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy2.nix
new file mode 100644
index 00000000000..e48eb729103
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/dnscrypt-proxy2.nix
@@ -0,0 +1,61 @@
+{ config, lib, pkgs, ... }: with lib;
+
+let
+ cfg = config.services.dnscrypt-proxy2;
+in
+
+{
+ options.services.dnscrypt-proxy2 = {
+ enable = mkEnableOption "dnscrypt-proxy2";
+
+ settings = mkOption {
+ description = ''
+ Attrset that is converted and passed as TOML config file.
+ For available params, see: <link xlink:href="https://github.com/DNSCrypt/dnscrypt-proxy/blob/master/dnscrypt-proxy/example-dnscrypt-proxy.toml"/>
+ '';
+ example = literalExample ''
+ {
+ sources.public-resolvers = {
+ urls = [ "https://download.dnscrypt.info/resolvers-list/v2/public-resolvers.md" ];
+ cache_file = "public-resolvers.md";
+ minisign_key = "RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3";
+ refresh_delay = 72;
+ };
+ }
+ '';
+ type = types.attrs;
+ default = {};
+ };
+
+ configFile = mkOption {
+ description = ''
+ Path to TOML config file. See: <link xlink:href="https://github.com/DNSCrypt/dnscrypt-proxy/blob/master/dnscrypt-proxy/example-dnscrypt-proxy.toml"/>
+ If this option is set, it will override any configuration done in options.services.dnscrypt-proxy2.settings.
+ '';
+ example = "/etc/dnscrypt-proxy/dnscrypt-proxy.toml";
+ type = types.path;
+ default = pkgs.runCommand "dnscrypt-proxy.toml" {
+ json = builtins.toJSON cfg.settings;
+ passAsFile = [ "json" ];
+ } ''
+ ${pkgs.remarshal}/bin/json2toml < $jsonPath > $out
+ '';
+ defaultText = literalExample "TOML file generated from services.dnscrypt-proxy2.settings";
+ };
+ };
+
+ config = mkIf cfg.enable {
+
+ networking.nameservers = lib.mkDefault [ "127.0.0.1" ];
+
+ systemd.services.dnscrypt-proxy2 = {
+ after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ serviceConfig = {
+ AmbientCapabilities = "CAP_NET_BIND_SERVICE";
+ DynamicUser = true;
+ ExecStart = "${pkgs.dnscrypt-proxy2}/bin/dnscrypt-proxy -config ${cfg.configFile}";
+ };
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/networking/firewall.nix b/nixpkgs/nixos/modules/services/networking/firewall.nix
index 15aaf741067..cdc3a172ea7 100644
--- a/nixpkgs/nixos/modules/services/networking/firewall.nix
+++ b/nixpkgs/nixos/modules/services/networking/firewall.nix
@@ -546,9 +546,13 @@ in
options nf_conntrack nf_conntrack_helper=1
'';
- assertions = [ { assertion = (cfg.checkReversePath != false) || kernelHasRPFilter;
- message = "This kernel does not support rpfilter"; }
- ];
+ assertions = [
+ # This is approximately "checkReversePath -> kernelHasRPFilter",
+ # but the checkReversePath option can include non-boolean
+ # values.
+ { assertion = cfg.checkReversePath == false || kernelHasRPFilter;
+ message = "This kernel does not support rpfilter"; }
+ ];
systemd.services.firewall = {
description = "Firewall";
diff --git a/nixpkgs/nixos/modules/services/networking/freeradius.nix b/nixpkgs/nixos/modules/services/networking/freeradius.nix
index e192b70c129..f3fdd576b65 100644
--- a/nixpkgs/nixos/modules/services/networking/freeradius.nix
+++ b/nixpkgs/nixos/modules/services/networking/freeradius.nix
@@ -10,14 +10,15 @@ let
{
description = "FreeRadius server";
wantedBy = ["multi-user.target"];
- after = ["network-online.target"];
- wants = ["network-online.target"];
+ after = ["network.target"];
+ wants = ["network.target"];
preStart = ''
${pkgs.freeradius}/bin/radiusd -C -d ${cfg.configDir} -l stdout
'';
serviceConfig = {
- ExecStart = "${pkgs.freeradius}/bin/radiusd -f -d ${cfg.configDir} -l stdout -xx";
+ ExecStart = "${pkgs.freeradius}/bin/radiusd -f -d ${cfg.configDir} -l stdout" +
+ optionalString cfg.debug " -xx";
ExecReload = [
"${pkgs.freeradius}/bin/radiusd -C -d ${cfg.configDir} -l stdout"
"${pkgs.coreutils}/bin/kill -HUP $MAINPID"
@@ -41,6 +42,16 @@ let
'';
};
+ debug = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to enable debug logging for freeradius (-xx
+ option). This should not be left on, since it includes
+ sensitive data such as passwords in the logs.
+ '';
+ };
+
};
in
@@ -66,6 +77,7 @@ in
};
systemd.services.freeradius = freeradiusService cfg;
+ warnings = optional cfg.debug "Freeradius debug logging is enabled. This will log passwords in plaintext to the journal!";
};
diff --git a/nixpkgs/nixos/modules/services/networking/git-daemon.nix b/nixpkgs/nixos/modules/services/networking/git-daemon.nix
index 6f2e149433f..52c895215fb 100644
--- a/nixpkgs/nixos/modules/services/networking/git-daemon.nix
+++ b/nixpkgs/nixos/modules/services/networking/git-daemon.nix
@@ -104,14 +104,14 @@ in
config = mkIf cfg.enable {
- users.users = optionalAttrs (cfg.user != "git") {
+ users.users = optionalAttrs (cfg.user == "git") {
git = {
uid = config.ids.uids.git;
description = "Git daemon user";
};
};
- users.groups = optionalAttrs (cfg.group != "git") {
+ users.groups = optionalAttrs (cfg.group == "git") {
git.gid = config.ids.gids.git;
};
diff --git a/nixpkgs/nixos/modules/services/networking/haproxy.nix b/nixpkgs/nixos/modules/services/networking/haproxy.nix
index aff71e5e97d..4678829986c 100644
--- a/nixpkgs/nixos/modules/services/networking/haproxy.nix
+++ b/nixpkgs/nixos/modules/services/networking/haproxy.nix
@@ -26,6 +26,18 @@ with lib;
'';
};
+ user = mkOption {
+ type = types.str;
+ default = "haproxy";
+ description = "User account under which haproxy runs.";
+ };
+
+ group = mkOption {
+ type = types.str;
+ default = "haproxy";
+ description = "Group account under which haproxy runs.";
+ };
+
config = mkOption {
type = types.nullOr types.lines;
default = null;
@@ -49,7 +61,8 @@ with lib;
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
- DynamicUser = true;
+ User = cfg.user;
+ Group = cfg.group;
Type = "notify";
# when running the config test, don't be quiet so we can see what goes wrong
ExecStartPre = "${pkgs.haproxy}/sbin/haproxy -c -f ${haproxyCfg}";
@@ -60,5 +73,16 @@ with lib;
AmbientCapabilities = "CAP_NET_BIND_SERVICE";
};
};
+
+ users.users = optionalAttrs (cfg.user == "haproxy") {
+ haproxy = {
+ group = cfg.group;
+ isSystemUser = true;
+ };
+ };
+
+ users.groups = optionalAttrs (cfg.group == "haproxy") {
+ haproxy = {};
+ };
};
}
diff --git a/nixpkgs/nixos/modules/services/networking/i2pd.nix b/nixpkgs/nixos/modules/services/networking/i2pd.nix
index 326d34f6ca9..93a21fd4c97 100644
--- a/nixpkgs/nixos/modules/services/networking/i2pd.nix
+++ b/nixpkgs/nixos/modules/services/networking/i2pd.nix
@@ -158,10 +158,10 @@ let
(sec "addressbook")
(strOpt "defaulturl" cfg.addressbook.defaulturl)
] ++ (optionalEmptyList "subscriptions" cfg.addressbook.subscriptions)
- ++ (flip mapAttrs
- (collect (name: proto: proto ? port && proto ? address && proto ? name) cfg.proto)
+ ++ (flip map
+ (collect (proto: proto ? port && proto ? address) cfg.proto)
(proto: let protoOpts = [
- (sec name)
+ (sec proto.name)
(boolOpt "enabled" proto.enable)
(strOpt "address" proto.address)
(intOpt "port" proto.port)
@@ -181,10 +181,10 @@ let
tunnelConf = let opts = [
notice
- (flip mapAttrs
- (collect (name: tun: tun ? port && tun ? destination) cfg.outTunnels)
+ (flip map
+ (collect (tun: tun ? port && tun ? destination) cfg.outTunnels)
(tun: let outTunOpts = [
- (sec name)
+ (sec tun.name)
"type = client"
(intOpt "port" tun.port)
(strOpt "destination" tun.destination)
@@ -204,10 +204,10 @@ let
++ (if tun ? crypto.tagsToSend then
optionalNullInt "crypto.tagstosend" tun.crypto.tagsToSend else []);
in concatStringsSep "\n" outTunOpts))
- (flip mapAttrs
- (collect (name: tun: tun ? port && tun ? address) cfg.inTunnels)
+ (flip map
+ (collect (tun: tun ? port && tun ? address) cfg.inTunnels)
(tun: let inTunOpts = [
- (sec name)
+ (sec tun.name)
"type = server"
(intOpt "port" tun.port)
(strOpt "host" tun.address)
@@ -606,7 +606,7 @@ in
outTunnels = mkOption {
default = {};
- type = with types; loaOf (submodule (
+ type = with types; attrsOf (submodule (
{ name, ... }: {
options = {
destinationPort = mkOption {
@@ -627,7 +627,7 @@ in
inTunnels = mkOption {
default = {};
- type = with types; loaOf (submodule (
+ type = with types; attrsOf (submodule (
{ name, ... }: {
options = {
inPort = mkOption {
diff --git a/nixpkgs/nixos/modules/services/networking/iodine.nix b/nixpkgs/nixos/modules/services/networking/iodine.nix
index f9ca26c2796..46051d7044b 100644
--- a/nixpkgs/nixos/modules/services/networking/iodine.nix
+++ b/nixpkgs/nixos/modules/services/networking/iodine.nix
@@ -9,6 +9,8 @@ let
iodinedUser = "iodined";
+ /* is this path made unreadable by ProtectHome = true ? */
+ isProtected = x: hasPrefix "/root" x || hasPrefix "/home" x;
in
{
imports = [
@@ -35,45 +37,48 @@ in
corresponding attribute name.
'';
example = literalExample ''
- {
- foo = {
- server = "tunnel.mdomain.com";
- relay = "8.8.8.8";
- extraConfig = "-v";
+ {
+ foo = {
+ server = "tunnel.mdomain.com";
+ relay = "8.8.8.8";
+ extraConfig = "-v";
+ }
}
- }
'';
- type = types.attrsOf (types.submodule (
- {
- options = {
- server = mkOption {
- type = types.str;
- default = "";
- description = "Domain or Subdomain of server running iodined";
- example = "tunnel.mydomain.com";
- };
-
- relay = mkOption {
- type = types.str;
- default = "";
- description = "DNS server to use as a intermediate relay to the iodined server";
- example = "8.8.8.8";
- };
-
- extraConfig = mkOption {
- type = types.str;
- default = "";
- description = "Additional command line parameters";
- example = "-l 192.168.1.10 -p 23";
- };
-
- passwordFile = mkOption {
- type = types.str;
- default = "";
- description = "File that contains password";
- };
- };
- }));
+ type = types.attrsOf (
+ types.submodule (
+ {
+ options = {
+ server = mkOption {
+ type = types.str;
+ default = "";
+ description = "Hostname of server running iodined";
+ example = "tunnel.mydomain.com";
+ };
+
+ relay = mkOption {
+ type = types.str;
+ default = "";
+ description = "DNS server to use as an intermediate relay to the iodined server";
+ example = "8.8.8.8";
+ };
+
+ extraConfig = mkOption {
+ type = types.str;
+ default = "";
+ description = "Additional command line parameters";
+ example = "-l 192.168.1.10 -p 23";
+ };
+
+ passwordFile = mkOption {
+ type = types.str;
+ default = "";
+ description = "Path to a file containing the password.";
+ };
+ };
+ }
+ )
+ );
};
server = {
@@ -121,31 +126,67 @@ in
boot.kernelModules = [ "tun" ];
systemd.services =
- let
- createIodineClientService = name: cfg:
- {
- description = "iodine client - ${name}";
- after = [ "network.target" ];
- wantedBy = [ "multi-user.target" ];
- script = "exec ${pkgs.iodine}/bin/iodine -f -u ${iodinedUser} ${cfg.extraConfig} ${optionalString (cfg.passwordFile != "") "< \"${cfg.passwordFile}\""} ${cfg.relay} ${cfg.server}";
- serviceConfig = {
- RestartSec = "30s";
- Restart = "always";
+ let
+ createIodineClientService = name: cfg:
+ {
+ description = "iodine client - ${name}";
+ after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ script = "exec ${pkgs.iodine}/bin/iodine -f -u ${iodinedUser} ${cfg.extraConfig} ${optionalString (cfg.passwordFile != "") "< \"${builtins.toString cfg.passwordFile}\""} ${cfg.relay} ${cfg.server}";
+ serviceConfig = {
+ RestartSec = "30s";
+ Restart = "always";
+
+ # hardening :
+ # Filesystem access
+ ProtectSystem = "strict";
+ ProtectHome = if isProtected cfg.passwordFile then "read-only" else "true" ;
+ PrivateTmp = true;
+ ReadWritePaths = "/dev/net/tun";
+ PrivateDevices = false;
+ ProtectKernelTunables = true;
+ ProtectKernelModules = true;
+ ProtectControlGroups = true;
+ # Caps
+ NoNewPrivileges = true;
+ # Misc.
+ LockPersonality = true;
+ RestrictRealtime = true;
+ PrivateMounts = true;
+ MemoryDenyWriteExecute = true;
+ };
+ };
+ in
+ listToAttrs (
+ mapAttrsToList
+ (name: value: nameValuePair "iodine-${name}" (createIodineClientService name value))
+ cfg.clients
+ ) // {
+ iodined = mkIf (cfg.server.enable) {
+ description = "iodine, ip over dns server daemon";
+ after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ script = "exec ${pkgs.iodine}/bin/iodined -f -u ${iodinedUser} ${cfg.server.extraConfig} ${optionalString (cfg.server.passwordFile != "") "< \"${builtins.toString cfg.server.passwordFile}\""} ${cfg.server.ip} ${cfg.server.domain}";
+ serviceConfig = {
+ # Filesystem access
+ ProtectSystem = "strict";
+ ProtectHome = if isProtected cfg.server.passwordFile then "read-only" else "true" ;
+ PrivateTmp = true;
+ ReadWritePaths = "/dev/net/tun";
+ PrivateDevices = false;
+ ProtectKernelTunables = true;
+ ProtectKernelModules = true;
+ ProtectControlGroups = true;
+ # Caps
+ NoNewPrivileges = true;
+ # Misc.
+ LockPersonality = true;
+ RestrictRealtime = true;
+ PrivateMounts = true;
+ MemoryDenyWriteExecute = true;
+ };
+ };
};
- };
- in
- listToAttrs (
- mapAttrsToList
- (name: value: nameValuePair "iodine-${name}" (createIodineClientService name value))
- cfg.clients
- ) // {
- iodined = mkIf (cfg.server.enable) {
- description = "iodine, ip over dns server daemon";
- after = [ "network.target" ];
- wantedBy = [ "multi-user.target" ];
- script = "exec ${pkgs.iodine}/bin/iodined -f -u ${iodinedUser} ${cfg.server.extraConfig} ${optionalString (cfg.server.passwordFile != "") "< \"${cfg.server.passwordFile}\""} ${cfg.server.ip} ${cfg.server.domain}";
- };
- };
users.users.${iodinedUser} = {
uid = config.ids.uids.iodined;
diff --git a/nixpkgs/nixos/modules/services/networking/iwd.nix b/nixpkgs/nixos/modules/services/networking/iwd.nix
index 839fa48d9a4..6be67a8b96f 100644
--- a/nixpkgs/nixos/modules/services/networking/iwd.nix
+++ b/nixpkgs/nixos/modules/services/networking/iwd.nix
@@ -23,12 +23,7 @@ in {
systemd.packages = [ pkgs.iwd ];
systemd.services.iwd.wantedBy = [ "multi-user.target" ];
-
- systemd.tmpfiles.rules = [
- "d /var/lib/iwd 0700 root root -"
- "d /var/lib/ead 0700 root root -"
- ];
};
- meta.maintainers = with lib.maintainers; [ mic92 ];
+ meta.maintainers = with lib.maintainers; [ mic92 dtzWill ];
}
diff --git a/nixpkgs/nixos/modules/services/networking/knot.nix b/nixpkgs/nixos/modules/services/networking/knot.nix
index 47364ecb846..12ff89fe849 100644
--- a/nixpkgs/nixos/modules/services/networking/knot.nix
+++ b/nixpkgs/nixos/modules/services/networking/knot.nix
@@ -5,14 +5,16 @@ with lib;
let
cfg = config.services.knot;
- configFile = pkgs.writeText "knot.conf" cfg.extraConfig;
- socketFile = "/run/knot/knot.sock";
+ configFile = pkgs.writeTextFile {
+ name = "knot.conf";
+ text = (concatMapStringsSep "\n" (file: "include: ${file}") cfg.keyFiles) + "\n" +
+ cfg.extraConfig;
+ checkPhase = lib.optionalString (cfg.keyFiles == []) ''
+ ${cfg.package}/bin/knotc --config=$out conf-check
+ '';
+ };
- knotConfCheck = file: pkgs.runCommand "knot-config-checked"
- { buildInputs = [ cfg.package ]; } ''
- ln -s ${configFile} $out
- knotc --config=${configFile} conf-check
- '';
+ socketFile = "/run/knot/knot.sock";
knot-cli-wrappers = pkgs.stdenv.mkDerivation {
name = "knot-cli-wrappers";
@@ -45,6 +47,19 @@ in {
'';
};
+ keyFiles = mkOption {
+ type = types.listOf types.path;
+ default = [];
+ description = ''
+ A list of files containing additional configuration
+ to be included using the include directive. This option
+ allows to include configuration like TSIG keys without
+ exposing them to the nix store readable to any process.
+ Note that using this option will also disable configuration
+ checks at build time.
+ '';
+ };
+
extraConfig = mkOption {
type = types.lines;
default = "";
@@ -65,6 +80,13 @@ in {
};
config = mkIf config.services.knot.enable {
+ users.users.knot = {
+ isSystemUser = true;
+ group = "knot";
+ description = "Knot daemon user";
+ };
+
+ users.groups.knot.gid = null;
systemd.services.knot = {
unitConfig.Documentation = "man:knotd(8) man:knot.conf(5) man:knotc(8) https://www.knot-dns.cz/docs/${cfg.package.version}/html/";
description = cfg.package.meta.description;
@@ -74,12 +96,12 @@ in {
serviceConfig = {
Type = "notify";
- ExecStart = "${cfg.package}/bin/knotd --config=${knotConfCheck configFile} --socket=${socketFile} ${concatStringsSep " " cfg.extraArgs}";
+ ExecStart = "${cfg.package}/bin/knotd --config=${configFile} --socket=${socketFile} ${concatStringsSep " " cfg.extraArgs}";
ExecReload = "${knot-cli-wrappers}/bin/knotc reload";
CapabilityBoundingSet = "CAP_NET_BIND_SERVICE CAP_SETPCAP";
AmbientCapabilities = "CAP_NET_BIND_SERVICE CAP_SETPCAP";
NoNewPrivileges = true;
- DynamicUser = "yes";
+ User = "knot";
RuntimeDirectory = "knot";
StateDirectory = "knot";
StateDirectoryMode = "0700";
diff --git a/nixpkgs/nixos/modules/services/networking/kresd.nix b/nixpkgs/nixos/modules/services/networking/kresd.nix
index bb941e93e15..c5a84eebd46 100644
--- a/nixpkgs/nixos/modules/services/networking/kresd.nix
+++ b/nixpkgs/nixos/modules/services/networking/kresd.nix
@@ -3,16 +3,38 @@
with lib;
let
-
cfg = config.services.kresd;
- configFile = pkgs.writeText "kresd.conf" ''
- ${optionalString (cfg.listenDoH != []) "modules.load('http')"}
- ${cfg.extraConfig};
- '';
- package = pkgs.knot-resolver.override {
- extraFeatures = cfg.listenDoH != [];
- };
+ # Convert systemd-style address specification to kresd config line(s).
+ # On Nix level we don't attempt to precisely validate the address specifications.
+ mkListen = kind: addr: let
+ al_v4 = builtins.match "([0-9.]\+):([0-9]\+)" addr;
+ al_v6 = builtins.match "\\[(.\+)]:([0-9]\+)" addr;
+ al_portOnly = builtins.match "()([0-9]\+)" addr;
+ al = findFirst (a: a != null)
+ (throw "services.kresd.*: incorrect address specification '${addr}'")
+ [ al_v4 al_v6 al_portOnly ];
+ port = last al;
+ addrSpec = if al_portOnly == null then "'${head al}'" else "{'::', '127.0.0.1'}";
+ in # freebind is set for compatibility with earlier kresd services;
+ # it could be configurable, for example.
+ ''
+ net.listen(${addrSpec}, ${port}, { kind = '${kind}', freebind = true })
+ '';
+
+ configFile = pkgs.writeText "kresd.conf" (
+ optionalString (cfg.listenDoH != []) ''
+ modules.load('http')
+ ''
+ + concatMapStrings (mkListen "dns") cfg.listenPlain
+ + concatMapStrings (mkListen "tls") cfg.listenTLS
+ + concatMapStrings (mkListen "doh") cfg.listenDoH
+ + cfg.extraConfig
+ );
+
+ package = if cfg.listenDoH == []
+ then pkgs.knot-resolver # never force `extraFeatures = false`
+ else pkgs.knot-resolver.override { extraFeatures = true; };
in {
meta.maintainers = [ maintainers.vcunat /* upstream developer */ ];
@@ -25,6 +47,7 @@ in {
value
)
)
+ (mkRemovedOptionModule [ "services" "kresd" "cacheDir" ] "Please use (bind-)mounting instead.")
];
###### interface
@@ -35,8 +58,8 @@ in {
description = ''
Whether to enable knot-resolver domain name server.
DNSSEC validation is turned on by default.
- You can run <literal>sudo nc -U /run/kresd/control</literal>
- and give commands interactively to kresd.
+ You can run <literal>sudo nc -U /run/knot-resolver/control/1</literal>
+ and give commands interactively to kresd@1.service.
'';
};
extraConfig = mkOption {
@@ -46,16 +69,10 @@ in {
Extra lines to be added verbatim to the generated configuration file.
'';
};
- cacheDir = mkOption {
- type = types.path;
- default = "/var/cache/kresd";
- description = ''
- Directory for caches. They are intended to survive reboots.
- '';
- };
listenPlain = mkOption {
type = with types; listOf str;
default = [ "[::1]:53" "127.0.0.1:53" ];
+ example = [ "53" ];
description = ''
What addresses and ports the server should listen on.
For detailed syntax see ListenStream in man systemd.socket.
@@ -75,91 +92,54 @@ in {
default = [];
example = [ "198.51.100.1:443" "[2001:db8::1]:443" "443" ];
description = ''
- Addresses and ports on which kresd should provide DNS over HTTPS (see RFC 7858).
+ Addresses and ports on which kresd should provide DNS over HTTPS (see RFC 8484).
For detailed syntax see ListenStream in man systemd.socket.
'';
};
+ instances = mkOption {
+ type = types.ints.unsigned;
+ default = 1;
+ description = ''
+ The number of instances to start. They will be called kresd@{1,2,...}.service.
+ Knot Resolver uses no threads, so this is the way to scale.
+ You can dynamically start/stop them at will, so this is just system default.
+ '';
+ };
# TODO: perhaps options for more common stuff like cache size or forwarding
};
###### implementation
config = mkIf cfg.enable {
- environment.etc."kresd.conf".source = configFile; # not required
+ environment.etc."knot-resolver/kresd.conf".source = configFile; # not required
- users.users.kresd =
- { uid = config.ids.uids.kresd;
- group = "kresd";
+ users.users.knot-resolver =
+ { isSystemUser = true;
+ group = "knot-resolver";
description = "Knot-resolver daemon user";
};
- users.groups.kresd.gid = config.ids.gids.kresd;
-
- systemd.sockets.kresd = rec {
- wantedBy = [ "sockets.target" ];
- before = wantedBy;
- listenStreams = cfg.listenPlain;
- socketConfig = {
- ListenDatagram = listenStreams;
- FreeBind = true;
- FileDescriptorName = "dns";
- };
- };
+ users.groups.knot-resolver.gid = null;
- systemd.sockets.kresd-tls = mkIf (cfg.listenTLS != []) rec {
- wantedBy = [ "sockets.target" ];
- before = wantedBy;
- partOf = [ "kresd.socket" ];
- listenStreams = cfg.listenTLS;
- socketConfig = {
- FileDescriptorName = "tls";
- FreeBind = true;
- Service = "kresd.service";
- };
- };
+ systemd.packages = [ package ]; # the units are patched inside the package a bit
- systemd.sockets.kresd-doh = mkIf (cfg.listenDoH != []) rec {
- wantedBy = [ "sockets.target" ];
- before = wantedBy;
- partOf = [ "kresd.socket" ];
- listenStreams = cfg.listenDoH;
- socketConfig = {
- FileDescriptorName = "doh";
- FreeBind = true;
- Service = "kresd.service";
- };
+ systemd.targets.kresd = { # configure units started by default
+ wantedBy = [ "multi-user.target" ];
+ wants = [ "kres-cache-gc.service" ]
+ ++ map (i: "kresd@${toString i}.service") (range 1 cfg.instances);
};
-
- systemd.sockets.kresd-control = rec {
- wantedBy = [ "sockets.target" ];
- before = wantedBy;
- partOf = [ "kresd.socket" ];
- listenStreams = [ "/run/kresd/control" ];
- socketConfig = {
- FileDescriptorName = "control";
- Service = "kresd.service";
- SocketMode = "0660"; # only root user/group may connect and control kresd
- };
+ systemd.services."kresd@".serviceConfig = {
+ ExecStart = "${package}/bin/kresd --noninteractive "
+ + "-c ${package}/lib/knot-resolver/distro-preconfig.lua -c ${configFile}";
+ # Ensure correct ownership in case UID or GID changes.
+ CacheDirectory = "knot-resolver";
+ CacheDirectoryMode = "0750";
};
- systemd.tmpfiles.rules = [ "d '${cfg.cacheDir}' 0770 kresd kresd - -" ];
+ environment.etc."tmpfiles.d/knot-resolver.conf".source =
+ "${package}/lib/tmpfiles.d/knot-resolver.conf";
- systemd.services.kresd = {
- description = "Knot-resolver daemon";
-
- serviceConfig = {
- User = "kresd";
- Type = "notify";
- WorkingDirectory = cfg.cacheDir;
- Restart = "on-failure";
- Sockets = [ "kresd.socket" "kresd-control.socket" ]
- ++ optional (cfg.listenTLS != []) "kresd-tls.socket";
- };
-
- # Trust anchor goes from dns-root-data by default.
- script = ''
- exec '${package}/bin/kresd' --config '${configFile}' --forks=1
- '';
-
- requires = [ "kresd.socket" ];
- };
+ # Try cleaning up the previously default location of cache file.
+ # Note that /var/cache/* should always be safe to remove.
+ # TODO: remove later, probably between 20.09 and 21.03
+ systemd.tmpfiles.rules = [ "R /var/cache/kresd" ];
};
}
diff --git a/nixpkgs/nixos/modules/services/networking/minidlna.nix b/nixpkgs/nixos/modules/services/networking/minidlna.nix
index 3ddea3c9757..c580ba47dad 100644
--- a/nixpkgs/nixos/modules/services/networking/minidlna.nix
+++ b/nixpkgs/nixos/modules/services/networking/minidlna.nix
@@ -95,6 +95,22 @@ in
'';
};
+ services.minidlna.announceInterval = mkOption {
+ type = types.int;
+ default = 895;
+ description =
+ ''
+ The interval between announces (in seconds).
+
+ By default miniDLNA will announce its presence on the network
+ approximately every 15 minutes.
+
+ Many people prefer shorter announce intervals (e.g. 60 seconds)
+ on their home networks, especially when DLNA clients are
+ started on demand.
+ '';
+ };
+
services.minidlna.config = mkOption {
type = types.lines;
description =
@@ -144,6 +160,7 @@ in
${concatMapStrings (dir: ''
media_dir=${dir}
'') cfg.mediaDirs}
+ notify_interval=${toString cfg.announceInterval}
${cfg.extraConfig}
'';
diff --git a/nixpkgs/nixos/modules/services/networking/nat.nix b/nixpkgs/nixos/modules/services/networking/nat.nix
index 9c658af30f7..21ae9eb8b6d 100644
--- a/nixpkgs/nixos/modules/services/networking/nat.nix
+++ b/nixpkgs/nixos/modules/services/networking/nat.nix
@@ -65,7 +65,7 @@ let
let
m = builtins.match "([0-9.]+):([0-9-]+)" fwd.destination;
destinationIP = if (m == null) then throw "bad ip:ports `${fwd.destination}'" else elemAt m 0;
- destinationPorts = if (m == null) then throw "bad ip:ports `${fwd.destination}'" else elemAt m 1;
+ destinationPorts = if (m == null) then throw "bad ip:ports `${fwd.destination}'" else builtins.replaceStrings ["-"] [":"] (elemAt m 1);
in ''
# Allow connections to ${loopbackip}:${toString fwd.sourcePort} from the host itself
iptables -w -t nat -A nixos-nat-out \
diff --git a/nixpkgs/nixos/modules/services/networking/nix-store-gcs-proxy.nix b/nixpkgs/nixos/modules/services/networking/nix-store-gcs-proxy.nix
new file mode 100644
index 00000000000..3f2ce5bca4d
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/nix-store-gcs-proxy.nix
@@ -0,0 +1,75 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ opts = { name, config, ... }: {
+ options = {
+ enable = mkOption {
+ default = true;
+ type = types.bool;
+ example = true;
+ description = "Whether to enable proxy for this bucket";
+ };
+ bucketName = mkOption {
+ type = types.str;
+ default = name;
+ example = "my-bucket-name";
+ description = "Name of Google storage bucket";
+ };
+ address = mkOption {
+ type = types.str;
+ example = "localhost:3000";
+ description = "The address of the proxy.";
+ };
+ };
+ };
+ enabledProxies = lib.filterAttrs (n: v: v.enable) config.services.nix-store-gcs-proxy;
+ mapProxies = function: lib.mkMerge (lib.mapAttrsToList function enabledProxies);
+in
+{
+ options.services.nix-store-gcs-proxy = mkOption {
+ type = types.attrsOf (types.submodule opts);
+ default = {};
+ description = ''
+ An attribute set describing an HTTP to GCS proxy that allows us to use GCS
+ bucket via HTTP protocol.
+ '';
+ };
+
+ config.systemd.services = mapProxies (name: cfg: {
+ "nix-store-gcs-proxy-${name}" = {
+ description = "A HTTP nix store that proxies requests to Google Storage";
+ wantedBy = ["multi-user.target"];
+
+ serviceConfig = {
+ RestartSec = 5;
+ StartLimitInterval = 10;
+ ExecStart = ''
+ ${pkgs.nix-store-gcs-proxy}/bin/nix-store-gcs-proxy \
+ --bucket-name ${cfg.bucketName} \
+ --addr ${cfg.address}
+ '';
+
+ DynamicUser = true;
+
+ ProtectSystem = "strict";
+ ProtectHome = true;
+ PrivateTmp = true;
+ PrivateDevices = true;
+ PrivateMounts = true;
+ PrivateUsers = true;
+
+ ProtectKernelTunables = true;
+ ProtectKernelModules = true;
+ ProtectControlGroups = true;
+
+ NoNewPrivileges = true;
+ LockPersonality = true;
+ RestrictRealtime = true;
+ };
+ };
+ });
+
+ meta.maintainers = [ maintainers.mrkkrp ];
+}
diff --git a/nixpkgs/nixos/modules/services/networking/nsd.nix b/nixpkgs/nixos/modules/services/networking/nsd.nix
index 344396638a6..429580e5c6c 100644
--- a/nixpkgs/nixos/modules/services/networking/nsd.nix
+++ b/nixpkgs/nixos/modules/services/networking/nsd.nix
@@ -244,7 +244,7 @@ let
};
data = mkOption {
- type = types.str;
+ type = types.lines;
default = "";
example = "";
description = ''
@@ -484,7 +484,7 @@ in
};
extraConfig = mkOption {
- type = types.str;
+ type = types.lines;
default = "";
description = ''
Extra nsd config.
diff --git a/nixpkgs/nixos/modules/services/networking/ntp/ntpd.nix b/nixpkgs/nixos/modules/services/networking/ntp/ntpd.nix
index b5403cb747d..54ff054d84c 100644
--- a/nixpkgs/nixos/modules/services/networking/ntp/ntpd.nix
+++ b/nixpkgs/nixos/modules/services/networking/ntp/ntpd.nix
@@ -23,6 +23,8 @@ let
restrict -6 ::1
${toString (map (server: "server " + server + " iburst\n") cfg.servers)}
+
+ ${cfg.extraConfig}
'';
ntpFlags = "-c ${configFile} -u ${ntpUser}:nogroup ${toString cfg.extraFlags}";
@@ -81,6 +83,17 @@ in
'';
};
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ example = ''
+ fudge 127.127.1.0 stratum 10
+ '';
+ description = ''
+ Additional text appended to <filename>ntp.conf</filename>.
+ '';
+ };
+
extraFlags = mkOption {
type = types.listOf types.str;
description = "Extra flags passed to the ntpd command.";
diff --git a/nixpkgs/nixos/modules/services/networking/pppd.nix b/nixpkgs/nixos/modules/services/networking/pppd.nix
index b31bfa64235..c1cbdb46176 100644
--- a/nixpkgs/nixos/modules/services/networking/pppd.nix
+++ b/nixpkgs/nixos/modules/services/networking/pppd.nix
@@ -130,7 +130,7 @@ in
systemdConfigs = listToAttrs (map mkSystemd enabledConfigs);
in mkIf cfg.enable {
- environment.etc = mkMerge etcFiles;
- systemd.services = mkMerge systemdConfigs;
+ environment.etc = etcFiles;
+ systemd.services = systemdConfigs;
};
}
diff --git a/nixpkgs/nixos/modules/services/networking/shorewall.nix b/nixpkgs/nixos/modules/services/networking/shorewall.nix
index 0f94d414fcf..16383be2530 100644
--- a/nixpkgs/nixos/modules/services/networking/shorewall.nix
+++ b/nixpkgs/nixos/modules/services/networking/shorewall.nix
@@ -26,7 +26,7 @@ in {
description = "The shorewall package to use.";
};
configs = lib.mkOption {
- type = types.attrsOf types.str;
+ type = types.attrsOf types.lines;
default = {};
description = ''
This option defines the Shorewall configs.
@@ -63,12 +63,7 @@ in {
'';
};
environment = {
- etc = lib.mapAttrsToList
- (name: file:
- { source = file;
- target = "shorewall/${name}";
- })
- cfg.configs;
+ etc = lib.mapAttrs' (name: conf: lib.nameValuePair "shorewall/${name}" {source=conf;}) cfg.configs;
systemPackages = [ cfg.package ];
};
};
diff --git a/nixpkgs/nixos/modules/services/networking/shorewall6.nix b/nixpkgs/nixos/modules/services/networking/shorewall6.nix
index 9c22a037c0b..e081aedc6c3 100644
--- a/nixpkgs/nixos/modules/services/networking/shorewall6.nix
+++ b/nixpkgs/nixos/modules/services/networking/shorewall6.nix
@@ -26,7 +26,7 @@ in {
description = "The shorewall package to use.";
};
configs = lib.mkOption {
- type = types.attrsOf types.str;
+ type = types.attrsOf types.lines;
default = {};
description = ''
This option defines the Shorewall configs.
@@ -63,12 +63,7 @@ in {
'';
};
environment = {
- etc = lib.mapAttrsToList
- (name: file:
- { source = file;
- target = "shorewall6/${name}";
- })
- cfg.configs;
+ etc = lib.mapAttrs' (name: conf: lib.nameValuePair "shorewall6/${name}" {source=conf;}) cfg.configs;
systemPackages = [ cfg.package ];
};
};
diff --git a/nixpkgs/nixos/modules/services/networking/smartdns.nix b/nixpkgs/nixos/modules/services/networking/smartdns.nix
new file mode 100644
index 00000000000..f1888af7041
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/smartdns.nix
@@ -0,0 +1,61 @@
+{ lib, pkgs, config, ... }:
+
+with lib;
+
+let
+ inherit (lib.types) attrsOf coercedTo listOf oneOf str int bool;
+ cfg = config.services.smartdns;
+
+ confFile = pkgs.writeText "smartdns.conf" (with generators;
+ toKeyValue {
+ mkKeyValue = mkKeyValueDefault {
+ mkValueString = v:
+ if isBool v then
+ if v then "yes" else "no"
+ else
+ mkValueStringDefault { } v;
+ } " ";
+ listsAsDuplicateKeys =
+ true; # Allowing duplications because we need to deal with multiple entries with the same key.
+ } cfg.settings);
+in {
+ options.services.smartdns = {
+ enable = mkEnableOption "SmartDNS DNS server";
+
+ bindPort = mkOption {
+ type = types.port;
+ default = 53;
+ description = "DNS listening port number.";
+ };
+
+ settings = mkOption {
+ type =
+ let atom = oneOf [ str int bool ];
+ in attrsOf (coercedTo atom toList (listOf atom));
+ example = literalExample ''
+ {
+ bind = ":5353 -no-rule -group example";
+ cache-size = 4096;
+ server-tls = [ "8.8.8.8:853" "1.1.1.1:853" ];
+ server-https = "https://cloudflare-dns.com/dns-query -exclude-default-group";
+ prefetch-domain = true;
+ speed-check-mode = "ping,tcp:80";
+ };
+ '';
+ description = ''
+ A set that will be generated into configuration file, see the <link xlink:href="https://github.com/pymumu/smartdns/blob/master/ReadMe_en.md#configuration-parameter">SmartDNS README</link> for details of configuration parameters.
+ You could override the options here like <option>services.smartdns.bindPort</option> by writing <literal>settings.bind = ":5353 -no-rule -group example";</literal>.
+ '';
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ services.smartdns.settings.bind = mkDefault ":${toString cfg.bindPort}";
+
+ systemd.packages = [ pkgs.smartdns ];
+ systemd.services.smartdns.wantedBy = [ "multi-user.target" ];
+ environment.etc."smartdns/smartdns.conf".source = confFile;
+ environment.etc."default/smartdns".source =
+ "${pkgs.smartdns}/etc/default/smartdns";
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/networking/ssh/sshd.nix b/nixpkgs/nixos/modules/services/networking/ssh/sshd.nix
index b0e2e303cbc..464e9ed38c4 100644
--- a/nixpkgs/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixpkgs/nixos/modules/services/networking/ssh/sshd.nix
@@ -17,7 +17,7 @@ let
${cfg.extraConfig}
EOL
- ssh-keygen -f mock-hostkey -N ""
+ ssh-keygen -q -f mock-hostkey -N ""
sshd -t -f $out -h mock-hostkey
'';
@@ -238,6 +238,26 @@ in
description = "Files from which authorized keys are read.";
};
+ authorizedKeysCommand = mkOption {
+ type = types.str;
+ default = "none";
+ description = ''
+ Specifies a program to be used to look up the user's public
+ keys. The program must be owned by root, not writable by group
+ or others and specified by an absolute path.
+ '';
+ };
+
+ authorizedKeysCommandUser = mkOption {
+ type = types.str;
+ default = "nobody";
+ description = ''
+ Specifies the user under whose account the AuthorizedKeysCommand
+ is run. It is recommended to use a dedicated user that has no
+ other role on the host than running authorized keys commands.
+ '';
+ };
+
kexAlgorithms = mkOption {
type = types.listOf types.str;
default = [
@@ -485,6 +505,10 @@ in
PrintMotd no # handled by pam_motd
AuthorizedKeysFile ${toString cfg.authorizedKeysFiles}
+ ${optionalString (cfg.authorizedKeysCommand != "none") ''
+ AuthorizedKeysCommand ${cfg.authorizedKeysCommand}
+ AuthorizedKeysCommandUser ${cfg.authorizedKeysCommandUser}
+ ''}
${flip concatMapStrings cfg.hostKeys (k: ''
HostKey ${k.path}
diff --git a/nixpkgs/nixos/modules/services/networking/sslh.nix b/nixpkgs/nixos/modules/services/networking/sslh.nix
index 0222e8ce8b5..c4fa370a5fe 100644
--- a/nixpkgs/nixos/modules/services/networking/sslh.nix
+++ b/nixpkgs/nixos/modules/services/networking/sslh.nix
@@ -77,19 +77,14 @@ in
config = mkMerge [
(mkIf cfg.enable {
- users.users.${user} = {
- description = "sslh daemon user";
- isSystemUser = true;
- };
-
systemd.services.sslh = {
description = "Applicative Protocol Multiplexer (e.g. share SSH and HTTPS on the same port)";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
- User = user;
- Group = "nogroup";
+ DynamicUser = true;
+ User = "sslh";
PermissionsStartOnly = true;
Restart = "always";
RestartSec = "1s";
diff --git a/nixpkgs/nixos/modules/services/networking/stubby.nix b/nixpkgs/nixos/modules/services/networking/stubby.nix
index b38bcd4cec0..c5e0f929a12 100644
--- a/nixpkgs/nixos/modules/services/networking/stubby.nix
+++ b/nixpkgs/nixos/modules/services/networking/stubby.nix
@@ -72,6 +72,7 @@ let
resolution_type: GETDNS_RESOLUTION_STUB
dns_transport_list:
${fallbacks}
+ appdata_dir: "/var/cache/stubby"
tls_authentication: ${cfg.authenticationMode}
tls_query_padding_blocksize: ${toString cfg.queryPaddingBlocksize}
edns_client_subnet_private: ${if cfg.subnetPrivate then "1" else "0"}
@@ -204,10 +205,12 @@ in
wantedBy = [ "multi-user.target" ];
serviceConfig = {
+ Type = "notify";
AmbientCapabilities = "CAP_NET_BIND_SERVICE";
CapabilityBoundingSet = "CAP_NET_BIND_SERVICE";
ExecStart = "${pkgs.stubby}/bin/stubby -C ${confFile} ${optionalString cfg.debugLogging "-l"}";
DynamicUser = true;
+ CacheDirectory = "stubby";
};
};
};
diff --git a/nixpkgs/nixos/modules/services/networking/supybot.nix b/nixpkgs/nixos/modules/services/networking/supybot.nix
index 92c84bd0e1e..dc9fb31ffd0 100644
--- a/nixpkgs/nixos/modules/services/networking/supybot.nix
+++ b/nixpkgs/nixos/modules/services/networking/supybot.nix
@@ -3,32 +3,35 @@
with lib;
let
-
cfg = config.services.supybot;
-
+ isStateDirHome = hasPrefix "/home/" cfg.stateDir;
+ isStateDirVar = cfg.stateDir == "/var/lib/supybot";
+ pyEnv = pkgs.python3.withPackages (p: [ p.limnoria ] ++ (cfg.extraPackages p));
in
-
{
-
options = {
services.supybot = {
enable = mkOption {
+ type = types.bool;
default = false;
- description = "Enable Supybot, an IRC bot";
+ description = "Enable Supybot, an IRC bot (also known as Limnoria).";
};
stateDir = mkOption {
- # Setting this to /var/lib/supybot caused useradd to fail
- default = "/home/supybot";
+ type = types.path;
+ default = if versionAtLeast config.system.stateVersion "20.09"
+ then "/var/lib/supybot"
+ else "/home/supybot";
+ defaultText = "/var/lib/supybot";
description = "The root directory, logs and plugins are stored here";
};
configFile = mkOption {
type = types.path;
description = ''
- Path to a supybot config file. This can be generated by
+ Path to initial supybot config file. This can be generated by
running supybot-wizard.
Note: all paths should include the full path to the stateDir
@@ -36,21 +39,54 @@ in
'';
};
+ plugins = mkOption {
+ type = types.attrsOf types.path;
+ default = {};
+ description = ''
+ Attribute set of additional plugins that will be symlinked to the
+ <filename>plugin</filename> subdirectory.
+
+ Please note that you still need to add the plugins to the config
+ file (or with <literal>!load</literal>) using their attribute name.
+ '';
+ example = literalExample ''
+ let
+ plugins = pkgs.fetchzip {
+ url = "https://github.com/ProgVal/Supybot-plugins/archive/57c2450c.zip";
+ sha256 = "077snf84ibnva3sbpzdfpfma6hcdw7dflwnhg6pw7mgnf0nd84qd";
+ };
+ in
+ {
+ Wikipedia = "''${plugins}/Wikipedia";
+ Decide = ./supy-decide;
+ }
+ '';
+ };
+
+ extraPackages = mkOption {
+ default = p: [];
+ description = ''
+ Extra Python packages available to supybot plugins. The
+ value must be a function which receives the attrset defined
+ in <varname>python3Packages</varname> as the sole argument.
+ '';
+ example = literalExample ''p: [ p.lxml p.requests ]'';
+ };
+
};
};
-
config = mkIf cfg.enable {
- environment.systemPackages = [ pkgs.pythonPackages.limnoria ];
+ environment.systemPackages = [ pkgs.python3Packages.limnoria ];
- users.users.supybotrs = {
+ users.users.supybot = {
uid = config.ids.uids.supybot;
group = "supybot";
description = "Supybot IRC bot user";
home = cfg.stateDir;
- createHome = true;
+ isSystemUser = true;
};
users.groups.supybot = {
@@ -59,19 +95,16 @@ in
systemd.services.supybot = {
description = "Supybot, an IRC bot";
+ documentation = [ "https://limnoria.readthedocs.io/" ];
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
- path = [ pkgs.pythonPackages.limnoria ];
preStart = ''
- cd ${cfg.stateDir}
- mkdir -p backup conf data plugins logs/plugins tmp web
- ln -sf ${cfg.configFile} supybot.cfg
# This needs to be created afresh every time
- rm -f supybot.cfg.bak
+ rm -f '${cfg.stateDir}/supybot.cfg.bak'
'';
serviceConfig = {
- ExecStart = "${pkgs.pythonPackages.limnoria}/bin/supybot ${cfg.stateDir}/supybot.cfg";
+ ExecStart = "${pyEnv}/bin/supybot ${cfg.stateDir}/supybot.cfg";
PIDFile = "/run/supybot.pid";
User = "supybot";
Group = "supybot";
@@ -79,8 +112,50 @@ in
Restart = "on-abort";
StartLimitInterval = "5m";
StartLimitBurst = "1";
+
+ NoNewPrivileges = true;
+ PrivateDevices = true;
+ PrivateMounts = true;
+ PrivateTmp = true;
+ ProtectControlGroups = true;
+ ProtectKernelModules = true;
+ ProtectKernelTunables = true;
+ RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+ RestrictSUIDSGID = true;
+ SystemCallArchitectures = "native";
+ RestrictNamespaces = true;
+ RestrictRealtime = true;
+ LockPersonality = true;
+ MemoryDenyWriteExecute = true;
+ RemoveIPC = true;
+ ProtectHostname = true;
+ CapabilityBoundingSet = "";
+ ProtectSystem = "full";
+ }
+ // optionalAttrs isStateDirVar {
+ StateDirectory = "supybot";
+ ProtectSystem = "strict";
+ }
+ // optionalAttrs (!isStateDirHome) {
+ ProtectHome = true;
};
};
+ systemd.tmpfiles.rules = [
+ "d '${cfg.stateDir}' 0700 supybot supybot - -"
+ "d '${cfg.stateDir}/backup' 0750 supybot supybot - -"
+ "d '${cfg.stateDir}/conf' 0750 supybot supybot - -"
+ "d '${cfg.stateDir}/data' 0750 supybot supybot - -"
+ "d '${cfg.stateDir}/plugins' 0750 supybot supybot - -"
+ "d '${cfg.stateDir}/logs' 0750 supybot supybot - -"
+ "d '${cfg.stateDir}/logs/plugins' 0750 supybot supybot - -"
+ "d '${cfg.stateDir}/tmp' 0750 supybot supybot - -"
+ "d '${cfg.stateDir}/web' 0750 supybot supybot - -"
+ "L '${cfg.stateDir}/supybot.cfg' - - - - ${cfg.configFile}"
+ ]
+ ++ (flip mapAttrsToList cfg.plugins (name: dest:
+ "L+ '${cfg.stateDir}/plugins/${name}' - - - - ${dest}"
+ ));
+
};
}
diff --git a/nixpkgs/nixos/modules/services/networking/tailscale.nix b/nixpkgs/nixos/modules/services/networking/tailscale.nix
new file mode 100644
index 00000000000..513c42b4011
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/networking/tailscale.nix
@@ -0,0 +1,46 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let cfg = config.services.tailscale;
+in {
+ meta.maintainers = with maintainers; [ danderson mbaillie ];
+
+ options.services.tailscale = {
+ enable = mkEnableOption "Tailscale client daemon";
+
+ port = mkOption {
+ type = types.port;
+ default = 41641;
+ description = "The port to listen on for tunnel traffic (0=autoselect).";
+ };
+ };
+
+ config = mkIf cfg.enable {
+ systemd.services.tailscale = {
+ description = "Tailscale client daemon";
+
+ after = [ "network-pre.target" ];
+ wants = [ "network-pre.target" ];
+ wantedBy = [ "multi-user.target" ];
+
+ unitConfig = {
+ StartLimitIntervalSec = 0;
+ StartLimitBurst = 0;
+ };
+
+ serviceConfig = {
+ ExecStart =
+ "${pkgs.tailscale}/bin/tailscaled --port ${toString cfg.port}";
+
+ RuntimeDirectory = "tailscale";
+ RuntimeDirectoryMode = 755;
+
+ StateDirectory = "tailscale";
+ StateDirectoryMode = 700;
+
+ Restart = "on-failure";
+ };
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/networking/vsftpd.nix b/nixpkgs/nixos/modules/services/networking/vsftpd.nix
index 47990dbb377..b3e20184423 100644
--- a/nixpkgs/nixos/modules/services/networking/vsftpd.nix
+++ b/nixpkgs/nixos/modules/services/networking/vsftpd.nix
@@ -133,8 +133,8 @@ let
${optionalString cfg.enableVirtualUsers ''
guest_enable=YES
guest_username=vsftpd
- pam_service_name=vsftpd
''}
+ pam_service_name=vsftpd
${cfg.extraConfig}
'';
diff --git a/nixpkgs/nixos/modules/services/networking/wireguard.nix b/nixpkgs/nixos/modules/services/networking/wireguard.nix
index 980961225c9..e8f83f6dd8b 100644
--- a/nixpkgs/nixos/modules/services/networking/wireguard.nix
+++ b/nixpkgs/nixos/modules/services/networking/wireguard.nix
@@ -151,7 +151,7 @@ let
publicKey = mkOption {
example = "xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=";
type = types.str;
- description = "The base64 public key the peer.";
+ description = "The base64 public key of the peer.";
};
presharedKey = mkOption {
@@ -428,14 +428,14 @@ in
++ (attrValues (
mapAttrs (name: value: {
assertion = value.generatePrivateKeyFile -> (value.privateKey == null);
- message = "networking.wireguard.interfaces.${name}.generatePrivateKey must not be set if networking.wireguard.interfaces.${name}.privateKey is set.";
+ message = "networking.wireguard.interfaces.${name}.generatePrivateKeyFile must not be set if networking.wireguard.interfaces.${name}.privateKey is set.";
}) cfg.interfaces))
++ map ({ interfaceName, peer, ... }: {
assertion = (peer.presharedKey == null) || (peer.presharedKeyFile == null);
message = "networking.wireguard.interfaces.${interfaceName} peer «${peer.publicKey}» has both presharedKey and presharedKeyFile set, but only one can be used.";
}) all_peers;
- boot.extraModulePackages = [ kernel.wireguard ];
+ boot.extraModulePackages = optional (versionOlder kernel.kernel.version "5.6") kernel.wireguard;
environment.systemPackages = [ pkgs.wireguard-tools ];
systemd.services =
diff --git a/nixpkgs/nixos/modules/services/networking/zerotierone.nix b/nixpkgs/nixos/modules/services/networking/zerotierone.nix
index 069e15a909b..cf39ed065a7 100644
--- a/nixpkgs/nixos/modules/services/networking/zerotierone.nix
+++ b/nixpkgs/nixos/modules/services/networking/zerotierone.nix
@@ -67,5 +67,16 @@ in
networking.firewall.allowedUDPPorts = [ cfg.port ];
environment.systemPackages = [ cfg.package ];
+
+ # Prevent systemd from potentially changing the MAC address
+ systemd.network.links."50-zerotier" = {
+ matchConfig = {
+ OriginalName = "zt*";
+ };
+ linkConfig = {
+ AutoNegotiation = false;
+ MACAddressPolicy = "none";
+ };
+ };
};
}
diff --git a/nixpkgs/nixos/modules/services/torrent/transmission.nix b/nixpkgs/nixos/modules/services/torrent/transmission.nix
index 5ba72e8d773..fd28b94f7be 100644
--- a/nixpkgs/nixos/modules/services/torrent/transmission.nix
+++ b/nixpkgs/nixos/modules/services/torrent/transmission.nix
@@ -23,7 +23,8 @@ let
for DIR in "${homeDir}" "${settingsDir}" "${fullSettings.download-dir}" "${fullSettings.incomplete-dir}"; do
mkdir -p "$DIR"
done
- chmod 700 "${homeDir}" "${settingsDir}"
+ chmod 755 "${homeDir}"
+ chmod 700 "${settingsDir}"
chmod ${downloadDirPermissions} "${fullSettings.download-dir}" "${fullSettings.incomplete-dir}"
cp -f ${settingsFile} ${settingsDir}/settings.json
'';
diff --git a/nixpkgs/nixos/modules/services/wayland/cage.nix b/nixpkgs/nixos/modules/services/wayland/cage.nix
new file mode 100644
index 00000000000..c59ca9983a6
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/wayland/cage.nix
@@ -0,0 +1,99 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+ cfg = config.services.cage;
+in {
+ options.services.cage.enable = mkEnableOption "cage kiosk service";
+
+ options.services.cage.user = mkOption {
+ type = types.str;
+ default = "demo";
+ description = ''
+ User to log-in as.
+ '';
+ };
+
+ options.services.cage.extraArguments = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ defaultText = "[]";
+ description = "Additional command line arguments to pass to Cage.";
+ example = ["-d"];
+ };
+
+ options.services.cage.program = mkOption {
+ type = types.path;
+ default = "${pkgs.xterm}/bin/xterm";
+ description = ''
+ Program to run in cage.
+ '';
+ };
+
+ config = mkIf cfg.enable {
+
+ # The service is partially based off of the one provided in the
+ # cage wiki at
+ # https://github.com/Hjdskes/cage/wiki/Starting-Cage-on-boot-with-systemd.
+ systemd.services."cage-tty1" = {
+ enable = true;
+ after = [
+ "systemd-user-sessions.service"
+ "plymouth-start.service"
+ "plymouth-quit.service"
+ "systemd-logind.service"
+ "getty@tty1.service"
+ ];
+ before = [ "graphical.target" ];
+ wants = [ "dbus.socket" "systemd-logind.service" "plymouth-quit.service"];
+ wantedBy = [ "graphical.target" ];
+ conflicts = [ "getty@tty1.service" ];
+
+ restartIfChanged = false;
+ unitConfig.ConditionPathExists = "/dev/tty1";
+ serviceConfig = {
+ ExecStart = ''
+ ${pkgs.cage}/bin/cage \
+ ${escapeShellArgs cfg.extraArguments} \
+ -- ${cfg.program}
+ '';
+ User = cfg.user;
+
+ IgnoreSIGPIPE = "no";
+
+ # Log this user with utmp, letting it show up with commands 'w' and
+ # 'who'. This is needed since we replace (a)getty.
+ UtmpIdentifier = "%n";
+ UtmpMode = "user";
+ # A virtual terminal is needed.
+ TTYPath = "/dev/tty1";
+ TTYReset = "yes";
+ TTYVHangup = "yes";
+ TTYVTDisallocate = "yes";
+ # Fail to start if not controlling the virtual terminal.
+ StandardInput = "tty-fail";
+ StandardOutput = "syslog";
+ StandardError = "syslog";
+ # Set up a full (custom) user session for the user, required by Cage.
+ PAMName = "cage";
+ };
+ };
+
+ security.pam.services.cage.text = ''
+ auth required pam_unix.so nullok
+ account required pam_unix.so
+ session required pam_unix.so
+ session required ${pkgs.systemd}/lib/security/pam_systemd.so
+ '';
+
+ hardware.opengl.enable = mkDefault true;
+
+ systemd.targets.graphical.wants = [ "cage-tty1.service" ];
+
+ systemd.defaultUnit = "graphical.target";
+ };
+
+ meta.maintainers = with lib.maintainers; [ matthewbauer flokli ];
+
+}
diff --git a/nixpkgs/nixos/modules/services/web-apps/codimd.nix b/nixpkgs/nixos/modules/services/web-apps/codimd.nix
index 5f56f8ed5a0..751f81649dd 100644
--- a/nixpkgs/nixos/modules/services/web-apps/codimd.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/codimd.nix
@@ -156,7 +156,7 @@ in
};
useCDN = mkOption {
type = types.bool;
- default = true;
+ default = false;
description = ''
Whether to use CDN resources or not.
'';
diff --git a/nixpkgs/nixos/modules/services/web-apps/grocy.nix b/nixpkgs/nixos/modules/services/web-apps/grocy.nix
new file mode 100644
index 00000000000..568bdfd0c42
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/web-apps/grocy.nix
@@ -0,0 +1,172 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.grocy;
+in {
+ options.services.grocy = {
+ enable = mkEnableOption "grocy";
+
+ hostName = mkOption {
+ type = types.str;
+ description = ''
+ FQDN for the grocy instance.
+ '';
+ };
+
+ nginx.enableSSL = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether or not to enable SSL (with ACME and let's encrypt)
+ for the grocy vhost.
+ '';
+ };
+
+ phpfpm.settings = mkOption {
+ type = with types; attrsOf (oneOf [ int str bool ]);
+ default = {
+ "pm" = "dynamic";
+ "php_admin_value[error_log]" = "stderr";
+ "php_admin_flag[log_errors]" = true;
+ "listen.owner" = "nginx";
+ "catch_workers_output" = true;
+ "pm.max_children" = "32";
+ "pm.start_servers" = "2";
+ "pm.min_spare_servers" = "2";
+ "pm.max_spare_servers" = "4";
+ "pm.max_requests" = "500";
+ };
+
+ description = ''
+ Options for grocy's PHPFPM pool.
+ '';
+ };
+
+ dataDir = mkOption {
+ type = types.str;
+ default = "/var/lib/grocy";
+ description = ''
+ Home directory of the <literal>grocy</literal> user which contains
+ the application's state.
+ '';
+ };
+
+ settings = {
+ currency = mkOption {
+ type = types.str;
+ default = "USD";
+ example = "EUR";
+ description = ''
+ ISO 4217 code for the currency to display.
+ '';
+ };
+
+ culture = mkOption {
+ type = types.enum [ "de" "en" "da" "en_GB" "es" "fr" "hu" "it" "nl" "no" "pl" "pt_BR" "ru" "sk_SK" "sv_SE" "tr" ];
+ default = "en";
+ description = ''
+ Display language of the frontend.
+ '';
+ };
+
+ calendar = {
+ showWeekNumber = mkOption {
+ default = true;
+ type = types.bool;
+ description = ''
+ Show the number of the weeks in the calendar views.
+ '';
+ };
+ firstDayOfWeek = mkOption {
+ default = null;
+ type = types.nullOr (types.enum (range 0 6));
+ description = ''
+ Which day of the week (0=Sunday, 1=Monday etc.) should be the
+ first day.
+ '';
+ };
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ environment.etc."grocy/config.php".text = ''
+ <?php
+ Setting('CULTURE', '${cfg.settings.culture}');
+ Setting('CURRENCY', '${cfg.settings.currency}');
+ Setting('CALENDAR_FIRST_DAY_OF_WEEK', '${toString cfg.settings.calendar.firstDayOfWeek}');
+ Setting('CALENDAR_SHOW_WEEK_OF_YEAR', ${boolToString cfg.settings.calendar.showWeekNumber});
+ '';
+
+ users.users.grocy = {
+ isSystemUser = true;
+ createHome = true;
+ home = cfg.dataDir;
+ group = "nginx";
+ };
+
+ systemd.tmpfiles.rules = map (
+ dirName: "d '${cfg.dataDir}/${dirName}' - grocy nginx - -"
+ ) [ "viewcache" "plugins" "settingoverrides" "storage" ];
+
+ services.phpfpm.pools.grocy = {
+ user = "grocy";
+ group = "nginx";
+
+ # PHP 7.3 is the only version which is supported/tested by upstream:
+ # https://github.com/grocy/grocy/blob/v2.6.0/README.md#how-to-install
+ phpPackage = pkgs.php73;
+
+ inherit (cfg.phpfpm) settings;
+
+ phpEnv = {
+ GROCY_CONFIG_FILE = "/etc/grocy/config.php";
+ GROCY_DB_FILE = "${cfg.dataDir}/grocy.db";
+ GROCY_STORAGE_DIR = "${cfg.dataDir}/storage";
+ GROCY_PLUGIN_DIR = "${cfg.dataDir}/plugins";
+ GROCY_CACHE_DIR = "${cfg.dataDir}/viewcache";
+ };
+ };
+
+ services.nginx = {
+ enable = true;
+ virtualHosts."${cfg.hostName}" = mkMerge [
+ { root = "${pkgs.grocy}/public";
+ locations."/".extraConfig = ''
+ rewrite ^ /index.php;
+ '';
+ locations."~ \\.php$".extraConfig = ''
+ fastcgi_split_path_info ^(.+\.php)(/.+)$;
+ fastcgi_pass unix:${config.services.phpfpm.pools.grocy.socket};
+ include ${config.services.nginx.package}/conf/fastcgi.conf;
+ include ${config.services.nginx.package}/conf/fastcgi_params;
+ '';
+ locations."~ \\.(js|css|ttf|woff2?|png|jpe?g|svg)$".extraConfig = ''
+ add_header Cache-Control "public, max-age=15778463";
+ add_header X-Content-Type-Options nosniff;
+ add_header X-XSS-Protection "1; mode=block";
+ add_header X-Robots-Tag none;
+ add_header X-Download-Options noopen;
+ add_header X-Permitted-Cross-Domain-Policies none;
+ add_header Referrer-Policy no-referrer;
+ access_log off;
+ '';
+ extraConfig = ''
+ try_files $uri /index.php;
+ '';
+ }
+ (mkIf cfg.nginx.enableSSL {
+ enableACME = true;
+ forceSSL = true;
+ })
+ ];
+ };
+ };
+
+ meta = {
+ maintainers = with maintainers; [ ma27 ];
+ doc = ./grocy.xml;
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/web-apps/grocy.xml b/nixpkgs/nixos/modules/services/web-apps/grocy.xml
new file mode 100644
index 00000000000..fdf6d00f4b1
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/web-apps/grocy.xml
@@ -0,0 +1,77 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ version="5.0"
+ xml:id="module-services-grocy">
+
+ <title>Grocy</title>
+ <para>
+ <link xlink:href="https://grocy.info/">Grocy</link> is a web-based self-hosted groceries
+ &amp; household management solution for your home.
+ </para>
+
+ <section xml:id="module-services-grocy-basic-usage">
+ <title>Basic usage</title>
+ <para>
+ A very basic configuration may look like this:
+<programlisting>{ pkgs, ... }:
+{
+ services.grocy = {
+ <link linkend="opt-services.grocy.enable">enable</link> = true;
+ <link linkend="opt-services.grocy.hostName">hostName</link> = "grocy.tld";
+ };
+}</programlisting>
+ This configures a simple vhost using <link linkend="opt-services.nginx.enable">nginx</link>
+ which listens to <literal>grocy.tld</literal> with fully configured ACME/LE (this can be
+ disabled by setting <link linkend="opt-services.grocy.nginx.enableSSL">services.grocy.nginx.enableSSL</link>
+ to <literal>false</literal>). After the initial setup the credentials <literal>admin:admin</literal>
+ can be used to login.
+ </para>
+ <para>
+ The application's state is persisted at <literal>/var/lib/grocy/grocy.db</literal> in a
+ <package>sqlite3</package> database. The migration is applied when requesting the <literal>/</literal>-route
+ of the application.
+ </para>
+ </section>
+
+ <section xml:id="module-services-grocy-settings">
+ <title>Settings</title>
+ <para>
+ The configuration for <literal>grocy</literal> is located at <literal>/etc/grocy/config.php</literal>.
+ By default, the following settings can be defined in the NixOS-configuration:
+<programlisting>{ pkgs, ... }:
+{
+ services.grocy.settings = {
+ # The default currency in the system for invoices etc.
+ # Please note that exchange rates aren't taken into account, this
+ # is just the setting for what's shown in the frontend.
+ <link linkend="opt-services.grocy.settings.currency">currency</link> = "EUR";
+
+ # The display language (and locale configuration) for grocy.
+ <link linkend="opt-services.grocy.settings.currency">culture</link> = "de";
+
+ calendar = {
+ # Whether or not to show the week-numbers
+ # in the calendar.
+ <link linkend="opt-services.grocy.settings.calendar.showWeekNumber">showWeekNumber</link> = true;
+
+ # Index of the first day to be shown in the calendar (0=Sunday, 1=Monday,
+ # 2=Tuesday and so on).
+ <link linkend="opt-services.grocy.settings.calendar.firstDayOfWeek">firstDayOfWeek</link> = 2;
+ };
+ };
+}</programlisting>
+ </para>
+ <para>
+ If you want to alter the configuration file on your own, you can do this manually with
+ an expression like this:
+<programlisting>{ lib, ... }:
+{
+ environment.etc."grocy/config.php".text = lib.mkAfter ''
+ // Arbitrary PHP code in grocy's configuration file
+ '';
+}</programlisting>
+ </para>
+ </section>
+
+</chapter>
diff --git a/nixpkgs/nixos/modules/services/web-apps/jirafeau.nix b/nixpkgs/nixos/modules/services/web-apps/jirafeau.nix
new file mode 100644
index 00000000000..4f181257ef7
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/web-apps/jirafeau.nix
@@ -0,0 +1,169 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+ cfg = config.services.jirafeau;
+
+ group = config.services.nginx.group;
+ user = config.services.nginx.user;
+
+ withTrailingSlash = str: if hasSuffix "/" str then str else "${str}/";
+
+ localConfig = pkgs.writeText "config.local.php" ''
+ <?php
+ $cfg['admin_password'] = '${cfg.adminPasswordSha256}';
+ $cfg['web_root'] = 'http://${withTrailingSlash cfg.hostName}';
+ $cfg['var_root'] = '${withTrailingSlash cfg.dataDir}';
+ $cfg['maximal_upload_size'] = ${builtins.toString cfg.maxUploadSizeMegabytes};
+ $cfg['installation_done'] = true;
+
+ ${cfg.extraConfig}
+ '';
+in
+{
+ options.services.jirafeau = {
+ adminPasswordSha256 = mkOption {
+ type = types.str;
+ default = "";
+ description = ''
+ SHA-256 of the desired administration password. Leave blank/unset for no password.
+ '';
+ };
+
+ dataDir = mkOption {
+ type = types.path;
+ default = "/var/lib/jirafeau/data/";
+ description = "Location of Jirafeau storage directory.";
+ };
+
+ enable = mkEnableOption "Jirafeau file upload application.";
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ example = ''
+ $cfg['style'] = 'courgette';
+ $cfg['organisation'] = 'ACME';
+ '';
+ description = let
+ documentationLink =
+ "https://gitlab.com/mojo42/Jirafeau/-/blob/${cfg.package.version}/lib/config.original.php";
+ in
+ ''
+ Jirefeau configuration. Refer to <link xlink:href="${documentationLink}"/> for supported
+ values.
+ '';
+ };
+
+ hostName = mkOption {
+ type = types.str;
+ default = "localhost";
+ description = "URL of instance. Must have trailing slash.";
+ };
+
+ maxUploadSizeMegabytes = mkOption {
+ type = types.int;
+ default = 0;
+ description = "Maximum upload size of accepted files.";
+ };
+
+ maxUploadTimeout = mkOption {
+ type = types.str;
+ default = "30m";
+ description = let
+ nginxCoreDocumentation = "http://nginx.org/en/docs/http/ngx_http_core_module.html";
+ in
+ ''
+ Timeout for reading client request bodies and headers. Refer to
+ <link xlink:href="${nginxCoreDocumentation}#client_body_timeout"/> and
+ <link xlink:href="${nginxCoreDocumentation}#client_header_timeout"/> for accepted values.
+ '';
+ };
+
+ nginxConfig = mkOption {
+ type = types.submodule
+ (import ../web-servers/nginx/vhost-options.nix { inherit config lib; });
+ default = {};
+ example = {
+ serverAliases = [ "wiki.\${config.networking.domain}" ];
+ };
+ description = "Extra configuration for the nginx virtual host of Jirafeau.";
+ };
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.jirafeau;
+ defaultText = "pkgs.jirafeau";
+ description = "Jirafeau package to use";
+ example = "pkgs.jirafeau";
+ };
+
+ poolConfig = mkOption {
+ type = with types; attrsOf (oneOf [ str int bool ]);
+ default = {
+ "pm" = "dynamic";
+ "pm.max_children" = 32;
+ "pm.start_servers" = 2;
+ "pm.min_spare_servers" = 2;
+ "pm.max_spare_servers" = 4;
+ "pm.max_requests" = 500;
+ };
+ description = ''
+ Options for Jirafeau PHP pool. See documentation on <literal>php-fpm.conf</literal> for
+ details on configuration directives.
+ '';
+ };
+ };
+
+
+ config = mkIf cfg.enable {
+ services = {
+ nginx = {
+ enable = true;
+ virtualHosts."${cfg.hostName}" = mkMerge [
+ cfg.nginxConfig
+ {
+ extraConfig = let
+ clientMaxBodySize =
+ if cfg.maxUploadSizeMegabytes == 0 then "0" else "${cfg.maxUploadSizeMegabytes}m";
+ in
+ ''
+ index index.php;
+ client_max_body_size ${clientMaxBodySize};
+ client_body_timeout ${cfg.maxUploadTimeout};
+ client_header_timeout ${cfg.maxUploadTimeout};
+ '';
+ locations = {
+ "~ \\.php$".extraConfig = ''
+ include ${pkgs.nginx}/conf/fastcgi_params;
+ fastcgi_split_path_info ^(.+\.php)(/.+)$;
+ fastcgi_index index.php;
+ fastcgi_pass unix:${config.services.phpfpm.pools.jirafeau.socket};
+ fastcgi_param PATH_INFO $fastcgi_path_info;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ '';
+ };
+ root = mkForce "${cfg.package}";
+ }
+ ];
+ };
+
+ phpfpm.pools.jirafeau = {
+ inherit group user;
+ phpEnv."JIRAFEAU_CONFIG" = "${localConfig}";
+ settings = {
+ "listen.mode" = "0660";
+ "listen.owner" = user;
+ "listen.group" = group;
+ } // cfg.poolConfig;
+ };
+ };
+
+ systemd.tmpfiles.rules = [
+ "d ${cfg.dataDir} 0750 ${user} ${group} - -"
+ "d ${cfg.dataDir}/files/ 0750 ${user} ${group} - -"
+ "d ${cfg.dataDir}/links/ 0750 ${user} ${group} - -"
+ "d ${cfg.dataDir}/async/ 0750 ${user} ${group} - -"
+ ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/web-apps/limesurvey.nix b/nixpkgs/nixos/modules/services/web-apps/limesurvey.nix
index e00a47191c6..56265e80957 100644
--- a/nixpkgs/nixos/modules/services/web-apps/limesurvey.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/limesurvey.nix
@@ -100,7 +100,7 @@ in
};
virtualHost = mkOption {
- type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix);
+ type = types.submodule (import ../web-servers/apache-httpd/vhost-options.nix);
example = literalExample ''
{
hostName = "survey.example.org";
diff --git a/nixpkgs/nixos/modules/services/web-apps/mattermost.nix b/nixpkgs/nixos/modules/services/web-apps/mattermost.nix
index 41c52b9653b..853347bf86e 100644
--- a/nixpkgs/nixos/modules/services/web-apps/mattermost.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/mattermost.nix
@@ -6,14 +6,18 @@ let
cfg = config.services.mattermost;
- defaultConfig = builtins.fromJSON (readFile "${pkgs.mattermost}/config/config.json");
+ defaultConfig = builtins.fromJSON (builtins.replaceStrings [ "\\u0026" ] [ "&" ]
+ (readFile "${pkgs.mattermost}/config/config.json")
+ );
+
+ database = "postgres://${cfg.localDatabaseUser}:${cfg.localDatabasePassword}@localhost:5432/${cfg.localDatabaseName}?sslmode=disable&connect_timeout=10";
mattermostConf = foldl recursiveUpdate defaultConfig
[ { ServiceSettings.SiteURL = cfg.siteUrl;
ServiceSettings.ListenAddress = cfg.listenAddress;
TeamSettings.SiteName = cfg.siteName;
SqlSettings.DriverName = "postgres";
- SqlSettings.DataSource = "postgres://${cfg.localDatabaseUser}:${cfg.localDatabasePassword}@localhost:5432/${cfg.localDatabaseName}?sslmode=disable&connect_timeout=10";
+ SqlSettings.DataSource = database;
}
cfg.extraConfig
];
@@ -175,7 +179,9 @@ in
mkdir -p ${cfg.statePath}/{data,config,logs}
ln -sf ${pkgs.mattermost}/{bin,fonts,i18n,templates,client} ${cfg.statePath}
'' + lib.optionalString (!cfg.mutableConfig) ''
- ln -sf ${mattermostConfJSON} ${cfg.statePath}/config/config.json
+ rm -f ${cfg.statePath}/config/config.json
+ cp ${mattermostConfJSON} ${cfg.statePath}/config/config.json
+ ${pkgs.mattermost}/bin/mattermost config migrate ${cfg.statePath}/config/config.json ${database}
'' + lib.optionalString cfg.mutableConfig ''
if ! test -e "${cfg.statePath}/config/.initial-created"; then
rm -f ${cfg.statePath}/config/config.json
@@ -201,7 +207,8 @@ in
PermissionsStartOnly = true;
User = cfg.user;
Group = cfg.group;
- ExecStart = "${pkgs.mattermost}/bin/mattermost";
+ ExecStart = "${pkgs.mattermost}/bin/mattermost" +
+ (lib.optionalString (!cfg.mutableConfig) " -c ${database}");
WorkingDirectory = "${cfg.statePath}";
Restart = "always";
RestartSec = "10";
@@ -227,4 +234,3 @@ in
})
];
}
-
diff --git a/nixpkgs/nixos/modules/services/web-apps/mediawiki.nix b/nixpkgs/nixos/modules/services/web-apps/mediawiki.nix
index 8a109b39bb5..e9ed53857d8 100644
--- a/nixpkgs/nixos/modules/services/web-apps/mediawiki.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/mediawiki.nix
@@ -290,7 +290,7 @@ in
};
virtualHost = mkOption {
- type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix);
+ type = types.submodule (import ../web-servers/apache-httpd/vhost-options.nix);
example = literalExample ''
{
hostName = "mediawiki.example.org";
diff --git a/nixpkgs/nixos/modules/services/web-apps/moodle.nix b/nixpkgs/nixos/modules/services/web-apps/moodle.nix
index 595d070d940..1196780cf6e 100644
--- a/nixpkgs/nixos/modules/services/web-apps/moodle.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/moodle.nix
@@ -140,7 +140,7 @@ in
};
virtualHost = mkOption {
- type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix);
+ type = types.submodule (import ../web-servers/apache-httpd/vhost-options.nix);
example = literalExample ''
{
hostName = "moodle.example.org";
diff --git a/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix b/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix
index d79f2bb735f..912e05d6d40 100644
--- a/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/nextcloud.nix
@@ -443,7 +443,7 @@ in {
pools.nextcloud = {
user = "nextcloud";
group = "nginx";
- phpOptions = phpOptionsExtensions + phpOptionsStr;
+ phpOptions = phpOptionsStr;
phpPackage = phpPackage;
phpEnv = {
NEXTCLOUD_CONFIG_DIR = "${cfg.home}/config";
@@ -533,6 +533,7 @@ in {
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
+ add_header X-Frame-Options sameorigin;
add_header Referrer-Policy no-referrer;
access_log off;
'';
@@ -547,6 +548,7 @@ in {
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
+ add_header X-Frame-Options sameorigin;
add_header Referrer-Policy no-referrer;
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
error_page 403 /core/templates/403.php;
diff --git a/nixpkgs/nixos/modules/services/web-apps/wordpress.nix b/nixpkgs/nixos/modules/services/web-apps/wordpress.nix
index ad4f39fbf52..c48a4409737 100644
--- a/nixpkgs/nixos/modules/services/web-apps/wordpress.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/wordpress.nix
@@ -209,7 +209,7 @@ let
};
virtualHost = mkOption {
- type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix);
+ type = types.submodule (import ../web-servers/apache-httpd/vhost-options.nix);
example = literalExample ''
{
adminAddr = "webmaster@example.org";
diff --git a/nixpkgs/nixos/modules/services/web-apps/zabbix.nix b/nixpkgs/nixos/modules/services/web-apps/zabbix.nix
index ee8447810c6..00719512834 100644
--- a/nixpkgs/nixos/modules/services/web-apps/zabbix.nix
+++ b/nixpkgs/nixos/modules/services/web-apps/zabbix.nix
@@ -113,7 +113,7 @@ in
};
virtualHost = mkOption {
- type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix);
+ type = types.submodule (import ../web-servers/apache-httpd/vhost-options.nix);
example = literalExample ''
{
hostName = "zabbix.example.org";
diff --git a/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix
index 9942c63acce..832c8b30ee9 100644
--- a/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/apache-httpd/default.nix
@@ -4,21 +4,21 @@ with lib;
let
- mainCfg = config.services.httpd;
+ cfg = config.services.httpd;
runtimeDir = "/run/httpd";
- httpd = mainCfg.package.out;
+ pkg = cfg.package.out;
- httpdConf = mainCfg.configFile;
+ httpdConf = cfg.configFile;
- php = mainCfg.phpPackage.override { apacheHttpd = httpd.dev; /* otherwise it only gets .out */ };
+ php = cfg.phpPackage.override { apacheHttpd = pkg.dev; /* otherwise it only gets .out */ };
phpMajorVersion = lib.versions.major (lib.getVersion php);
- mod_perl = pkgs.apacheHttpdPackages.mod_perl.override { apacheHttpd = httpd; };
+ mod_perl = pkgs.apacheHttpdPackages.mod_perl.override { apacheHttpd = pkg; };
- vhosts = attrValues mainCfg.virtualHosts;
+ vhosts = attrValues cfg.virtualHosts;
mkListenInfo = hostOpts:
if hostOpts.listen != [] then hostOpts.listen
@@ -29,8 +29,8 @@ let
listenInfo = unique (concatMap mkListenInfo vhosts);
+ enableHttp2 = any (vhost: vhost.http2) vhosts;
enableSSL = any (listen: listen.ssl) listenInfo;
-
enableUserDir = any (vhost: vhost.enableUserDir) vhosts;
# NOTE: generally speaking order of modules is very important
@@ -41,23 +41,19 @@ let
"mime" "autoindex" "negotiation" "dir"
"alias" "rewrite"
"unixd" "slotmem_shm" "socache_shmcb"
- "mpm_${mainCfg.multiProcessingModule}"
+ "mpm_${cfg.multiProcessingModule}"
]
- ++ (if mainCfg.multiProcessingModule == "prefork" then [ "cgi" ] else [ "cgid" ])
+ ++ (if cfg.multiProcessingModule == "prefork" then [ "cgi" ] else [ "cgid" ])
+ ++ optional enableHttp2 "http2"
++ optional enableSSL "ssl"
++ optional enableUserDir "userdir"
- ++ optional mainCfg.enableMellon { name = "auth_mellon"; path = "${pkgs.apacheHttpdPackages.mod_auth_mellon}/modules/mod_auth_mellon.so"; }
- ++ optional mainCfg.enablePHP { name = "php${phpMajorVersion}"; path = "${php}/modules/libphp${phpMajorVersion}.so"; }
- ++ optional mainCfg.enablePerl { name = "perl"; path = "${mod_perl}/modules/mod_perl.so"; }
- ++ mainCfg.extraModules;
-
-
- allDenied = "Require all denied";
- allGranted = "Require all granted";
+ ++ optional cfg.enableMellon { name = "auth_mellon"; path = "${pkgs.apacheHttpdPackages.mod_auth_mellon}/modules/mod_auth_mellon.so"; }
+ ++ optional cfg.enablePHP { name = "php${phpMajorVersion}"; path = "${php}/modules/libphp${phpMajorVersion}.so"; }
+ ++ optional cfg.enablePerl { name = "perl"; path = "${mod_perl}/modules/mod_perl.so"; }
+ ++ cfg.extraModules;
-
- loggingConf = (if mainCfg.logFormat != "none" then ''
- ErrorLog ${mainCfg.logDir}/error.log
+ loggingConf = (if cfg.logFormat != "none" then ''
+ ErrorLog ${cfg.logDir}/error.log
LogLevel notice
@@ -66,7 +62,7 @@ let
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
- CustomLog ${mainCfg.logDir}/access.log ${mainCfg.logFormat}
+ CustomLog ${cfg.logDir}/access.log ${cfg.logFormat}
'' else ''
ErrorLog /dev/null
'');
@@ -88,34 +84,36 @@ let
sslConf = ''
- SSLSessionCache shmcb:${runtimeDir}/ssl_scache(512000)
+ <IfModule mod_ssl.c>
+ SSLSessionCache shmcb:${runtimeDir}/ssl_scache(512000)
- Mutex posixsem
+ Mutex posixsem
- SSLRandomSeed startup builtin
- SSLRandomSeed connect builtin
+ SSLRandomSeed startup builtin
+ SSLRandomSeed connect builtin
- SSLProtocol ${mainCfg.sslProtocols}
- SSLCipherSuite ${mainCfg.sslCiphers}
- SSLHonorCipherOrder on
+ SSLProtocol ${cfg.sslProtocols}
+ SSLCipherSuite ${cfg.sslCiphers}
+ SSLHonorCipherOrder on
+ </IfModule>
'';
mimeConf = ''
- TypesConfig ${httpd}/conf/mime.types
+ TypesConfig ${pkg}/conf/mime.types
AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl .crl
AddType application/x-httpd-php .php .phtml
<IfModule mod_mime_magic.c>
- MIMEMagicFile ${httpd}/conf/magic
+ MIMEMagicFile ${pkg}/conf/magic
</IfModule>
'';
mkVHostConf = hostOpts:
let
- adminAddr = if hostOpts.adminAddr != null then hostOpts.adminAddr else mainCfg.adminAddr;
+ adminAddr = if hostOpts.adminAddr != null then hostOpts.adminAddr else cfg.adminAddr;
listen = filter (listen: !listen.ssl) (mkListenInfo hostOpts);
listenSSL = filter (listen: listen.ssl) (mkListenInfo hostOpts);
@@ -167,6 +165,7 @@ let
SSLCertificateFile ${sslServerCert}
SSLCertificateKeyFile ${sslServerKey}
${optionalString (sslServerChain != null) "SSLCertificateChainFile ${sslServerChain}"}
+ ${optionalString hostOpts.http2 "Protocols h2 h2c http/1.1"}
${acmeChallenge}
${mkVHostCommonConf hostOpts}
</VirtualHost>
@@ -203,9 +202,9 @@ let
'') (sortProperties (mapAttrsToList (k: v: v // { location = k; }) locations)));
in
''
- ${optionalString mainCfg.logPerVirtualHost ''
- ErrorLog ${mainCfg.logDir}/error-${hostOpts.hostName}.log
- CustomLog ${mainCfg.logDir}/access-${hostOpts.hostName}.log ${hostOpts.logFormat}
+ ${optionalString cfg.logPerVirtualHost ''
+ ErrorLog ${cfg.logDir}/error-${hostOpts.hostName}.log
+ CustomLog ${cfg.logDir}/access-${hostOpts.hostName}.log ${hostOpts.logFormat}
''}
${optionalString (hostOpts.robotsEntries != "") ''
@@ -217,7 +216,7 @@ let
<Directory "${documentRoot}">
Options Indexes FollowSymLinks
AllowOverride None
- ${allGranted}
+ Require all granted
</Directory>
${optionalString hostOpts.enableUserDir ''
@@ -244,7 +243,7 @@ let
Alias ${elem.urlPath} ${elem.dir}/
<Directory ${elem.dir}>
Options +Indexes
- ${allGranted}
+ Require all granted
AllowOverride All
</Directory>
'';
@@ -259,20 +258,20 @@ let
confFile = pkgs.writeText "httpd.conf" ''
- ServerRoot ${httpd}
+ ServerRoot ${pkg}
ServerName ${config.networking.hostName}
DefaultRuntimeDir ${runtimeDir}/runtime
PidFile ${runtimeDir}/httpd.pid
- ${optionalString (mainCfg.multiProcessingModule != "prefork") ''
+ ${optionalString (cfg.multiProcessingModule != "prefork") ''
# mod_cgid requires this.
ScriptSock ${runtimeDir}/cgisock
''}
<IfModule prefork.c>
- MaxClients ${toString mainCfg.maxClients}
- MaxRequestsPerChild ${toString mainCfg.maxRequestsPerChild}
+ MaxClients ${toString cfg.maxClients}
+ MaxRequestsPerChild ${toString cfg.maxRequestsPerChild}
</IfModule>
${let
@@ -281,12 +280,12 @@ let
in concatStringsSep "\n" uniqueListen
}
- User ${mainCfg.user}
- Group ${mainCfg.group}
+ User ${cfg.user}
+ Group ${cfg.group}
${let
mkModule = module:
- if isString module then { name = module; path = "${httpd}/modules/mod_${module}.so"; }
+ if isString module then { name = module; path = "${pkg}/modules/mod_${module}.so"; }
else if isAttrs module then { inherit (module) name path; }
else throw "Expecting either a string or attribute set including a name and path.";
in
@@ -296,37 +295,37 @@ let
AddHandler type-map var
<Files ~ "^\.ht">
- ${allDenied}
+ Require all denied
</Files>
${mimeConf}
${loggingConf}
${browserHacks}
- Include ${httpd}/conf/extra/httpd-default.conf
- Include ${httpd}/conf/extra/httpd-autoindex.conf
- Include ${httpd}/conf/extra/httpd-multilang-errordoc.conf
- Include ${httpd}/conf/extra/httpd-languages.conf
+ Include ${pkg}/conf/extra/httpd-default.conf
+ Include ${pkg}/conf/extra/httpd-autoindex.conf
+ Include ${pkg}/conf/extra/httpd-multilang-errordoc.conf
+ Include ${pkg}/conf/extra/httpd-languages.conf
TraceEnable off
- ${if enableSSL then sslConf else ""}
+ ${sslConf}
# Fascist default - deny access to everything.
<Directory />
Options FollowSymLinks
AllowOverride None
- ${allDenied}
+ Require all denied
</Directory>
# But do allow access to files in the store so that we don't have
# to generate <Directory> clauses for every generated file that we
# want to serve.
<Directory /nix/store>
- ${allGranted}
+ Require all granted
</Directory>
- ${mainCfg.extraConfig}
+ ${cfg.extraConfig}
${concatMapStringsSep "\n" mkVHostConf vhosts}
'';
@@ -334,7 +333,7 @@ let
# Generate the PHP configuration file. Should probably be factored
# out into a separate module.
phpIni = pkgs.runCommand "php.ini"
- { options = mainCfg.phpOptions;
+ { options = cfg.phpOptions;
preferLocalBuild = true;
}
''
@@ -367,17 +366,13 @@ in
(mkRemovedOptionModule [ "services" "httpd" "sslServerKey" ] "Please define a virtual host using `services.httpd.virtualHosts`.")
];
- ###### interface
+ # interface
options = {
services.httpd = {
- enable = mkOption {
- type = types.bool;
- default = false;
- description = "Whether to enable the Apache HTTP Server.";
- };
+ enable = mkEnableOption "the Apache HTTP Server";
package = mkOption {
type = types.package;
@@ -404,7 +399,7 @@ in
default = "";
description = ''
Configuration lines appended to the generated Apache
- configuration file. Note that this mechanism may not work
+ configuration file. Note that this mechanism will not work
when <option>configFile</option> is overridden.
'';
};
@@ -419,7 +414,7 @@ in
]
'';
description = ''
- Additional Apache modules to be used. These can be
+ Additional Apache modules to be used. These can be
specified as a string in the case of modules distributed
with Apache, or as an attribute set specifying the
<varname>name</varname> and <varname>path</varname> of the
@@ -458,8 +453,7 @@ in
type = types.str;
default = "wwwrun";
description = ''
- User account under which httpd runs. The account is created
- automatically if it doesn't exist.
+ User account under which httpd runs.
'';
};
@@ -467,8 +461,7 @@ in
type = types.str;
default = "wwwrun";
description = ''
- Group under which httpd runs. The account is created
- automatically if it doesn't exist.
+ Group under which httpd runs.
'';
};
@@ -476,15 +469,15 @@ in
type = types.path;
default = "/var/log/httpd";
description = ''
- Directory for Apache's log files. It is created automatically.
+ Directory for Apache's log files. It is created automatically.
'';
};
virtualHosts = mkOption {
- type = with types; attrsOf (submodule (import ./per-server-options.nix));
+ type = with types; attrsOf (submodule (import ./vhost-options.nix));
default = {
localhost = {
- documentRoot = "${httpd}/htdocs";
+ documentRoot = "${pkg}/htdocs";
};
};
example = literalExample ''
@@ -540,17 +533,18 @@ in
''
date.timezone = "CET"
'';
- description =
- "Options appended to the PHP configuration file <filename>php.ini</filename>.";
+ description = ''
+ Options appended to the PHP configuration file <filename>php.ini</filename>.
+ '';
};
multiProcessingModule = mkOption {
- type = types.str;
+ type = types.enum [ "event" "prefork" "worker" ];
default = "prefork";
example = "worker";
description =
''
- Multi-processing module to be used by Apache. Available
+ Multi-processing module to be used by Apache. Available
modules are <literal>prefork</literal> (the default;
handles each request in a separate child process),
<literal>worker</literal> (hybrid approach that starts a
@@ -572,8 +566,9 @@ in
type = types.int;
default = 0;
example = 500;
- description =
- "Maximum number of httpd requests answered per httpd child (prefork), 0 means unlimited";
+ description = ''
+ Maximum number of httpd requests answered per httpd child (prefork), 0 means unlimited.
+ '';
};
sslCiphers = mkOption {
@@ -592,10 +587,9 @@ in
};
+ # implementation
- ###### implementation
-
- config = mkIf config.services.httpd.enable {
+ config = mkIf cfg.enable {
assertions = [
{
@@ -626,30 +620,30 @@ in
warnings =
mapAttrsToList (name: hostOpts: ''
Using config.services.httpd.virtualHosts."${name}".servedFiles is deprecated and will become unsupported in a future release. Your configuration will continue to work as is but please migrate your configuration to config.services.httpd.virtualHosts."${name}".locations before the 20.09 release of NixOS.
- '') (filterAttrs (name: hostOpts: hostOpts.servedFiles != []) mainCfg.virtualHosts);
+ '') (filterAttrs (name: hostOpts: hostOpts.servedFiles != []) cfg.virtualHosts);
- users.users = optionalAttrs (mainCfg.user == "wwwrun") {
+ users.users = optionalAttrs (cfg.user == "wwwrun") {
wwwrun = {
- group = mainCfg.group;
+ group = cfg.group;
description = "Apache httpd user";
uid = config.ids.uids.wwwrun;
};
};
- users.groups = optionalAttrs (mainCfg.group == "wwwrun") {
+ users.groups = optionalAttrs (cfg.group == "wwwrun") {
wwwrun.gid = config.ids.gids.wwwrun;
};
security.acme.certs = mapAttrs (name: hostOpts: {
- user = mainCfg.user;
- group = mkDefault mainCfg.group;
- email = if hostOpts.adminAddr != null then hostOpts.adminAddr else mainCfg.adminAddr;
+ user = cfg.user;
+ group = mkDefault cfg.group;
+ email = if hostOpts.adminAddr != null then hostOpts.adminAddr else cfg.adminAddr;
webroot = hostOpts.acmeRoot;
extraDomains = genAttrs hostOpts.serverAliases (alias: null);
postRun = "systemctl reload httpd.service";
- }) (filterAttrs (name: hostOpts: hostOpts.enableACME) mainCfg.virtualHosts);
+ }) (filterAttrs (name: hostOpts: hostOpts.enableACME) cfg.virtualHosts);
- environment.systemPackages = [httpd];
+ environment.systemPackages = [ pkg ];
# required for "apachectl configtest"
environment.etc."httpd/httpd.conf".source = httpdConf;
@@ -689,6 +683,15 @@ in
"access_compat"
];
+ systemd.tmpfiles.rules =
+ let
+ svc = config.systemd.services.httpd.serviceConfig;
+ in
+ [
+ "d '${cfg.logDir}' 0700 ${svc.User} ${svc.Group}"
+ "Z '${cfg.logDir}' - ${svc.User} ${svc.Group}"
+ ];
+
systemd.services.httpd =
let
vhostsACME = filter (hostOpts: hostOpts.enableACME) vhosts;
@@ -700,35 +703,36 @@ in
after = [ "network.target" "fs.target" ] ++ map (hostOpts: "acme-selfsigned-${hostOpts.hostName}.service") vhostsACME;
path =
- [ httpd pkgs.coreutils pkgs.gnugrep ]
- ++ optional mainCfg.enablePHP pkgs.system-sendmail; # Needed for PHP's mail() function.
+ [ pkg pkgs.coreutils pkgs.gnugrep ]
+ ++ optional cfg.enablePHP pkgs.system-sendmail; # Needed for PHP's mail() function.
environment =
- optionalAttrs mainCfg.enablePHP { PHPRC = phpIni; }
- // optionalAttrs mainCfg.enableMellon { LD_LIBRARY_PATH = "${pkgs.xmlsec}/lib"; };
+ optionalAttrs cfg.enablePHP { PHPRC = phpIni; }
+ // optionalAttrs cfg.enableMellon { LD_LIBRARY_PATH = "${pkgs.xmlsec}/lib"; };
preStart =
''
- mkdir -m 0700 -p ${mainCfg.logDir}
-
# Get rid of old semaphores. These tend to accumulate across
# server restarts, eventually preventing it from restarting
# successfully.
- for i in $(${pkgs.utillinux}/bin/ipcs -s | grep ' ${mainCfg.user} ' | cut -f2 -d ' '); do
+ for i in $(${pkgs.utillinux}/bin/ipcs -s | grep ' ${cfg.user} ' | cut -f2 -d ' '); do
${pkgs.utillinux}/bin/ipcrm -s $i
done
'';
- serviceConfig.ExecStart = "@${httpd}/bin/httpd httpd -f ${httpdConf}";
- serviceConfig.ExecStop = "${httpd}/bin/httpd -f ${httpdConf} -k graceful-stop";
- serviceConfig.ExecReload = "${httpd}/bin/httpd -f ${httpdConf} -k graceful";
- serviceConfig.Group = mainCfg.group;
- serviceConfig.Type = "forking";
- serviceConfig.PIDFile = "${runtimeDir}/httpd.pid";
- serviceConfig.Restart = "always";
- serviceConfig.RestartSec = "5s";
- serviceConfig.RuntimeDirectory = "httpd httpd/runtime";
- serviceConfig.RuntimeDirectoryMode = "0750";
+ serviceConfig = {
+ ExecStart = "@${pkg}/bin/httpd httpd -f ${httpdConf}";
+ ExecStop = "${pkg}/bin/httpd -f ${httpdConf} -k graceful-stop";
+ ExecReload = "${pkg}/bin/httpd -f ${httpdConf} -k graceful";
+ User = "root";
+ Group = cfg.group;
+ Type = "forking";
+ PIDFile = "${runtimeDir}/httpd.pid";
+ Restart = "always";
+ RestartSec = "5s";
+ RuntimeDirectory = "httpd httpd/runtime";
+ RuntimeDirectoryMode = "0750";
+ };
};
};
diff --git a/nixpkgs/nixos/modules/services/web-servers/apache-httpd/per-server-options.nix b/nixpkgs/nixos/modules/services/web-servers/apache-httpd/vhost-options.nix
index f34f8b4acdf..263980add8b 100644
--- a/nixpkgs/nixos/modules/services/web-servers/apache-httpd/per-server-options.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/apache-httpd/vhost-options.nix
@@ -135,6 +135,15 @@ in
description = "Path to server SSL chain file.";
};
+ http2 = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to enable HTTP 2. HTTP/2 is supported in all multi-processing modules that come with httpd. <emphasis>However, if you use the prefork mpm, there will
+ be severe restrictions.</emphasis> Refer to <link xlink:href="https://httpd.apache.org/docs/2.4/howto/http2.html#mpm-config"/> for details.
+ '';
+ };
+
adminAddr = mkOption {
type = types.nullOr types.str;
default = null;
diff --git a/nixpkgs/nixos/modules/services/web-servers/caddy.nix b/nixpkgs/nixos/modules/services/web-servers/caddy.nix
index 132c50735d9..0e6e10a5f47 100644
--- a/nixpkgs/nixos/modules/services/web-servers/caddy.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/caddy.nix
@@ -64,32 +64,38 @@ in {
config = mkIf cfg.enable {
systemd.services.caddy = {
description = "Caddy web server";
+ # upstream unit: https://github.com/caddyserver/caddy/blob/master/dist/init/linux-systemd/caddy.service
after = [ "network-online.target" ];
+ wants = [ "network-online.target" ]; # systemd-networkd-wait-online.service
wantedBy = [ "multi-user.target" ];
environment = mkIf (versionAtLeast config.system.stateVersion "17.09")
{ CADDYPATH = cfg.dataDir; };
serviceConfig = {
ExecStart = ''
- ${cfg.package}/bin/caddy -root=/var/tmp -conf=${configFile} \
+ ${cfg.package}/bin/caddy -log stdout -log-timestamps=false \
+ -root=/var/tmp -conf=${configFile} \
-ca=${cfg.ca} -email=${cfg.email} ${optionalString cfg.agree "-agree"}
'';
- ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+ ExecReload = "${pkgs.coreutils}/bin/kill -USR1 $MAINPID";
Type = "simple";
User = "caddy";
Group = "caddy";
- Restart = "on-failure";
- StartLimitInterval = 86400;
- StartLimitBurst = 5;
+ Restart = "on-abnormal";
+ StartLimitIntervalSec = 14400;
+ StartLimitBurst = 10;
AmbientCapabilities = "cap_net_bind_service";
CapabilityBoundingSet = "cap_net_bind_service";
NoNewPrivileges = true;
- LimitNPROC = 64;
+ LimitNPROC = 512;
LimitNOFILE = 1048576;
PrivateTmp = true;
PrivateDevices = true;
ProtectHome = true;
ProtectSystem = "full";
ReadWriteDirectories = cfg.dataDir;
+ KillMode = "mixed";
+ KillSignal = "SIGQUIT";
+ TimeoutStopSec = "5s";
};
};
diff --git a/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix b/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix
index c8602e5975b..28b433104a1 100644
--- a/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/nginx/default.nix
@@ -87,10 +87,17 @@ let
${optionalString (cfg.sslDhparam != null) "ssl_dhparam ${cfg.sslDhparam};"}
${optionalString (cfg.recommendedTlsSettings) ''
- ssl_session_cache shared:SSL:42m;
- ssl_session_timeout 23m;
- ssl_ecdh_curve secp384r1;
- ssl_prefer_server_ciphers on;
+ # Keep in sync with https://ssl-config.mozilla.org/#server=nginx&config=intermediate
+
+ ssl_session_timeout 1d;
+ ssl_session_cache shared:SSL:10m;
+ # Breaks forward secrecy: https://github.com/mozilla/server-side-tls/issues/135
+ ssl_session_tickets off;
+ # We don't enable insecure ciphers by default, so this allows
+ # clients to pick the most performant, per https://github.com/mozilla/server-side-tls/issues/260
+ ssl_prefer_server_ciphers off;
+
+ # OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
''}
@@ -487,8 +494,9 @@ in
sslCiphers = mkOption {
type = types.str;
- default = "EECDH+aRSA+AESGCM:EDH+aRSA:EECDH+aRSA:+AES256:+AES128:+SHA1:!CAMELLIA:!SEED:!3DES:!DES:!RC4:!eNULL";
- description = "Ciphers to choose from when negotiating tls handshakes.";
+ # Keep in sync with https://ssl-config.mozilla.org/#server=nginx&config=intermediate
+ default = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
+ description = "Ciphers to choose from when negotiating TLS handshakes.";
};
sslProtocols = mkOption {
diff --git a/nixpkgs/nixos/modules/services/web-servers/uwsgi.nix b/nixpkgs/nixos/modules/services/web-servers/uwsgi.nix
index 3481b5e6040..4b74c329e3d 100644
--- a/nixpkgs/nixos/modules/services/web-servers/uwsgi.nix
+++ b/nixpkgs/nixos/modules/services/web-servers/uwsgi.nix
@@ -32,7 +32,7 @@ let
inherit plugins;
} // removeAttrs c [ "type" "pythonPackages" ]
// optionalAttrs (python != null) {
- pythonpath = "${pythonEnv}/${python.sitePackages}";
+ pyhome = "${pythonEnv}";
env =
# Argh, uwsgi expects list of key-values there instead of a dictionary.
let env' = c.env or [];
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix
index 4a6f2ca727d..910a246d776 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix
@@ -86,6 +86,7 @@ in
pkgs.shared-mime-info
pkgs.xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/
pkgs.mate.mate-settings-daemon
+ pkgs.yelp # for 'Contents' in 'Help' menus
];
programs.dconf.enable = true;
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix
index b46a2d189ef..869c6694489 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix
@@ -16,7 +16,10 @@ in
{
- meta.maintainers = pkgs.pantheon.maintainers;
+ meta = {
+ doc = ./pantheon.xml;
+ maintainers = pkgs.pantheon.maintainers;
+ };
options = {
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.xml b/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.xml
new file mode 100644
index 00000000000..4d92a7446c0
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.xml
@@ -0,0 +1,130 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xml:id="chap-pantheon">
+ <title>Pantheon Destkop</title>
+ <para>
+ Pantheon is the desktop environment created for the elementary OS distribution. It is written from scratch in Vala, utilizing GNOME technologies with GTK 3 and Granite.
+ </para>
+ <section xml:id="sec-pantheon-enable">
+ <title>Enabling Pantheon</title>
+
+ <para>
+ All of Pantheon is working in NixOS and the applications should be available, aside from a few <link xlink:href="https://github.com/NixOS/nixpkgs/issues/58161">exceptions</link>. To enable Pantheon, set
+<programlisting>
+<xref linkend="opt-services.xserver.desktopManager.pantheon.enable"/> = true;
+</programlisting>
+ This automatically enables LightDM and Pantheon's LightDM greeter. If you'd like to disable this, set
+<programlisting>
+<xref linkend="opt-services.xserver.displayManager.lightdm.greeters.pantheon.enable"/> = false;
+<xref linkend="opt-services.xserver.displayManager.lightdm.enable"/> = false;
+</programlisting>
+ but please be aware using Pantheon without LightDM as a display manager will break screenlocking from the UI. The NixOS module for Pantheon installs all of Pantheon's default applications. If you'd like to not install Pantheon's apps, set
+<programlisting>
+<xref linkend="opt-services.pantheon.apps.enable"/> = false;
+</programlisting>
+ You can also use <xref linkend="opt-environment.pantheon.excludePackages"/> to remove any other app (like <package>geary</package>).
+ </para>
+ </section>
+ <section xml:id="sec-pantheon-wingpanel-switchboard">
+ <title>Wingpanel and Switchboard plugins</title>
+
+ <para>
+ Wingpanel and Switchboard work differently than they do in other distributions, as far as using plugins. You cannot install a plugin globally (like with <option>environment.systemPackages</option>) to start using it. You should instead be using the following options:
+ <itemizedlist>
+ <listitem>
+ <para>
+ <xref linkend="opt-services.xserver.desktopManager.pantheon.extraWingpanelIndicators"/>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <xref linkend="opt-services.xserver.desktopManager.pantheon.extraSwitchboardPlugs"/>
+ </para>
+ </listitem>
+ </itemizedlist>
+ to configure the programs with plugs or indicators.
+ </para>
+
+ <para>
+ The difference in NixOS is both these programs are patched to load plugins from a directory that is the value of an environment variable. All of which is controlled in Nix. If you need to configure the particular packages manually you can override the packages like:
+<programlisting>
+wingpanel-with-indicators.override {
+ indicators = [
+ pkgs.some-special-indicator
+ ];
+};
+
+switchboard-with-plugs.override {
+ plugs = [
+ pkgs.some-special-plug
+ ];
+};
+</programlisting>
+ please note that, like how the NixOS options describe these as extra plugins, this would only add to the default plugins included with the programs. If for some reason you'd like to configure which plugins to use exactly, both packages have an argument for this:
+<programlisting>
+wingpanel-with-indicators.override {
+ useDefaultIndicators = false;
+ indicators = specialListOfIndicators;
+};
+
+switchboard-with-plugs.override {
+ useDefaultPlugs = false;
+ plugs = specialListOfPlugs;
+};
+</programlisting>
+ this could be most useful for testing a particular plug-in in isolation.
+ </para>
+ </section>
+ <section xml:id="sec-pantheon-faq">
+ <title>FAQ</title>
+
+ <variablelist>
+ <varlistentry xml:id="sec-pantheon-faq-messed-up-theme">
+ <term>
+ I have switched from a different desktop and Pantheon’s theming looks messed up.
+ </term>
+ <listitem>
+ <para>
+ Open Switchboard and go to: <guilabel>Administration</guilabel> → <guilabel>About</guilabel> → <guilabel>Restore Default Settings</guilabel> → <guibutton>Restore Settings</guibutton>. This will reset any dconf settings to their Pantheon defaults. Note this could reset certain GNOME specific preferences if that desktop was used prior.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry xml:id="sec-pantheon-faq-slow-shutdown">
+ <term>
+ Using Pantheon sometimes makes my shutdown take a long time.
+ </term>
+ <listitem>
+ <para>
+ We have not yet determined what processes fight with systemd during shutdown, there are many reports. In elementary OS the default system timeout is lowered to lessen the impact of the issue. If you'd like to do this in NixOS, set
+<programlisting>
+ <xref linkend="opt-systemd.extraConfig"/> = ''
+ DefaultTimeoutStopSec=10s
+ DefaultTimeoutStartSec=10s
+'';
+</programlisting>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry xml:id="sec-pantheon-faq-gnome3-and-pantheon">
+ <term>
+ I cannot enable both GNOME 3 and Pantheon.
+ </term>
+ <listitem>
+ <para>
+ This is a known <link xlink:href="https://github.com/NixOS/nixpkgs/issues/64611">issue</link> and there is no known workaround.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry xml:id="sec-pantheon-faq-appcenter">
+ <term>
+ Does AppCenter work, or is it available?
+ </term>
+ <listitem>
+ <para>
+ AppCenter has been available since 20.03, but it is of little use. This is because there is no functioning PackageKit backend for Nix 2.0. In the near future you will be able to install Flatpak applications from AppCenter on NixOS. See this <link xlink:href="https://github.com/NixOS/nixpkgs/issues/70214">issue</link>.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+</chapter>
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix
index 2538858ac0f..60ef0159ff1 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix
@@ -8,6 +8,137 @@ let
cfg = xcfg.desktopManager.plasma5;
inherit (pkgs) kdeApplications plasma5 libsForQt5 qt5;
+ inherit (pkgs) writeText;
+
+ pulseaudio = config.hardware.pulseaudio;
+ pactl = "${getBin pulseaudio.package}/bin/pactl";
+ startplasma-x11 = "${getBin plasma5.plasma-workspace}/bin/startplasma-x11";
+ sed = "${getBin pkgs.gnused}/bin/sed";
+
+ gtkrc2 = writeText "gtkrc-2.0" ''
+ # Default GTK+ 2 config for NixOS Plasma 5
+ include "/run/current-system/sw/share/themes/Breeze/gtk-2.0/gtkrc"
+ style "user-font"
+ {
+ font_name="Sans Serif Regular"
+ }
+ widget_class "*" style "user-font"
+ gtk-font-name="Sans Serif Regular 10"
+ gtk-theme-name="Breeze"
+ gtk-icon-theme-name="breeze"
+ gtk-fallback-icon-theme="hicolor"
+ gtk-cursor-theme-name="breeze_cursors"
+ gtk-toolbar-style=GTK_TOOLBAR_ICONS
+ gtk-menu-images=1
+ gtk-button-images=1
+ '';
+
+ gtk3_settings = writeText "settings.ini" ''
+ [Settings]
+ gtk-font-name=Sans Serif Regular 10
+ gtk-theme-name=Breeze
+ gtk-icon-theme-name=breeze
+ gtk-fallback-icon-theme=hicolor
+ gtk-cursor-theme-name=breeze_cursors
+ gtk-toolbar-style=GTK_TOOLBAR_ICONS
+ gtk-menu-images=1
+ gtk-button-images=1
+ '';
+
+ kcminputrc = writeText "kcminputrc" ''
+ [Mouse]
+ cursorTheme=breeze_cursors
+ cursorSize=0
+ '';
+
+ activationScript = ''
+ ${set_XDG_CONFIG_HOME}
+
+ # The KDE icon cache is supposed to update itself automatically, but it uses
+ # the timestamp on the icon theme directory as a trigger. This doesn't work
+ # on NixOS because the timestamp never changes. As a workaround, delete the
+ # icon cache at login and session activation.
+ # See also: http://lists-archives.org/kde-devel/26175-what-when-will-icon-cache-refresh.html
+ rm -fv $HOME/.cache/icon-cache.kcache
+
+ # xdg-desktop-settings generates this empty file but
+ # it makes kbuildsyscoca5 fail silently. To fix this
+ # remove that menu if it exists.
+ rm -fv ''${XDG_CONFIG_HOME}/menus/applications-merged/xdg-desktop-menu-dummy.menu
+
+ # Qt writes a weird ‘libraryPath’ line to
+ # ~/.config/Trolltech.conf that causes the KDE plugin
+ # paths of previous KDE invocations to be searched.
+ # Obviously using mismatching KDE libraries is potentially
+ # disastrous, so here we nuke references to the Nix store
+ # in Trolltech.conf. A better solution would be to stop
+ # Qt from doing this wackiness in the first place.
+ trolltech_conf="''${XDG_CONFIG_HOME}/Trolltech.conf"
+ if [ -e "$trolltech_conf" ]; then
+ ${sed} -i "$trolltech_conf" -e '/nix\\store\|nix\/store/ d'
+ fi
+
+ # Remove the kbuildsyscoca5 cache. It will be regenerated
+ # immediately after. This is necessary for kbuildsyscoca5 to
+ # recognize that software that has been removed.
+ rm -fv $HOME/.cache/ksycoca*
+
+ ${pkgs.libsForQt5.kservice}/bin/kbuildsycoca5
+ '';
+
+ set_XDG_CONFIG_HOME = ''
+ # Set the default XDG_CONFIG_HOME if it is unset.
+ # Per the XDG Base Directory Specification:
+ # https://specifications.freedesktop.org/basedir-spec/latest
+ # 1. Never export this variable! If it is unset, then child processes are
+ # expected to set the default themselves.
+ # 2. Contaminate / if $HOME is unset; do not check if $HOME is set.
+ XDG_CONFIG_HOME=''${XDG_CONFIG_HOME:-$HOME/.config}
+ '';
+
+ startplasma =
+ ''
+ ${set_XDG_CONFIG_HOME}
+ mkdir -p "''${XDG_CONFIG_HOME}"
+
+ ''
+ + optionalString pulseaudio.enable ''
+ # Load PulseAudio module for routing support.
+ # See also: http://colin.guthr.ie/2009/10/so-how-does-the-kde-pulseaudio-support-work-anyway/
+ ${pactl} load-module module-device-manager "do_routing=1"
+
+ ''
+ + ''
+ ${activationScript}
+
+ # Create default configurations if Plasma has never been started.
+ kdeglobals="''${XDG_CONFIG_HOME}/kdeglobals"
+ if ! [ -f "$kdeglobals" ]
+ then
+ kcminputrc="''${XDG_CONFIG_HOME}/kcminputrc"
+ if ! [ -f "$kcminputrc" ]
+ then
+ cat ${kcminputrc} >"$kcminputrc"
+ fi
+
+ gtkrc2="$HOME/.gtkrc-2.0"
+ if ! [ -f "$gtkrc2" ]
+ then
+ cat ${gtkrc2} >"$gtkrc2"
+ fi
+
+ gtk3_settings="''${XDG_CONFIG_HOME}/gtk-3.0/settings.ini"
+ if ! [ -f "$gtk3_settings" ]
+ then
+ mkdir -p "$(dirname "$gtk3_settings")"
+ cat ${gtk3_settings} >"$gtk3_settings"
+ fi
+ fi
+
+ ''
+ + ''
+ exec "${startplasma-x11}"
+ '';
in
@@ -41,27 +172,7 @@ in
services.xserver.desktopManager.session = singleton {
name = "plasma5";
bgSupport = true;
- start = ''
- # Load PulseAudio module for routing support.
- # See http://colin.guthr.ie/2009/10/so-how-does-the-kde-pulseaudio-support-work-anyway/
- ${optionalString config.hardware.pulseaudio.enable ''
- ${getBin config.hardware.pulseaudio.package}/bin/pactl load-module module-device-manager "do_routing=1"
- ''}
-
- if [ -f "$HOME/.config/kdeglobals" ]
- then
- # Remove extraneous font style names.
- # See also: https://phabricator.kde.org/D9070
- ${getBin pkgs.gnused}/bin/sed -i "$HOME/.config/kdeglobals" \
- -e '/^fixed=/ s/,Regular$//' \
- -e '/^font=/ s/,Regular$//' \
- -e '/^menuFont=/ s/,Regular$//' \
- -e '/^smallestReadableFont=/ s/,Regular$//' \
- -e '/^toolBarFont=/ s/,Regular$//'
- fi
-
- exec "${getBin plasma5.plasma-workspace}/bin/startkde"
- '';
+ start = startplasma;
};
security.wrappers = {
@@ -137,6 +248,7 @@ in
libkscreen
libksysguard
milou
+ plasma-browser-integration
plasma-integration
polkit-kde-agent
systemsettings
@@ -226,29 +338,7 @@ in
xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-kde ];
# Update the start menu for each user that is currently logged in
- system.userActivationScripts.plasmaSetup = ''
- # The KDE icon cache is supposed to update itself
- # automatically, but it uses the timestamp on the icon
- # theme directory as a trigger. Since in Nix the
- # timestamp is always the same, this doesn't work. So as
- # a workaround, nuke the icon cache on login. This isn't
- # perfect, since it may require logging out after
- # installing new applications to update the cache.
- # See http://lists-archives.org/kde-devel/26175-what-when-will-icon-cache-refresh.html
- rm -fv $HOME/.cache/icon-cache.kcache
-
- # xdg-desktop-settings generates this empty file but
- # it makes kbuildsyscoca5 fail silently. To fix this
- # remove that menu if it exists.
- rm -fv $HOME/.config/menus/applications-merged/xdg-desktop-menu-dummy.menu
-
- # Remove the kbuildsyscoca5 cache. It will be regenerated
- # immediately after. This is necessary for kbuildsyscoca5 to
- # recognize that software that has been removed.
- rm -fv $HOME/.cache/ksycoca*
-
- ${pkgs.libsForQt5.kservice}/bin/kbuildsycoca5
- '';
+ system.userActivationScripts.plasmaSetup = activationScript;
})
];
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/xfce.nix
index 21f59074f3a..a08b1947f65 100644
--- a/nixpkgs/nixos/modules/services/x11/desktop-managers/xfce.nix
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/xfce.nix
@@ -127,9 +127,14 @@ in
"/share/gtksourceview-4.0"
];
- services.xserver.displayManager.sessionPackages = [
- pkgs.xfce.xfce4-session
- ];
+ services.xserver.desktopManager.session = [{
+ name = "xfce";
+ bgSupport = true;
+ start = ''
+ ${pkgs.runtimeShell} ${pkgs.xfce.xfce4-session.xinitrc} &
+ waitPID=$!
+ '';
+ }];
services.xserver.updateDbusEnvironment = true;
services.xserver.gdk-pixbuf.modulePackages = [ pkgs.librsvg ];
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/default.nix b/nixpkgs/nixos/modules/services/x11/display-managers/default.nix
index 1efd0739376..5d49ca94387 100644
--- a/nixpkgs/nixos/modules/services/x11/display-managers/default.nix
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/default.nix
@@ -141,9 +141,11 @@ let
'';
dmDefault = cfg.desktopManager.default;
+ # fallback default for cases when only default wm is set
+ dmFallbackDefault = if dmDefault != null then dmDefault else "none";
wmDefault = cfg.windowManager.default;
- defaultSessionFromLegacyOptions = concatStringsSep "+" (filter (s: s != null) ([ dmDefault ] ++ optional (wmDefault != "none") wmDefault));
+ defaultSessionFromLegacyOptions = dmFallbackDefault + optionalString (wmDefault != null && wmDefault != "none") "+${wmDefault}";
in
@@ -358,7 +360,7 @@ in
{ c = wmDefault; t = "- services.xserver.windowManager.default"; }
]))}
Please use
- services.xserver.displayManager.defaultSession = "${concatStringsSep "+" (filter (s: s != null) [ dmDefault wmDefault ])}";
+ services.xserver.displayManager.defaultSession = "${defaultSessionFromLegacyOptions}";
instead.
''
];
@@ -425,6 +427,7 @@ in
TryExec=${script}
Exec=${script}
Name=${sessionName}
+ DesktopNames=${sessionName}
'';
} // {
providedSessions = [ sessionName ];
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/gdm.nix b/nixpkgs/nixos/modules/services/x11/display-managers/gdm.nix
index 325023f4121..e0ac47bb766 100644
--- a/nixpkgs/nixos/modules/services/x11/display-managers/gdm.nix
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/gdm.nix
@@ -166,9 +166,10 @@ in
};
systemd.tmpfiles.rules = [
- "d /run/gdm/.config 0711 gdm gdm -"
+ "d /run/gdm/.config 0711 gdm gdm"
] ++ optionals config.hardware.pulseaudio.enable [
- "L+ /run/gdm/.config/pulse - - - - ${pulseConfig}"
+ "d /run/gdm/.config/pulse 0711 gdm gdm"
+ "L+ /run/gdm/.config/pulse/${pulseConfig.name} - - - - ${pulseConfig}"
] ++ optionals config.services.gnome3.gnome-initial-setup.enable [
# Create stamp file for gnome-initial-setup to prevent it starting in GDM.
"f /run/gdm/.config/gnome-initial-setup-done 0711 gdm gdm - yes"
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/tiny.nix b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/tiny.nix
new file mode 100644
index 00000000000..a9ba8e6280d
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/tiny.nix
@@ -0,0 +1,92 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ dmcfg = config.services.xserver.displayManager;
+ ldmcfg = dmcfg.lightdm;
+ cfg = ldmcfg.greeters.tiny;
+
+in
+{
+ options = {
+
+ services.xserver.displayManager.lightdm.greeters.tiny = {
+
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to enable lightdm-tiny-greeter as the lightdm greeter.
+
+ Note that this greeter starts only the default X session.
+ You can configure the default X session using
+ <xref linkend="opt-services.xserver.displayManager.defaultSession"/>.
+ '';
+ };
+
+ label = {
+ user = mkOption {
+ type = types.str;
+ default = "Username";
+ description = ''
+ The string to represent the user_text label.
+ '';
+ };
+
+ pass = mkOption {
+ type = types.str;
+ default = "Password";
+ description = ''
+ The string to represent the pass_text label.
+ '';
+ };
+ };
+
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Section to describe style and ui.
+ '';
+ };
+
+ };
+
+ };
+
+ config = mkIf (ldmcfg.enable && cfg.enable) {
+
+ services.xserver.displayManager.lightdm.greeters.gtk.enable = false;
+
+ nixpkgs.config.lightdm-tiny-greeter.conf =
+ let
+ configHeader = ''
+ #include <gtk/gtk.h>
+ static const char *user_text = "${cfg.label.user}";
+ static const char *pass_text = "${cfg.label.pass}";
+ static const char *session = "${dmcfg.defaultSession}";
+ '';
+ in
+ optionalString (cfg.extraConfig != "")
+ (configHeader + cfg.extraConfig);
+
+ services.xserver.displayManager.lightdm.greeter =
+ mkDefault {
+ package = pkgs.lightdm-tiny-greeter.xgreeters;
+ name = "lightdm-tiny-greeter";
+ };
+
+ assertions = [
+ {
+ assertion = dmcfg.defaultSession != null;
+ message = ''
+ Please set: services.xserver.displayManager.defaultSession
+ '';
+ }
+ ];
+
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/lightdm.nix b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm.nix
index f7face0adb7..cb7b5f95958 100644
--- a/nixpkgs/nixos/modules/services/x11/display-managers/lightdm.nix
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm.nix
@@ -77,6 +77,7 @@ in
./lightdm-greeters/mini.nix
./lightdm-greeters/enso-os.nix
./lightdm-greeters/pantheon.nix
+ ./lightdm-greeters/tiny.nix
];
options = {
diff --git a/nixpkgs/nixos/modules/services/x11/unclutter.nix b/nixpkgs/nixos/modules/services/x11/unclutter.nix
index c0868604a68..56e30c79d1f 100644
--- a/nixpkgs/nixos/modules/services/x11/unclutter.nix
+++ b/nixpkgs/nixos/modules/services/x11/unclutter.nix
@@ -61,7 +61,7 @@ in {
serviceConfig.ExecStart = ''
${cfg.package}/bin/unclutter \
-idle ${toString cfg.timeout} \
- -jitter ${toString (cfg.threeshold - 1)} \
+ -jitter ${toString (cfg.threshold - 1)} \
${optionalString cfg.keystroke "-keystroke"} \
${concatMapStrings (x: " -"+x) cfg.extraOptions} \
-not ${concatStringsSep " " cfg.excluded} \
diff --git a/nixpkgs/nixos/modules/services/x11/urxvtd.nix b/nixpkgs/nixos/modules/services/x11/urxvtd.nix
index 9bfcfa9b065..867ac38a944 100644
--- a/nixpkgs/nixos/modules/services/x11/urxvtd.nix
+++ b/nixpkgs/nixos/modules/services/x11/urxvtd.nix
@@ -18,10 +18,10 @@ in {
};
package = mkOption {
- default = pkgs.rxvt_unicode-with-plugins;
- defaultText = "pkgs.rxvt_unicode-with-plugins";
+ default = pkgs.rxvt-unicode;
+ defaultText = "pkgs.rxvt-unicode";
description = ''
- Package to install. Usually pkgs.rxvt_unicode-with-plugins or pkgs.rxvt_unicode
+ Package to install. Usually pkgs.rxvt-unicode.
'';
type = types.package;
};
diff --git a/nixpkgs/nixos/modules/services/x11/xserver.nix b/nixpkgs/nixos/modules/services/x11/xserver.nix
index 7f0de96d208..74d702ea1c3 100644
--- a/nixpkgs/nixos/modules/services/x11/xserver.nix
+++ b/nixpkgs/nixos/modules/services/x11/xserver.nix
@@ -573,7 +573,7 @@ in
then { modules = [xorg.${"xf86video" + name}]; }
else null)
knownVideoDrivers;
- in optional (driver != null) ({ inherit name; modules = []; driverName = name; } // driver));
+ in optional (driver != null) ({ inherit name; modules = []; driverName = name; display = true; } // driver));
assertions = [
{ assertion = config.security.polkit.enable;
@@ -740,7 +740,7 @@ in
${cfg.serverLayoutSection}
# Reference the Screen sections for each driver. This will
# cause the X server to try each in turn.
- ${flip concatMapStrings cfg.drivers (d: ''
+ ${flip concatMapStrings (filter (d: d.display) cfg.drivers) (d: ''
Screen "Screen-${d.name}[0]"
'')}
EndSection
@@ -764,42 +764,44 @@ in
${driver.deviceSection or ""}
${xrandrDeviceSection}
EndSection
+ ${optionalString driver.display ''
+
+ Section "Screen"
+ Identifier "Screen-${driver.name}[0]"
+ Device "Device-${driver.name}[0]"
+ ${optionalString (cfg.monitorSection != "") ''
+ Monitor "Monitor[0]"
+ ''}
+
+ ${cfg.screenSection}
+ ${driver.screenSection or ""}
+
+ ${optionalString (cfg.defaultDepth != 0) ''
+ DefaultDepth ${toString cfg.defaultDepth}
+ ''}
+
+ ${optionalString
+ (driver.name != "virtualbox" &&
+ (cfg.resolutions != [] ||
+ cfg.extraDisplaySettings != "" ||
+ cfg.virtualScreen != null))
+ (let
+ f = depth:
+ ''
+ SubSection "Display"
+ Depth ${toString depth}
+ ${optionalString (cfg.resolutions != [])
+ "Modes ${concatMapStrings (res: ''"${toString res.x}x${toString res.y}"'') cfg.resolutions}"}
+ ${cfg.extraDisplaySettings}
+ ${optionalString (cfg.virtualScreen != null)
+ "Virtual ${toString cfg.virtualScreen.x} ${toString cfg.virtualScreen.y}"}
+ EndSubSection
+ '';
+ in concatMapStrings f [8 16 24]
+ )}
- Section "Screen"
- Identifier "Screen-${driver.name}[0]"
- Device "Device-${driver.name}[0]"
- ${optionalString (cfg.monitorSection != "") ''
- Monitor "Monitor[0]"
- ''}
-
- ${cfg.screenSection}
- ${driver.screenSection or ""}
-
- ${optionalString (cfg.defaultDepth != 0) ''
- DefaultDepth ${toString cfg.defaultDepth}
- ''}
-
- ${optionalString
- (driver.name != "virtualbox" &&
- (cfg.resolutions != [] ||
- cfg.extraDisplaySettings != "" ||
- cfg.virtualScreen != null))
- (let
- f = depth:
- ''
- SubSection "Display"
- Depth ${toString depth}
- ${optionalString (cfg.resolutions != [])
- "Modes ${concatMapStrings (res: ''"${toString res.x}x${toString res.y}"'') cfg.resolutions}"}
- ${cfg.extraDisplaySettings}
- ${optionalString (cfg.virtualScreen != null)
- "Virtual ${toString cfg.virtualScreen.x} ${toString cfg.virtualScreen.y}"}
- EndSubSection
- '';
- in concatMapStrings f [8 16 24]
- )}
-
- EndSection
+ EndSection
+ ''}
'')}
${xrandrMonitorSections}
diff --git a/nixpkgs/nixos/modules/system/activation/activation-script.nix b/nixpkgs/nixos/modules/system/activation/activation-script.nix
index 495d77dfd49..ddfd1af4a31 100644
--- a/nixpkgs/nixos/modules/system/activation/activation-script.nix
+++ b/nixpkgs/nixos/modules/system/activation/activation-script.nix
@@ -162,16 +162,6 @@ in
<literal>/usr/bin/env</literal>.
'';
};
-
- environment.ld-linux = mkOption {
- default = false;
- type = types.bool;
- visible = false;
- description = ''
- Install symlink to ld-linux(8) system-wide to allow running unmodified ELF binaries.
- It might be useful to run games or executables distributed inside jar files.
- '';
- };
};
@@ -205,30 +195,9 @@ in
''
else ''
rm -f /usr/bin/env
- rmdir -p /usr/bin || true
+ rmdir --ignore-fail-on-non-empty /usr/bin /usr
'';
- system.activationScripts.ld-linux =
- concatStrings (
- mapAttrsToList
- (target: source:
- if config.environment.ld-linux then ''
- mkdir -m 0755 -p $(dirname ${target})
- ln -sfn ${escapeShellArg source} ${target}.tmp
- mv -f ${target}.tmp ${target} # atomically replace
- '' else ''
- rm -f ${target}
- rmdir $(dirname ${target}) || true
- '')
- {
- "i686-linux" ."/lib/ld-linux.so.2" = "${pkgs.glibc.out}/lib/ld-linux.so.2";
- "x86_64-linux" ."/lib/ld-linux.so.2" = "${pkgs.pkgsi686Linux.glibc.out}/lib/ld-linux.so.2";
- "x86_64-linux" ."/lib64/ld-linux-x86-64.so.2" = "${pkgs.glibc.out}/lib64/ld-linux-x86-64.so.2";
- "aarch64-linux"."/lib/ld-linux-aarch64.so.1" = "${pkgs.glibc.out}/lib/ld-linux-aarch64.so.1";
- "armv7l-linux" ."/lib/ld-linux-armhf.so.3" = "${pkgs.glibc.out}/lib/ld-linux-armhf.so.3";
- }.${pkgs.stdenv.system} or {}
- );
-
system.activationScripts.specialfs =
''
specialMount() {
diff --git a/nixpkgs/nixos/modules/system/activation/switch-to-configuration.pl b/nixpkgs/nixos/modules/system/activation/switch-to-configuration.pl
index 641cf9faadc..b82d69b3bb8 100644
--- a/nixpkgs/nixos/modules/system/activation/switch-to-configuration.pl
+++ b/nixpkgs/nixos/modules/system/activation/switch-to-configuration.pl
@@ -183,7 +183,7 @@ while (my ($unit, $state) = each %{$activePrev}) {
# active after the system has resumed, which probably
# should not be the case. Just ignore it.
if ($unit ne "suspend.target" && $unit ne "hibernate.target" && $unit ne "hybrid-sleep.target") {
- unless (boolIsTrue($unitInfo->{'RefuseManualStart'} // "no")) {
+ unless (boolIsTrue($unitInfo->{'RefuseManualStart'} // "no") || boolIsTrue($unitInfo->{'X-OnlyManualStart'} // "no")) {
$unitsToStart{$unit} = 1;
recordUnit($startListFile, $unit);
# Don't spam the user with target units that always get started.
@@ -222,7 +222,7 @@ while (my ($unit, $state) = each %{$activePrev}) {
$unitsToReload{$unit} = 1;
recordUnit($reloadListFile, $unit);
}
- elsif (!boolIsTrue($unitInfo->{'X-RestartIfChanged'} // "yes") || boolIsTrue($unitInfo->{'RefuseManualStop'} // "no") ) {
+ elsif (!boolIsTrue($unitInfo->{'X-RestartIfChanged'} // "yes") || boolIsTrue($unitInfo->{'RefuseManualStop'} // "no") || boolIsTrue($unitInfo->{'X-OnlyManualStart'} // "no")) {
$unitsToSkip{$unit} = 1;
} else {
if (!boolIsTrue($unitInfo->{'X-StopIfChanged'} // "yes")) {
diff --git a/nixpkgs/nixos/modules/system/activation/top-level.nix b/nixpkgs/nixos/modules/system/activation/top-level.nix
index f67d2900561..14bd751ce32 100644
--- a/nixpkgs/nixos/modules/system/activation/top-level.nix
+++ b/nixpkgs/nixos/modules/system/activation/top-level.nix
@@ -15,6 +15,7 @@ let
map (childConfig:
(import ../../../lib/eval-config.nix {
inherit baseModules;
+ system = config.nixpkgs.initialSystem;
modules =
(optionals inheritParent modules)
++ [ ./no-clone.nix ]
diff --git a/nixpkgs/nixos/modules/system/boot/initrd-network.nix b/nixpkgs/nixos/modules/system/boot/initrd-network.nix
index cb8fc957a99..0ab6e626b34 100644
--- a/nixpkgs/nixos/modules/system/boot/initrd-network.nix
+++ b/nixpkgs/nixos/modules/system/boot/initrd-network.nix
@@ -6,7 +6,11 @@ let
cfg = config.boot.initrd.network;
- dhcpinterfaces = lib.attrNames (lib.filterAttrs (iface: v: v.useDHCP == true) (config.networking.interfaces or {}));
+ dhcpInterfaces = lib.attrNames (lib.filterAttrs (iface: v: v.useDHCP == true) (config.networking.interfaces or {}));
+ doDhcp = config.networking.useDHCP || dhcpInterfaces != [];
+ dhcpIfShellExpr = if config.networking.useDHCP
+ then "$(ls /sys/class/net/ | grep -v ^lo$)"
+ else lib.concatMapStringsSep " " lib.escapeShellArg dhcpInterfaces;
udhcpcScript = pkgs.writeScript "udhcp-script"
''
@@ -62,6 +66,16 @@ in
'';
};
+ boot.initrd.network.flushBeforeStage2 = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether to clear the configuration of the interfaces that were set up in
+ the initrd right before stage 2 takes over. Stage 2 will do the regular network
+ configuration based on the NixOS networking options.
+ '';
+ };
+
boot.initrd.network.udhcpc.extraArgs = mkOption {
default = [];
type = types.listOf types.str;
@@ -89,49 +103,45 @@ in
boot.initrd.kernelModules = [ "af_packet" ];
boot.initrd.extraUtilsCommands = ''
- copy_bin_and_libs ${pkgs.mkinitcpio-nfs-utils}/bin/ipconfig
+ copy_bin_and_libs ${pkgs.klibc}/lib/klibc/bin.static/ipconfig
'';
boot.initrd.preLVMCommands = mkBefore (
# Search for interface definitions in command line.
''
+ ifaces=""
for o in $(cat /proc/cmdline); do
case $o in
ip=*)
- ipconfig $o && hasNetwork=1
+ ipconfig $o && ifaces="$ifaces $(echo $o | cut -d: -f6)"
;;
esac
done
''
# Otherwise, use DHCP.
- + optionalString (config.networking.useDHCP || dhcpinterfaces != []) ''
- if [ -z "$hasNetwork" ]; then
-
- # Bring up all interfaces.
- for iface in $(ls /sys/class/net/); do
- echo "bringing up network interface $iface..."
- ip link set "$iface" up
- done
+ + optionalString doDhcp ''
+ # Bring up all interfaces.
+ for iface in ${dhcpIfShellExpr}; do
+ echo "bringing up network interface $iface..."
+ ip link set "$iface" up && ifaces="$ifaces $iface"
+ done
- # Acquire DHCP leases.
- for iface in ${ if config.networking.useDHCP then
- "$(ls /sys/class/net/ | grep -v ^lo$)"
- else
- lib.concatMapStringsSep " " lib.escapeShellArg dhcpinterfaces
- }; do
- echo "acquiring IP address via DHCP on $iface..."
- udhcpc --quit --now -i $iface -O staticroutes --script ${udhcpcScript} ${udhcpcArgs} && hasNetwork=1
- done
- fi
+ # Acquire DHCP leases.
+ for iface in ${dhcpIfShellExpr}; do
+ echo "acquiring IP address via DHCP on $iface..."
+ udhcpc --quit --now -i $iface -O staticroutes --script ${udhcpcScript} ${udhcpcArgs}
+ done
''
- + ''
- if [ -n "$hasNetwork" ]; then
- echo "networking is up!"
- ${cfg.postCommands}
- fi
- '');
+ + cfg.postCommands);
+
+ boot.initrd.postMountCommands = mkIf cfg.flushBeforeStage2 ''
+ for iface in $ifaces; do
+ ip address flush "$iface"
+ ip link down "$iface"
+ done
+ '';
};
diff --git a/nixpkgs/nixos/modules/system/boot/kernel.nix b/nixpkgs/nixos/modules/system/boot/kernel.nix
index 6edb9082e75..43871f439f7 100644
--- a/nixpkgs/nixos/modules/system/boot/kernel.nix
+++ b/nixpkgs/nixos/modules/system/boot/kernel.nix
@@ -101,7 +101,12 @@ in
type = types.bool;
default = false;
description = ''
- Whether to activate VESA video mode on boot.
+ (Deprecated) This option, if set, activates the VESA 800x600 video
+ mode on boot and disables kernel modesetting. It is equivalent to
+ specifying <literal>[ "vga=0x317" "nomodeset" ]</literal> in the
+ <option>boot.kernelParams</option> option. This option is
+ deprecated as of 2020: Xorg now works better with modesetting, and
+ you might want a different VESA vga setting, anyway.
'';
};
@@ -187,139 +192,144 @@ in
###### implementation
- config = mkIf (!config.boot.isContainer) {
-
- system.build = { inherit kernel; };
-
- system.modulesTree = [ kernel ] ++ config.boot.extraModulePackages;
-
- # Implement consoleLogLevel both in early boot and using sysctl
- # (so you don't need to reboot to have changes take effect).
- boot.kernelParams =
- [ "loglevel=${toString config.boot.consoleLogLevel}" ] ++
- optionals config.boot.vesa [ "vga=0x317" "nomodeset" ];
-
- boot.kernel.sysctl."kernel.printk" = mkDefault config.boot.consoleLogLevel;
-
- boot.kernelModules = [ "loop" "atkbd" ];
-
- boot.initrd.availableKernelModules =
- [ # Note: most of these (especially the SATA/PATA modules)
- # shouldn't be included by default since nixos-generate-config
- # detects them, but I'm keeping them for now for backwards
- # compatibility.
-
- # Some SATA/PATA stuff.
- "ahci"
- "sata_nv"
- "sata_via"
- "sata_sis"
- "sata_uli"
- "ata_piix"
- "pata_marvell"
-
- # Standard SCSI stuff.
- "sd_mod"
- "sr_mod"
-
- # SD cards and internal eMMC drives.
- "mmc_block"
-
- # Support USB keyboards, in case the boot fails and we only have
- # a USB keyboard, or for LUKS passphrase prompt.
- "uhci_hcd"
- "ehci_hcd"
- "ehci_pci"
- "ohci_hcd"
- "ohci_pci"
- "xhci_hcd"
- "xhci_pci"
- "usbhid"
- "hid_generic" "hid_lenovo" "hid_apple" "hid_roccat"
- "hid_logitech_hidpp" "hid_logitech_dj"
-
- ] ++ optionals (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) [
- # Misc. x86 keyboard stuff.
- "pcips2" "atkbd" "i8042"
-
- # x86 RTC needed by the stage 2 init script.
- "rtc_cmos"
- ];
-
- boot.initrd.kernelModules =
- [ # For LVM.
- "dm_mod"
- ];
-
- # The Linux kernel >= 2.6.27 provides firmware.
- hardware.firmware = [ kernel ];
-
- # Create /etc/modules-load.d/nixos.conf, which is read by
- # systemd-modules-load.service to load required kernel modules.
- environment.etc =
- { "modules-load.d/nixos.conf".source = kernelModulesConf;
- };
-
- systemd.services.systemd-modules-load =
- { wantedBy = [ "multi-user.target" ];
- restartTriggers = [ kernelModulesConf ];
- serviceConfig =
- { # Ignore failed module loads. Typically some of the
- # modules in ‘boot.kernelModules’ are "nice to have but
- # not required" (e.g. acpi-cpufreq), so we don't want to
- # barf on those.
- SuccessExitStatus = "0 1";
+ config = mkMerge
+ [ (mkIf config.boot.initrd.enable {
+ boot.initrd.availableKernelModules =
+ [ # Note: most of these (especially the SATA/PATA modules)
+ # shouldn't be included by default since nixos-generate-config
+ # detects them, but I'm keeping them for now for backwards
+ # compatibility.
+
+ # Some SATA/PATA stuff.
+ "ahci"
+ "sata_nv"
+ "sata_via"
+ "sata_sis"
+ "sata_uli"
+ "ata_piix"
+ "pata_marvell"
+
+ # Standard SCSI stuff.
+ "sd_mod"
+ "sr_mod"
+
+ # SD cards and internal eMMC drives.
+ "mmc_block"
+
+ # Support USB keyboards, in case the boot fails and we only have
+ # a USB keyboard, or for LUKS passphrase prompt.
+ "uhci_hcd"
+ "ehci_hcd"
+ "ehci_pci"
+ "ohci_hcd"
+ "ohci_pci"
+ "xhci_hcd"
+ "xhci_pci"
+ "usbhid"
+ "hid_generic" "hid_lenovo" "hid_apple" "hid_roccat"
+ "hid_logitech_hidpp" "hid_logitech_dj"
+
+ ] ++ optionals (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) [
+ # Misc. x86 keyboard stuff.
+ "pcips2" "atkbd" "i8042"
+
+ # x86 RTC needed by the stage 2 init script.
+ "rtc_cmos"
+ ];
+
+ boot.initrd.kernelModules =
+ [ # For LVM.
+ "dm_mod"
+ ];
+ })
+
+ (mkIf (!config.boot.isContainer) {
+ system.build = { inherit kernel; };
+
+ system.modulesTree = [ kernel ] ++ config.boot.extraModulePackages;
+
+ # Implement consoleLogLevel both in early boot and using sysctl
+ # (so you don't need to reboot to have changes take effect).
+ boot.kernelParams =
+ [ "loglevel=${toString config.boot.consoleLogLevel}" ] ++
+ optionals config.boot.vesa [ "vga=0x317" "nomodeset" ];
+
+ boot.kernel.sysctl."kernel.printk" = mkDefault config.boot.consoleLogLevel;
+
+ boot.kernelModules = [ "loop" "atkbd" ];
+
+ # The Linux kernel >= 2.6.27 provides firmware.
+ hardware.firmware = [ kernel ];
+
+ # Create /etc/modules-load.d/nixos.conf, which is read by
+ # systemd-modules-load.service to load required kernel modules.
+ environment.etc =
+ { "modules-load.d/nixos.conf".source = kernelModulesConf;
};
- };
-
- lib.kernelConfig = {
- isYes = option: {
- assertion = config: config.isYes option;
- message = "CONFIG_${option} is not yes!";
- configLine = "CONFIG_${option}=y";
- };
-
- isNo = option: {
- assertion = config: config.isNo option;
- message = "CONFIG_${option} is not no!";
- configLine = "CONFIG_${option}=n";
- };
-
- isModule = option: {
- assertion = config: config.isModule option;
- message = "CONFIG_${option} is not built as a module!";
- configLine = "CONFIG_${option}=m";
- };
-
- ### Usually you will just want to use these two
- # True if yes or module
- isEnabled = option: {
- assertion = config: config.isEnabled option;
- message = "CONFIG_${option} is not enabled!";
- configLine = "CONFIG_${option}=y";
- };
-
- # True if no or omitted
- isDisabled = option: {
- assertion = config: config.isDisabled option;
- message = "CONFIG_${option} is not disabled!";
- configLine = "CONFIG_${option}=n";
- };
- };
- # The config options that all modules can depend upon
- system.requiredKernelConfig = with config.lib.kernelConfig; [
- # !!! Should this really be needed?
- (isYes "MODULES")
- (isYes "BINFMT_ELF")
- ] ++ (optional (randstructSeed != "") (isYes "GCC_PLUGIN_RANDSTRUCT"));
+ systemd.services.systemd-modules-load =
+ { wantedBy = [ "multi-user.target" ];
+ restartTriggers = [ kernelModulesConf ];
+ serviceConfig =
+ { # Ignore failed module loads. Typically some of the
+ # modules in ‘boot.kernelModules’ are "nice to have but
+ # not required" (e.g. acpi-cpufreq), so we don't want to
+ # barf on those.
+ SuccessExitStatus = "0 1";
+ };
+ };
- # nixpkgs kernels are assumed to have all required features
- assertions = if config.boot.kernelPackages.kernel ? features then [] else
- let cfg = config.boot.kernelPackages.kernel.config; in map (attrs:
- { assertion = attrs.assertion cfg; inherit (attrs) message; }
- ) config.system.requiredKernelConfig;
+ lib.kernelConfig = {
+ isYes = option: {
+ assertion = config: config.isYes option;
+ message = "CONFIG_${option} is not yes!";
+ configLine = "CONFIG_${option}=y";
+ };
- };
+ isNo = option: {
+ assertion = config: config.isNo option;
+ message = "CONFIG_${option} is not no!";
+ configLine = "CONFIG_${option}=n";
+ };
+
+ isModule = option: {
+ assertion = config: config.isModule option;
+ message = "CONFIG_${option} is not built as a module!";
+ configLine = "CONFIG_${option}=m";
+ };
+
+ ### Usually you will just want to use these two
+ # True if yes or module
+ isEnabled = option: {
+ assertion = config: config.isEnabled option;
+ message = "CONFIG_${option} is not enabled!";
+ configLine = "CONFIG_${option}=y";
+ };
+
+ # True if no or omitted
+ isDisabled = option: {
+ assertion = config: config.isDisabled option;
+ message = "CONFIG_${option} is not disabled!";
+ configLine = "CONFIG_${option}=n";
+ };
+ };
+
+ # The config options that all modules can depend upon
+ system.requiredKernelConfig = with config.lib.kernelConfig;
+ [
+ # !!! Should this really be needed?
+ (isYes "MODULES")
+ (isYes "BINFMT_ELF")
+ ] ++ (optional (randstructSeed != "") (isYes "GCC_PLUGIN_RANDSTRUCT"));
+
+ # nixpkgs kernels are assumed to have all required features
+ assertions = if config.boot.kernelPackages.kernel ? features then [] else
+ let cfg = config.boot.kernelPackages.kernel.config; in map (attrs:
+ { assertion = attrs.assertion cfg; inherit (attrs) message; }
+ ) config.system.requiredKernelConfig;
+
+ })
+
+ ];
}
diff --git a/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix b/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix
index 9a4db84f7b7..b97ef88a7ca 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix
+++ b/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix
@@ -224,7 +224,11 @@ in
extraConfig = mkOption {
default = "";
- example = "serial; terminal_output.serial";
+ example = ''
+ serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1
+ terminal_input --append serial
+ terminal_output --append serial
+ '';
type = types.lines;
description = ''
Additional GRUB commands inserted in the configuration file
@@ -630,7 +634,7 @@ in
boot.loader.grub.extraPrepareConfig =
concatStrings (mapAttrsToList (n: v: ''
- ${pkgs.coreutils}/bin/cp -pf "${v}" "/boot/${n}"
+ ${pkgs.coreutils}/bin/cp -pf "${v}" "@bootPath@/${n}"
'') config.boot.loader.grub.extraFiles);
assertions = [
diff --git a/nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl
index a09c5dc4761..ca0fb0248e0 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl
+++ b/nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl
@@ -475,6 +475,9 @@ if ($grubVersion == 2) {
}
}
+# extraPrepareConfig could refer to @bootPath@, which we have to substitute
+$extraPrepareConfig =~ s/\@bootPath\@/$bootPath/g;
+
# Run extraPrepareConfig in sh
if ($extraPrepareConfig ne "") {
system((get("shell"), "-c", $extraPrepareConfig));
diff --git a/nixpkgs/nixos/modules/system/boot/loader/grub/memtest.nix b/nixpkgs/nixos/modules/system/boot/loader/grub/memtest.nix
index 94e5a14174b..71e50dd0577 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/grub/memtest.nix
+++ b/nixpkgs/nixos/modules/system/boot/loader/grub/memtest.nix
@@ -1,4 +1,4 @@
-# This module adds Memtest86+ to the GRUB boot menu.
+# This module adds Memtest86+/Memtest86 to the GRUB boot menu.
{ config, lib, pkgs, ... }:
@@ -6,6 +6,7 @@ with lib;
let
memtest86 = pkgs.memtest86plus;
+ efiSupport = config.boot.loader.grub.efiSupport;
cfg = config.boot.loader.grub.memtest86;
in
@@ -18,8 +19,11 @@ in
default = false;
type = types.bool;
description = ''
- Make Memtest86+, a memory testing program, available from the
- GRUB boot menu.
+ Make Memtest86+ (or MemTest86 if EFI support is enabled),
+ a memory testing program, available from the
+ GRUB boot menu. MemTest86 is an unfree program, so
+ this requires <literal>allowUnfree</literal> to be set to
+ <literal>true</literal>.
'';
};
@@ -75,19 +79,38 @@ in
};
};
- config = mkIf cfg.enable {
-
- boot.loader.grub.extraEntries =
- if config.boot.loader.grub.version == 2 then
- ''
- menuentry "Memtest86+" {
- linux16 @bootRoot@/memtest.bin ${toString cfg.params}
- }
- ''
- else
- throw "Memtest86+ is not supported with GRUB 1.";
-
- boot.loader.grub.extraFiles."memtest.bin" = "${memtest86}/memtest.bin";
+ config = mkMerge [
+ (mkIf (cfg.enable && efiSupport) {
+ assertions = [
+ {
+ assertion = cfg.params == [];
+ message = "Parameters are not available for MemTest86";
+ }
+ ];
+
+ boot.loader.grub.extraFiles = {
+ "memtest86.efi" = "${pkgs.memtest86-efi}/BOOTX64.efi";
+ };
- };
+ boot.loader.grub.extraEntries = ''
+ menuentry "Memtest86" {
+ chainloader /memtest86.efi
+ }
+ '';
+ })
+
+ (mkIf (cfg.enable && !efiSupport) {
+ boot.loader.grub.extraEntries =
+ if config.boot.loader.grub.version == 2 then
+ ''
+ menuentry "Memtest86+" {
+ linux16 @bootRoot@/memtest.bin ${toString cfg.params}
+ }
+ ''
+ else
+ throw "Memtest86+ is not supported with GRUB 1.";
+
+ boot.loader.grub.extraFiles."memtest.bin" = "${memtest86}/memtest.bin";
+ })
+ ];
}
diff --git a/nixpkgs/nixos/modules/system/boot/networkd.nix b/nixpkgs/nixos/modules/system/boot/networkd.nix
index 56a9d6b1138..3078f84f6e9 100644
--- a/nixpkgs/nixos/modules/system/boot/networkd.nix
+++ b/nixpkgs/nixos/modules/system/boot/networkd.nix
@@ -55,6 +55,11 @@ let
(assertMacAddress "MACAddress")
];
+ checkVRF = checkUnitConfig "VRF" [
+ (assertOnlyFields [ "Table" ])
+ (assertMinimum "Table" 0)
+ ];
+
# NOTE The PrivateKey directive is missing on purpose here, please
# do not add it to this list. The nix store is world-readable let's
# refrain ourselves from providing a footgun.
@@ -62,7 +67,12 @@ let
(assertOnlyFields [
"PrivateKeyFile" "ListenPort" "FwMark"
])
- (assertRange "FwMark" 1 4294967295)
+ # The following check won't work on nix <= 2.2
+ # see https://github.com/NixOS/nix/pull/2378
+ #
+ # Add this again when we'll have drop the
+ # nix < 2.2 support.
+ # (assertRange "FwMark" 1 4294967295)
];
# NOTE The PresharedKey directive is missing on purpose here, please
@@ -176,7 +186,12 @@ let
(assertOnlyFields [
"InterfaceId" "Independent"
])
- (assertRange "InterfaceId" 1 4294967295)
+ # The following check won't work on nix <= 2.2
+ # see https://github.com/NixOS/nix/pull/2378
+ #
+ # Add this again when we'll have drop the
+ # nix < 2.2 support.
+ # (assertRange "InterfaceId" 1 4294967295)
(assertValueOneOf "Independent" boolValues)
];
@@ -230,6 +245,26 @@ let
(assertValueOneOf "AutoJoin" boolValues)
];
+ checkRoutingPolicyRule = checkUnitConfig "RoutingPolicyRule" [
+ (assertOnlyFields [
+ "TypeOfService" "From" "To" "FirewallMark" "Table" "Priority"
+ "IncomingInterface" "OutgoingInterface" "SourcePort" "DestinationPort"
+ "IPProtocol" "InvertRule" "Family"
+ ])
+ (assertRange "TypeOfService" 0 255)
+ # The following check won't work on nix <= 2.2
+ # see https://github.com/NixOS/nix/pull/2378
+ #
+ # Add this again when we'll have drop the
+ # nix < 2.2 support.
+ # (assertRange "FirewallMark" 1 4294967295)
+ (assertInt "Priority")
+ (assertPort "SourcePort")
+ (assertPort "DestinationPort")
+ (assertValueOneOf "InvertRule" boolValues)
+ (assertValueOneOf "Family" ["ipv4" "ipv6" "both"])
+ ];
+
checkRoute = checkUnitConfig "Route" [
(assertOnlyFields [
"Gateway" "GatewayOnLink" "Destination" "Source" "Metric"
@@ -320,6 +355,14 @@ let
};
linkOptions = commonNetworkOptions // {
+ # overwrite enable option from above
+ enable = mkOption {
+ default = true;
+ type = types.bool;
+ description = ''
+ Whether to enable this .link unit. It's handled by udev no matter if <command>systemd-networkd</command> is enabled or not
+ '';
+ };
linkConfig = mkOption {
default = {};
@@ -349,6 +392,21 @@ let
'';
};
+ vrfConfig = mkOption {
+ default = {};
+ example = { Table = 2342; };
+ type = types.addCheck (types.attrsOf unitOption) checkVRF;
+ description = ''
+ Each attribute in this set specifies an option in the
+ <literal>[VRF]</literal> section of the unit. See
+ <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
+ <manvolnum>5</manvolnum></citerefentry> for details.
+ A detailed explanation about how VRFs work can be found in the
+ <link xlink:href="https://www.kernel.org/doc/Documentation/networking/vrf.txt">kernel
+ docs</link>.
+ '';
+ };
+
wireguardConfig = mkOption {
default = {};
example = {
@@ -515,6 +573,22 @@ let
};
};
+ routingPolicyRulesOptions = {
+ options = {
+ routingPolicyRuleConfig = mkOption {
+ default = { };
+ example = { routingPolicyRuleConfig = { Table = 10; IncomingInterface = "eth1"; Family = "both"; } ;};
+ type = types.addCheck (types.attrsOf unitOption) checkRoutingPolicyRule;
+ description = ''
+ Each attribute in this set specifies an option in the
+ <literal>[RoutingPolicyRule]</literal> section of the unit. See
+ <citerefentry><refentrytitle>systemd.network</refentrytitle>
+ <manvolnum>5</manvolnum></citerefentry> for details.
+ '';
+ };
+ };
+ };
+
routeOptions = {
options = {
routeConfig = mkOption {
@@ -752,6 +826,16 @@ let
'';
};
+ routingPolicyRules = mkOption {
+ default = [ ];
+ type = with types; listOf (submodule routingPolicyRulesOptions);
+ description = ''
+ A list of routing policy rules sections to be added to the unit. See
+ <citerefentry><refentrytitle>systemd.network</refentrytitle>
+ <manvolnum>5</manvolnum></citerefentry> for details.
+ '';
+ };
+
routes = mkOption {
default = [ ];
type = with types; listOf (submodule routeOptions);
@@ -845,6 +929,11 @@ let
${attrsToSection def.xfrmConfig}
''}
+ ${optionalString (def.vrfConfig != { }) ''
+ [VRF]
+ ${attrsToSection def.vrfConfig}
+
+ ''}
${optionalString (def.wireguardConfig != { }) ''
[WireGuard]
${attrsToSection def.wireguardConfig}
@@ -904,6 +993,11 @@ let
${attrsToSection x.routeConfig}
'')}
+ ${flip concatMapStrings def.routingPolicyRules (x: ''
+ [RoutingPolicyRule]
+ ${attrsToSection x.routingPolicyRuleConfig}
+
+ '')}
${def.extraConfig}
'';
};
@@ -947,9 +1041,10 @@ in
systemd.network.units = mkOption {
description = "Definition of networkd units.";
default = {};
+ internal = true;
type = with types; attrsOf (submodule (
{ name, config, ... }:
- { options = concreteUnitOptions;
+ { options = mapAttrs (_: x: x // { internal = true; }) concreteUnitOptions;
config = {
unit = mkDefault (makeUnit name config);
};
@@ -958,44 +1053,49 @@ in
};
- config = mkIf config.systemd.network.enable {
+ config = mkMerge [
+ # .link units are honored by udev, no matter if systemd-networkd is enabled or not.
+ {
+ systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.links;
+ environment.etc = unitFiles;
+ }
- users.users.systemd-network.group = "systemd-network";
+ (mkIf config.systemd.network.enable {
- systemd.additionalUpstreamSystemUnits = [
- "systemd-networkd.service" "systemd-networkd-wait-online.service"
- ];
+ users.users.systemd-network.group = "systemd-network";
- systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.link" (linkToUnit n v)) cfg.links
- // mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.netdevs
- // mapAttrs' (n: v: nameValuePair "${n}.network" (networkToUnit n v)) cfg.networks;
+ systemd.additionalUpstreamSystemUnits = [
+ "systemd-networkd.service" "systemd-networkd-wait-online.service"
+ ];
- environment.etc = unitFiles;
+ systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.netdevs
+ // mapAttrs' (n: v: nameValuePair "${n}.network" (networkToUnit n v)) cfg.networks;
- systemd.services.systemd-networkd = {
- wantedBy = [ "multi-user.target" ];
- restartTriggers = attrNames unitFiles;
- # prevent race condition with interface renaming (#39069)
- requires = [ "systemd-udev-settle.service" ];
- after = [ "systemd-udev-settle.service" ];
- };
+ systemd.services.systemd-networkd = {
+ wantedBy = [ "multi-user.target" ];
+ restartTriggers = attrNames unitFiles;
+ # prevent race condition with interface renaming (#39069)
+ requires = [ "systemd-udev-settle.service" ];
+ after = [ "systemd-udev-settle.service" ];
+ };
- systemd.services.systemd-networkd-wait-online = {
- wantedBy = [ "network-online.target" ];
- };
+ systemd.services.systemd-networkd-wait-online = {
+ wantedBy = [ "network-online.target" ];
+ };
- systemd.services."systemd-network-wait-online@" = {
- description = "Wait for Network Interface %I to be Configured";
- conflicts = [ "shutdown.target" ];
- requisite = [ "systemd-networkd.service" ];
- after = [ "systemd-networkd.service" ];
- serviceConfig = {
- Type = "oneshot";
- RemainAfterExit = true;
- ExecStart = "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online -i %I";
+ systemd.services."systemd-network-wait-online@" = {
+ description = "Wait for Network Interface %I to be Configured";
+ conflicts = [ "shutdown.target" ];
+ requisite = [ "systemd-networkd.service" ];
+ after = [ "systemd-networkd.service" ];
+ serviceConfig = {
+ Type = "oneshot";
+ RemainAfterExit = true;
+ ExecStart = "${config.systemd.package}/lib/systemd/systemd-networkd-wait-online -i %I";
+ };
};
- };
- services.resolved.enable = mkDefault true;
- };
+ services.resolved.enable = mkDefault true;
+ })
+ ];
}
diff --git a/nixpkgs/nixos/modules/system/boot/stage-1-init.sh b/nixpkgs/nixos/modules/system/boot/stage-1-init.sh
index f520bf54ad1..607aec87f01 100644
--- a/nixpkgs/nixos/modules/system/boot/stage-1-init.sh
+++ b/nixpkgs/nixos/modules/system/boot/stage-1-init.sh
@@ -210,6 +210,8 @@ done
# Create device nodes in /dev.
@preDeviceCommands@
echo "running udev..."
+mkdir -p /etc/systemd
+ln -sfn @linkUnits@ /etc/systemd/network
mkdir -p /etc/udev
ln -sfn @udevRules@ /etc/udev/rules.d
mkdir -p /dev/.mdadm
@@ -266,7 +268,7 @@ checkFS() {
return 0
fi
- # Device might be already mounted manually
+ # Device might be already mounted manually
# e.g. NBD-device or the host filesystem of the file which contains encrypted root fs
if mount | grep -q "^$device on "; then
echo "skip checking already mounted $device"
@@ -334,8 +336,10 @@ mountFS() {
# Filter out x- options, which busybox doesn't do yet.
local optionsFiltered="$(IFS=,; for i in $options; do if [ "${i:0:2}" != "x-" ]; then echo -n $i,; fi; done)"
+ # Prefix (lower|upper|work)dir with /mnt-root (overlayfs)
+ local optionsPrefixed="$( echo "$optionsFiltered" | sed -E 's#\<(lowerdir|upperdir|workdir)=#\1=/mnt-root#g' )"
- echo "$device /mnt-root$mountPoint $fsType $optionsFiltered" >> /etc/fstab
+ echo "$device /mnt-root$mountPoint $fsType $optionsPrefixed" >> /etc/fstab
checkFS "$device" "$fsType"
@@ -349,15 +353,16 @@ mountFS() {
elif [ "$fsType" = f2fs ]; then
echo "resizing $device..."
fsck.f2fs -fp "$device"
- resize.f2fs "$device"
+ resize.f2fs "$device"
fi
;;
esac
- # Create backing directories for unionfs-fuse.
- if [ "$fsType" = unionfs-fuse ]; then
- for i in $(IFS=:; echo ${options##*,dirs=}); do
- mkdir -m 0700 -p /mnt-root"${i%=*}"
+ # Create backing directories for overlayfs
+ if [ "$fsType" = overlay ]; then
+ for i in upper work; do
+ dir="$( echo "$optionsPrefixed" | grep -o "${i}dir=[^,]*" )"
+ mkdir -m 0700 -p "${dir##*=}"
done
fi
diff --git a/nixpkgs/nixos/modules/system/boot/stage-1.nix b/nixpkgs/nixos/modules/system/boot/stage-1.nix
index 4c2d130d5a5..93cd801ef80 100644
--- a/nixpkgs/nixos/modules/system/boot/stage-1.nix
+++ b/nixpkgs/nixos/modules/system/boot/stage-1.nix
@@ -120,6 +120,7 @@ let
# Copy udev.
copy_bin_and_libs ${udev}/lib/systemd/systemd-udevd
+ copy_bin_and_libs ${udev}/lib/systemd/systemd-sysctl
copy_bin_and_libs ${udev}/bin/udevadm
for BIN in ${udev}/lib/udev/*_id; do
copy_bin_and_libs $BIN
@@ -198,6 +199,14 @@ let
''; # */
+ linkUnits = pkgs.runCommand "link-units" {
+ allowedReferences = [ extraUtils ];
+ preferLocalBuild = true;
+ } ''
+ mkdir -p $out
+ cp -v ${udev}/lib/systemd/network/*.link $out/
+ '';
+
udevRules = pkgs.runCommand "udev-rules" {
allowedReferences = [ extraUtils ];
preferLocalBuild = true;
@@ -208,7 +217,9 @@ let
cp -v ${udev}/lib/udev/rules.d/60-cdrom_id.rules $out/
cp -v ${udev}/lib/udev/rules.d/60-persistent-storage.rules $out/
+ cp -v ${udev}/lib/udev/rules.d/75-net-description.rules $out/
cp -v ${udev}/lib/udev/rules.d/80-drivers.rules $out/
+ cp -v ${udev}/lib/udev/rules.d/80-net-setup-link.rules $out/
cp -v ${pkgs.lvm2}/lib/udev/rules.d/*.rules $out/
${config.boot.initrd.extraUdevRulesCommands}
@@ -222,7 +233,7 @@ let
--replace ${pkgs.lvm2}/sbin ${extraUtils}/bin \
--replace ${pkgs.mdadm}/sbin ${extraUtils}/sbin \
--replace ${pkgs.bash}/bin/sh ${extraUtils}/bin/sh \
- --replace ${udev}/bin/udevadm ${extraUtils}/bin/udevadm
+ --replace ${udev} ${extraUtils}
done
# Work around a bug in QEMU, which doesn't implement the "READ
@@ -257,7 +268,7 @@ let
${pkgs.buildPackages.busybox}/bin/ash -n $target
'';
- inherit udevRules extraUtils modulesClosure;
+ inherit linkUnits udevRules extraUtils modulesClosure;
inherit (config.boot) resumeDevice;
@@ -379,6 +390,17 @@ in
'';
};
+ boot.initrd.enable = mkOption {
+ type = types.bool;
+ default = !config.boot.isContainer;
+ defaultText = "!config.boot.isContainer";
+ description = ''
+ Whether to enable the NixOS initial RAM disk (initrd). This may be
+ needed to perform some initialisation tasks (like mounting
+ network/encrypted file systems) before continuing the boot process.
+ '';
+ };
+
boot.initrd.prepend = mkOption {
default = [ ];
type = types.listOf types.str;
@@ -544,7 +566,7 @@ in
};
- config = mkIf (!config.boot.isContainer) {
+ config = mkIf config.boot.initrd.enable {
assertions = [
{ assertion = any (fs: fs.mountPoint == "/") fileSystems;
message = "The ‘fileSystems’ option does not specify your root file system.";
diff --git a/nixpkgs/nixos/modules/system/boot/systemd-lib.nix b/nixpkgs/nixos/modules/system/boot/systemd-lib.nix
index fd1a5b9f62c..a3360291586 100644
--- a/nixpkgs/nixos/modules/system/boot/systemd-lib.nix
+++ b/nixpkgs/nixos/modules/system/boot/systemd-lib.nix
@@ -59,6 +59,11 @@ in rec {
optional (attr ? ${name} && ! isMacAddress attr.${name})
"Systemd ${group} field `${name}' must be a valid mac address.";
+ isPort = i: i >= 0 && i <= 65535;
+
+ assertPort = name: group: attr:
+ optional (attr ? ${name} && ! isPort attr.${name})
+ "Error on the systemd ${group} field `${name}': ${attr.name} is not a valid port number.";
assertValueOneOf = name: values: group: attr:
optional (attr ? ${name} && !elem attr.${name} values)
diff --git a/nixpkgs/nixos/modules/system/boot/systemd.nix b/nixpkgs/nixos/modules/system/boot/systemd.nix
index 941df5797c6..cdc9d237939 100644
--- a/nixpkgs/nixos/modules/system/boot/systemd.nix
+++ b/nixpkgs/nixos/modules/system/boot/systemd.nix
@@ -697,6 +697,16 @@ in
'';
};
+ systemd.sleep.extraConfig = mkOption {
+ default = "";
+ type = types.lines;
+ example = "HibernateDelaySec=1h";
+ description = ''
+ Extra config options for systemd sleep state logic.
+ See sleep.conf.d(5) man page for available options.
+ '';
+ };
+
systemd.user.extraConfig = mkOption {
default = "";
type = types.lines;
@@ -776,6 +786,18 @@ in
'';
};
+ systemd.suppressedSystemUnits = mkOption {
+ default = [ ];
+ type = types.listOf types.str;
+ example = [ "systemd-backlight@.service" ];
+ description = ''
+ A list of units to suppress when generating system systemd configuration directory. This has
+ priority over upstream units, <option>systemd.units</option>, and
+ <option>systemd.additionalUpstreamSystemUnits</option>. The main purpose of this is to
+ suppress a upstream systemd unit with any modifications made to it by other NixOS modules.
+ '';
+ };
+
};
@@ -808,8 +830,11 @@ in
done
${concatStrings (mapAttrsToList (exec: target: "ln -s ${target} $out/${exec};\n") links)}
'';
+
+ enabledUpstreamSystemUnits = filter (n: ! elem n cfg.suppressedSystemUnits) upstreamSystemUnits;
+ enabledUnits = filterAttrs (n: v: ! elem n cfg.suppressedSystemUnits) cfg.units;
in ({
- "systemd/system".source = generateUnits "system" cfg.units upstreamSystemUnits upstreamSystemWants;
+ "systemd/system".source = generateUnits "system" enabledUnits enabledUpstreamSystemUnits upstreamSystemWants;
"systemd/user".source = generateUnits "user" cfg.user.units upstreamUserUnits [];
@@ -863,6 +888,7 @@ in
"systemd/sleep.conf".text = ''
[Sleep]
+ ${config.systemd.sleep.extraConfig}
'';
# install provided sysctl snippets
diff --git a/nixpkgs/nixos/modules/system/etc/etc.nix b/nixpkgs/nixos/modules/system/etc/etc.nix
index 57ade288096..1f4d54a1ae2 100644
--- a/nixpkgs/nixos/modules/system/etc/etc.nix
+++ b/nixpkgs/nixos/modules/system/etc/etc.nix
@@ -94,7 +94,7 @@ in
default = 0;
type = types.int;
description = ''
- UID of created file. Only takes affect when the file is
+ UID of created file. Only takes effect when the file is
copied (that is, the mode is not 'symlink').
'';
};
@@ -103,7 +103,7 @@ in
default = 0;
type = types.int;
description = ''
- GID of created file. Only takes affect when the file is
+ GID of created file. Only takes effect when the file is
copied (that is, the mode is not 'symlink').
'';
};
@@ -113,7 +113,7 @@ in
type = types.str;
description = ''
User name of created file.
- Only takes affect when the file is copied (that is, the mode is not 'symlink').
+ Only takes effect when the file is copied (that is, the mode is not 'symlink').
Changing this option takes precedence over <literal>uid</literal>.
'';
};
@@ -123,7 +123,7 @@ in
type = types.str;
description = ''
Group name of created file.
- Only takes affect when the file is copied (that is, the mode is not 'symlink').
+ Only takes effect when the file is copied (that is, the mode is not 'symlink').
Changing this option takes precedence over <literal>gid</literal>.
'';
};
diff --git a/nixpkgs/nixos/modules/tasks/auto-upgrade.nix b/nixpkgs/nixos/modules/tasks/auto-upgrade.nix
index 7fe06699191..bfc1e301efa 100644
--- a/nixpkgs/nixos/modules/tasks/auto-upgrade.nix
+++ b/nixpkgs/nixos/modules/tasks/auto-upgrade.nix
@@ -63,6 +63,19 @@ let cfg = config.system.autoUpgrade; in
'';
};
+ randomizedDelaySec = mkOption {
+ default = "0";
+ type = types.str;
+ example = "45min";
+ description = ''
+ Add a randomized delay before each automatic upgrade.
+ The delay will be chozen between zero and this value.
+ This value must be a time span in the format specified by
+ <citerefentry><refentrytitle>systemd.time</refentrytitle>
+ <manvolnum>7</manvolnum></citerefentry>
+ '';
+ };
+
};
};
@@ -109,6 +122,8 @@ let cfg = config.system.autoUpgrade; in
startAt = cfg.dates;
};
+ systemd.timers.nixos-upgrade.timerConfig.RandomizedDelaySec = cfg.randomizedDelaySec;
+
};
}
diff --git a/nixpkgs/nixos/modules/tasks/encrypted-devices.nix b/nixpkgs/nixos/modules/tasks/encrypted-devices.nix
index 2c9231f5523..bc0933f16fe 100644
--- a/nixpkgs/nixos/modules/tasks/encrypted-devices.nix
+++ b/nixpkgs/nixos/modules/tasks/encrypted-devices.nix
@@ -65,7 +65,7 @@ in
boot.initrd = {
luks = {
devices =
- map (dev: { name = dev.encrypted.label; device = dev.encrypted.blkDev; } ) keylessEncDevs;
+ builtins.listToAttrs (map (dev: { name = dev.encrypted.label; value = { device = dev.encrypted.blkDev; }; }) keylessEncDevs);
forceLuksSupportInInitrd = true;
};
postMountCommands =
diff --git a/nixpkgs/nixos/modules/tasks/filesystems.nix b/nixpkgs/nixos/modules/tasks/filesystems.nix
index 688c77cb22d..0ade74b957a 100644
--- a/nixpkgs/nixos/modules/tasks/filesystems.nix
+++ b/nixpkgs/nixos/modules/tasks/filesystems.nix
@@ -304,6 +304,11 @@ in
in listToAttrs (map formatDevice (filter (fs: fs.autoFormat) fileSystems));
+ systemd.tmpfiles.rules = [
+ "d /run/keys 0750 root ${toString config.ids.gids.keys}"
+ "z /run/keys 0750 root ${toString config.ids.gids.keys}"
+ ];
+
# Sync mount options with systemd's src/core/mount-setup.c: mount_table.
boot.specialFileSystems = {
"/proc" = { fsType = "proc"; options = [ "nosuid" "noexec" "nodev" ]; };
@@ -312,8 +317,8 @@ in
"/dev/shm" = { fsType = "tmpfs"; options = [ "nosuid" "nodev" "strictatime" "mode=1777" "size=${config.boot.devShmSize}" ]; };
"/dev/pts" = { fsType = "devpts"; options = [ "nosuid" "noexec" "mode=620" "ptmxmode=0666" "gid=${toString config.ids.gids.tty}" ]; };
- # To hold secrets that shouldn't be written to disk (generally used for NixOps, harmless elsewhere)
- "/run/keys" = { fsType = "ramfs"; options = [ "nosuid" "nodev" "mode=750" "gid=${toString config.ids.gids.keys}" ]; };
+ # To hold secrets that shouldn't be written to disk
+ "/run/keys" = { fsType = "ramfs"; options = [ "nosuid" "nodev" "mode=750" ]; };
} // optionalAttrs (!config.boot.isContainer) {
# systemd-nspawn populates /sys by itself, and remounting it causes all
# kinds of weird issues (most noticeably, waiting for host disk device
diff --git a/nixpkgs/nixos/modules/tasks/filesystems/btrfs.nix b/nixpkgs/nixos/modules/tasks/filesystems/btrfs.nix
index 48be18c7102..f64493e1a3c 100644
--- a/nixpkgs/nixos/modules/tasks/filesystems/btrfs.nix
+++ b/nixpkgs/nixos/modules/tasks/filesystems/btrfs.nix
@@ -118,12 +118,17 @@ in
fs' = utils.escapeSystemdPath fs;
in nameValuePair "btrfs-scrub-${fs'}" {
description = "btrfs scrub on ${fs}";
+ # scrub prevents suspend2ram or proper shutdown
+ conflicts = [ "shutdown.target" "sleep.target" ];
+ before = [ "shutdown.target" "sleep.target" ];
serviceConfig = {
- Type = "oneshot";
+ # simple and not oneshot, otherwise ExecStop is not used
+ Type = "simple";
Nice = 19;
IOSchedulingClass = "idle";
ExecStart = "${pkgs.btrfs-progs}/bin/btrfs scrub start -B ${fs}";
+ ExecStop = "${pkgs.btrfs-progs}/bin/btrfs scrub cancel ${fs}";
};
};
in listToAttrs (map scrubService cfgScrub.fileSystems);
diff --git a/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix b/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix
index d14ba98ec48..09c7e074e12 100644
--- a/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix
+++ b/nixpkgs/nixos/modules/tasks/filesystems/zfs.nix
@@ -623,7 +623,11 @@ in
after = [ "zfs-import.target" ];
path = [ packages.zfsUser ];
startAt = cfgTrim.interval;
- serviceConfig.ExecStart = "${pkgs.runtimeShell} -c 'zpool list -H -o name | xargs --no-run-if-empty -n1 zpool trim'";
+ # By default we ignore errors returned by the trim command, in case:
+ # - HDDs are mixed with SSDs
+ # - There is a SSDs in a pool that is currently trimmed.
+ # - There are only HDDs and we would set the system in a degraded state
+ serviceConfig.ExecStart = ''${pkgs.runtimeShell} -c 'for pool in $(zpool list -H -o name); do zpool trim $pool; done || true' '';
};
})
];
diff --git a/nixpkgs/nixos/modules/tasks/network-interfaces-scripted.nix b/nixpkgs/nixos/modules/tasks/network-interfaces-scripted.nix
index 1726d05115e..4d25137c5df 100644
--- a/nixpkgs/nixos/modules/tasks/network-interfaces-scripted.nix
+++ b/nixpkgs/nixos/modules/tasks/network-interfaces-scripted.nix
@@ -10,7 +10,7 @@ let
slaves = concatMap (i: i.interfaces) (attrValues cfg.bonds)
++ concatMap (i: i.interfaces) (attrValues cfg.bridges)
- ++ concatMap (i: i.interfaces) (attrValues cfg.vswitches)
+ ++ concatMap (i: attrNames (filterAttrs (_: config: config.type != "internal") i.interfaces)) (attrValues cfg.vswitches)
++ concatMap (i: [i.interface]) (attrValues cfg.macvlans)
++ concatMap (i: [i.interface]) (attrValues cfg.vlans);
@@ -336,34 +336,47 @@ let
createVswitchDevice = n: v: nameValuePair "${n}-netdev"
(let
- deps = concatLists (map deviceDependency v.interfaces);
+ deps = concatLists (map deviceDependency (attrNames (filterAttrs (_: config: config.type != "internal") v.interfaces)));
+ internalConfigs = concatMap (i: ["network-link-${i}.service" "network-addresses-${i}.service"]) (attrNames (filterAttrs (_: config: config.type == "internal") v.interfaces));
ofRules = pkgs.writeText "vswitch-${n}-openFlowRules" v.openFlowRules;
in
{ description = "Open vSwitch Interface ${n}";
- wantedBy = [ "network-setup.service" "vswitchd.service" ] ++ deps;
- bindsTo = [ "vswitchd.service" (subsystemDevice n) ] ++ deps;
- partOf = [ "network-setup.service" "vswitchd.service" ];
- after = [ "network-pre.target" "vswitchd.service" ] ++ deps;
- before = [ "network-setup.service" ];
+ wantedBy = [ "network-setup.service" (subsystemDevice n) ] ++ internalConfigs;
+ # before = [ "network-setup.service" ];
+ # should work without internalConfigs dependencies because address/link configuration depends
+ # on the device, which is created by ovs-vswitchd with type=internal, but it does not...
+ before = [ "network-setup.service" ] ++ internalConfigs;
+ partOf = [ "network-setup.service" ]; # shutdown the bridge when network is shutdown
+ bindsTo = [ "ovs-vswitchd.service" ]; # requires ovs-vswitchd to be alive at all times
+ after = [ "network-pre.target" "ovs-vswitchd.service" ] ++ deps; # start switch after physical interfaces and vswitch daemon
+ wants = deps; # if one or more interface fails, the switch should continue to run
serviceConfig.Type = "oneshot";
serviceConfig.RemainAfterExit = true;
path = [ pkgs.iproute config.virtualisation.vswitch.package ];
+ preStart = ''
+ echo "Resetting Open vSwitch ${n}..."
+ ovs-vsctl --if-exists del-br ${n} -- add-br ${n} \
+ -- set bridge ${n} protocols=${concatStringsSep "," v.supportedOpenFlowVersions}
+ '';
script = ''
- echo "Removing old Open vSwitch ${n}..."
- ovs-vsctl --if-exists del-br ${n}
-
- echo "Adding Open vSwitch ${n}..."
- ovs-vsctl -- add-br ${n} ${concatMapStrings (i: " -- add-port ${n} ${i}") v.interfaces} \
+ echo "Configuring Open vSwitch ${n}..."
+ ovs-vsctl ${concatStrings (mapAttrsToList (name: config: " -- add-port ${n} ${name}" + optionalString (config.vlan != null) " tag=${toString config.vlan}") v.interfaces)} \
+ ${concatStrings (mapAttrsToList (name: config: optionalString (config.type != null) " -- set interface ${name} type=${config.type}") v.interfaces)} \
${concatMapStrings (x: " -- set-controller ${n} " + x) v.controllers} \
${concatMapStrings (x: " -- " + x) (splitString "\n" v.extraOvsctlCmds)}
+
echo "Adding OpenFlow rules for Open vSwitch ${n}..."
- ovs-ofctl add-flows ${n} ${ofRules}
+ ovs-ofctl --protocols=${v.openFlowVersion} add-flows ${n} ${ofRules}
'';
postStop = ''
+ echo "Cleaning Open vSwitch ${n}"
+ echo "Shuting down internal ${n} interface"
ip link set ${n} down || true
- ovs-ofctl del-flows ${n} || true
- ovs-vsctl --if-exists del-br ${n}
+ echo "Deleting flows for ${n}"
+ ovs-ofctl --protocols=${v.openFlowVersion} del-flows ${n} || true
+ echo "Deleting Open vSwitch ${n}"
+ ovs-vsctl --if-exists del-br ${n} || true
'';
});
@@ -476,9 +489,9 @@ let
# Remove Dead Interfaces
ip link show "${n}" >/dev/null 2>&1 && ip link delete "${n}"
ip link add link "${v.interface}" name "${n}" type vlan id "${toString v.id}"
-
- # We try to bring up the logical VLAN interface. If the master
- # interface the logical interface is dependent upon is not up yet we will
+
+ # We try to bring up the logical VLAN interface. If the master
+ # interface the logical interface is dependent upon is not up yet we will
# fail to immediately bring up the logical interface. The resulting logical
# interface will brought up later when the master interface is up.
ip link set "${n}" up || true
diff --git a/nixpkgs/nixos/modules/tasks/network-interfaces-systemd.nix b/nixpkgs/nixos/modules/tasks/network-interfaces-systemd.nix
index e25dc0c0b39..41deceb000e 100644
--- a/nixpkgs/nixos/modules/tasks/network-interfaces-systemd.nix
+++ b/nixpkgs/nixos/modules/tasks/network-interfaces-systemd.nix
@@ -1,4 +1,4 @@
-{ config, lib, utils, ... }:
+{ config, lib, utils, pkgs, ... }:
with utils;
with lib;
@@ -18,7 +18,10 @@ let
concatLists (map (bond: bond.interfaces) (attrValues cfg.bonds))
++ concatLists (map (bridge: bridge.interfaces) (attrValues cfg.bridges))
++ map (sit: sit.dev) (attrValues cfg.sits)
- ++ map (vlan: vlan.interface) (attrValues cfg.vlans);
+ ++ map (vlan: vlan.interface) (attrValues cfg.vlans)
+ # add dependency to physical or independently created vswitch member interface
+ # TODO: warn the user that any address configured on those interfaces will be useless
+ ++ concatMap (i: attrNames (filterAttrs (_: config: config.type != "internal") i.interfaces)) (attrValues cfg.vswitches);
in
@@ -51,11 +54,6 @@ in
networking.dhcpcd.enable = mkDefault false;
- systemd.services.network-local-commands = {
- after = [ "systemd-networkd.service" ];
- bindsTo = [ "systemd-networkd.service" ];
- };
-
systemd.network =
let
domains = cfg.search ++ (optional (cfg.domain != null) cfg.domain);
@@ -233,6 +231,63 @@ in
# This forces the network interface creator to initialize slaves.
networking.interfaces = listToAttrs (map (i: nameValuePair i { }) slaves);
+ systemd.services = let
+ # We must escape interfaces due to the systemd interpretation
+ subsystemDevice = interface:
+ "sys-subsystem-net-devices-${escapeSystemdPath interface}.device";
+ # support for creating openvswitch switches
+ createVswitchDevice = n: v: nameValuePair "${n}-netdev"
+ (let
+ deps = map subsystemDevice (attrNames (filterAttrs (_: config: config.type != "internal") v.interfaces));
+ ofRules = pkgs.writeText "vswitch-${n}-openFlowRules" v.openFlowRules;
+ in
+ { description = "Open vSwitch Interface ${n}";
+ wantedBy = [ "network.target" (subsystemDevice n) ];
+ # and create bridge before systemd-networkd starts because it might create internal interfaces
+ before = [ "systemd-networkd.service" ];
+ # shutdown the bridge when network is shutdown
+ partOf = [ "network.target" ];
+ # requires ovs-vswitchd to be alive at all times
+ bindsTo = [ "ovs-vswitchd.service" ];
+ # start switch after physical interfaces and vswitch daemon
+ after = [ "network-pre.target" "ovs-vswitchd.service" ] ++ deps;
+ wants = deps; # if one or more interface fails, the switch should continue to run
+ serviceConfig.Type = "oneshot";
+ serviceConfig.RemainAfterExit = true;
+ path = [ pkgs.iproute config.virtualisation.vswitch.package ];
+ preStart = ''
+ echo "Resetting Open vSwitch ${n}..."
+ ovs-vsctl --if-exists del-br ${n} -- add-br ${n} \
+ -- set bridge ${n} protocols=${concatStringsSep "," v.supportedOpenFlowVersions}
+ '';
+ script = ''
+ echo "Configuring Open vSwitch ${n}..."
+ ovs-vsctl ${concatStrings (mapAttrsToList (name: config: " -- add-port ${n} ${name}" + optionalString (config.vlan != null) " tag=${toString config.vlan}") v.interfaces)} \
+ ${concatStrings (mapAttrsToList (name: config: optionalString (config.type != null) " -- set interface ${name} type=${config.type}") v.interfaces)} \
+ ${concatMapStrings (x: " -- set-controller ${n} " + x) v.controllers} \
+ ${concatMapStrings (x: " -- " + x) (splitString "\n" v.extraOvsctlCmds)}
+
+
+ echo "Adding OpenFlow rules for Open vSwitch ${n}..."
+ ovs-ofctl --protocols=${v.openFlowVersion} add-flows ${n} ${ofRules}
+ '';
+ postStop = ''
+ echo "Cleaning Open vSwitch ${n}"
+ echo "Shuting down internal ${n} interface"
+ ip link set ${n} down || true
+ echo "Deleting flows for ${n}"
+ ovs-ofctl --protocols=${v.openFlowVersion} del-flows ${n} || true
+ echo "Deleting Open vSwitch ${n}"
+ ovs-vsctl --if-exists del-br ${n} || true
+ '';
+ });
+ in mapAttrs' createVswitchDevice cfg.vswitches
+ // {
+ "network-local-commands" = {
+ after = [ "systemd-networkd.service" ];
+ bindsTo = [ "systemd-networkd.service" ];
+ };
+ };
};
}
diff --git a/nixpkgs/nixos/modules/tasks/network-interfaces.nix b/nixpkgs/nixos/modules/tasks/network-interfaces.nix
index 31e2ed1cd1e..9542a60beee 100644
--- a/nixpkgs/nixos/modules/tasks/network-interfaces.nix
+++ b/nixpkgs/nixos/modules/tasks/network-interfaces.nix
@@ -13,7 +13,7 @@ let
slaves = concatMap (i: i.interfaces) (attrValues cfg.bonds)
++ concatMap (i: i.interfaces) (attrValues cfg.bridges)
- ++ concatMap (i: i.interfaces) (attrValues cfg.vswitches);
+ ++ concatMap (i: attrNames (filterAttrs (name: config: ! (config.type == "internal" || hasAttr name cfg.interfaces)) i.interfaces)) (attrValues cfg.vswitches);
slaveIfs = map (i: cfg.interfaces.${i}) (filter (i: cfg.interfaces ? ${i}) slaves);
@@ -143,13 +143,34 @@ let
description = "Name of the interface.";
};
- preferTempAddress = mkOption {
- type = types.bool;
- default = cfg.enableIPv6;
- defaultText = literalExample "config.networking.enableIPv6";
+ tempAddress = mkOption {
+ type = types.enum [ "default" "enabled" "disabled" ];
+ default = if cfg.enableIPv6 then "default" else "disabled";
+ defaultText = literalExample ''if cfg.enableIPv6 then "default" else "disabled"'';
description = ''
- When using SLAAC prefer a temporary (IPv6) address over the EUI-64
- address for originating connections. This is used to reduce tracking.
+ When IPv6 is enabled with SLAAC, this option controls the use of
+ temporary address (aka privacy extensions). This is used to reduce tracking.
+ The three possible values are:
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>"default"</literal> to generate temporary addresses and use
+ them by default;
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>"enabled"</literal> to generate temporary addresses but keep
+ using the standard EUI-64 ones by default;
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>"disabled"</literal> to completely disable temporary addresses.
+ </para>
+ </listitem>
+ </itemizedlist>
'';
};
@@ -287,6 +308,11 @@ let
let
defined = x: x != "_mkMergedOptionModule";
in [
+ (mkChangedOptionModule [ "preferTempAddress" ] [ "tempAddress" ]
+ (config:
+ let bool = getAttrFromPath [ "preferTempAddress" ] config;
+ in if bool then "default" else "enabled"
+ ))
(mkRenamedOptionModule [ "ip4" ] [ "ipv4" "addresses"])
(mkRenamedOptionModule [ "ip6" ] [ "ipv6" "addresses"])
(mkRemovedOptionModule [ "subnetMask" ] ''
@@ -310,6 +336,32 @@ let
};
+ vswitchInterfaceOpts = {name, ...}: {
+
+ options = {
+
+ name = mkOption {
+ description = "Name of the interface";
+ example = "eth0";
+ type = types.str;
+ };
+
+ vlan = mkOption {
+ description = "Vlan tag to apply to interface";
+ example = 10;
+ type = types.nullOr types.int;
+ default = null;
+ };
+
+ type = mkOption {
+ description = "Openvswitch type to assign to interface";
+ example = "internal";
+ type = types.nullOr types.str;
+ default = null;
+ };
+ };
+ };
+
hexChars = stringToCharacters "0123456789abcdef";
isHexString = s: all (c: elem c hexChars) (stringToCharacters (toLower s));
@@ -460,8 +512,8 @@ in
networking.vswitches = mkOption {
default = { };
example =
- { vs0.interfaces = [ "eth0" "eth1" ];
- vs1.interfaces = [ "eth2" "wlan0" ];
+ { vs0.interfaces = { eth0 = { }; lo1 = { type="internal"; }; };
+ vs1.interfaces = [ { name = "eth2"; } { name = "lo2"; type="internal"; } ];
};
description =
''
@@ -478,9 +530,8 @@ in
interfaces = mkOption {
example = [ "eth0" "eth1" ];
- type = types.listOf types.str;
- description =
- "The physical network interfaces connected by the vSwitch.";
+ description = "The physical network interfaces connected by the vSwitch.";
+ type = with types; loaOf (submodule vswitchInterfaceOpts);
};
controllers = mkOption {
@@ -504,6 +555,25 @@ in
'';
};
+ # TODO: custom "openflow version" type, with list from existing openflow protocols
+ supportedOpenFlowVersions = mkOption {
+ type = types.listOf types.str;
+ example = [ "OpenFlow10" "OpenFlow13" "OpenFlow14" ];
+ default = [ "OpenFlow13" ];
+ description = ''
+ Supported versions to enable on this switch.
+ '';
+ };
+
+ # TODO: use same type as elements from supportedOpenFlowVersions
+ openFlowVersion = mkOption {
+ type = types.str;
+ default = "OpenFlow13";
+ description = ''
+ Version of OpenFlow protocol to use when communicating with the switch internally (e.g. with <literal>openFlowRules</literal>).
+ '';
+ };
+
extraOvsctlCmds = mkOption {
type = types.lines;
default = "";
@@ -945,7 +1015,7 @@ in
The networking.interfaces."${i.name}" must not have any defined ips when it is a slave.
'';
})) ++ (forEach interfaces (i: {
- assertion = i.preferTempAddress -> cfg.enableIPv6;
+ assertion = i.tempAddress != "disabled" -> cfg.enableIPv6;
message = ''
Temporary addresses are only needed when IPv6 is enabled.
'';
@@ -973,8 +1043,11 @@ in
"net.ipv6.conf.all.forwarding" = mkDefault (any (i: i.proxyARP) interfaces);
} // listToAttrs (flip concatMap (filter (i: i.proxyARP) interfaces)
(i: forEach [ "4" "6" ] (v: nameValuePair "net.ipv${v}.conf.${replaceChars ["."] ["/"] i.name}.proxy_arp" true)))
- // listToAttrs (forEach (filter (i: i.preferTempAddress) interfaces)
- (i: nameValuePair "net.ipv6.conf.${replaceChars ["."] ["/"] i.name}.use_tempaddr" 2));
+ // listToAttrs (forEach interfaces
+ (i: let
+ opt = i.tempAddress;
+ val = { disabled = 0; enabled = 1; default = 2; }.${opt};
+ in nameValuePair "net.ipv6.conf.${replaceChars ["."] ["/"] i.name}.use_tempaddr" val));
# Capabilities won't work unless we have at-least a 4.3 Linux
# kernel because we need the ambient capability
@@ -1103,10 +1176,18 @@ in
(pkgs.writeTextFile rec {
name = "ipv6-privacy-extensions.rules";
destination = "/etc/udev/rules.d/99-${name}";
- text = concatMapStrings (i: ''
- # enable IPv6 privacy addresses but prefer EUI-64 addresses for ${i.name}
- ACTION=="add", SUBSYSTEM=="net", RUN+="${pkgs.procps}/bin/sysctl net.ipv6.conf.${replaceChars ["."] ["/"] i.name}.use_tempaddr=1"
- '') (filter (i: !i.preferTempAddress) interfaces);
+ text = concatMapStrings (i:
+ let
+ opt = i.tempAddress;
+ val = if opt == "disabled" then 0 else 1;
+ msg = if opt == "disabled"
+ then "completely disable IPv6 privacy addresses"
+ else "enable IPv6 privacy addresses but prefer EUI-64 addresses";
+ in
+ ''
+ # override to ${msg} for ${i.name}
+ ACTION=="add", SUBSYSTEM=="net", RUN+="${pkgs.procps}/bin/sysctl net.ipv6.conf.${replaceChars ["."] ["/"] i.name}.use_tempaddr=${toString val}"
+ '') (filter (i: i.tempAddress != "default") interfaces);
})
] ++ lib.optional (cfg.wlanInterfaces != {})
(pkgs.writeTextFile {
diff --git a/nixpkgs/nixos/modules/testing/service-runner.nix b/nixpkgs/nixos/modules/testing/service-runner.nix
index 17d5e337690..99a9f979068 100644
--- a/nixpkgs/nixos/modules/testing/service-runner.nix
+++ b/nixpkgs/nixos/modules/testing/service-runner.nix
@@ -12,7 +12,10 @@ let
sub run {
my ($cmd) = @_;
- my @args = split " ", $cmd;
+ my @args = ();
+ while ($cmd =~ /([^ \t\n']+)|(\'([^'])\')\s*/g) {
+ push @args, $1;
+ }
my $prog;
if (substr($args[0], 0, 1) eq "@") {
$prog = substr($args[0], 1);
@@ -48,15 +51,20 @@ let
'') service.environment)}
# Run the ExecStartPre program. FIXME: this could be a list.
- my $preStart = '${service.serviceConfig.ExecStartPre or ""}';
- if ($preStart ne "") {
+ my $preStart = <<END_CMD;
+ ${service.serviceConfig.ExecStartPre or ""}
+ END_CMD
+ if (defined $preStart && $preStart ne "\n") {
print STDERR "running ExecStartPre: $preStart\n";
my $res = run_wait $preStart;
die "$0: ExecStartPre failed with status $res\n" if $res;
};
# Run the ExecStart program.
- my $cmd = '${service.serviceConfig.ExecStart}';
+ my $cmd = <<END_CMD;
+ ${service.serviceConfig.ExecStart}
+ END_CMD
+
print STDERR "running ExecStart: $cmd\n";
my $mainPid = run $cmd;
$ENV{'MAINPID'} = $mainPid;
@@ -70,8 +78,10 @@ let
$SIG{'QUIT'} = \&intHandler;
# Run the ExecStartPost program.
- my $postStart = '${service.serviceConfig.ExecStartPost or ""}';
- if ($postStart ne "") {
+ my $postStart = <<END_CMD;
+ ${service.serviceConfig.ExecStartPost or ""}
+ END_CMD
+ if (defined $postStart && $postStart ne "\n") {
print STDERR "running ExecStartPost: $postStart\n";
my $res = run_wait $postStart;
die "$0: ExecStartPost failed with status $res\n" if $res;
@@ -82,8 +92,10 @@ let
my $mainRes = $?;
# Run the ExecStopPost program.
- my $postStop = '${service.serviceConfig.ExecStopPost or ""}';
- if ($postStop ne "") {
+ my $postStop = <<END_CMD;
+ ${service.serviceConfig.ExecStopPost or ""}
+ END_CMD
+ if (defined $postStop && $postStop ne "\n") {
print STDERR "running ExecStopPost: $postStop\n";
my $res = run_wait $postStop;
die "$0: ExecStopPost failed with status $res\n" if $res;
diff --git a/nixpkgs/nixos/modules/virtualisation/docker-containers.nix b/nixpkgs/nixos/modules/virtualisation/docker-containers.nix
index 3a2eb97d1bf..5ab990a3d7c 100644
--- a/nixpkgs/nixos/modules/virtualisation/docker-containers.nix
+++ b/nixpkgs/nixos/modules/virtualisation/docker-containers.nix
@@ -39,7 +39,7 @@ let
entrypoint = mkOption {
type = with types; nullOr str;
- description = "Overwrite the default entrypoint of the image.";
+ description = "Override the default entrypoint of the image.";
default = null;
example = "/bin/my-app";
};
@@ -145,7 +145,7 @@ let
Note that this is a list of <literal>"src:dst"</literal> strings to
allow for <literal>src</literal> to refer to
- <literal>/nix/store</literal> paths, which would difficult with an
+ <literal>/nix/store</literal> paths, which would be difficult with an
attribute set. There are also a variety of mount options available
as a third field; please refer to the
<link xlink:href="https://docs.docker.com/engine/reference/run/#volume-shared-filesystems">
@@ -192,16 +192,34 @@ let
["--network=host"]
'';
};
+
+ autoStart = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ When enabled, the container is automatically started on boot.
+ If this option is set to false, the container has to be started on-demand via its service.
+ '';
+ };
};
};
mkService = name: container: let
mkAfter = map (x: "docker-${x}.service") container.dependsOn;
in rec {
- wantedBy = [ "multi-user.target" ];
+ wantedBy = [] ++ optional (container.autoStart) "multi-user.target";
after = [ "docker.service" "docker.socket" ] ++ mkAfter;
requires = after;
-
+ path = [ pkgs.docker ];
+
+ preStart = ''
+ docker rm -f ${name} || true
+ ${optionalString (container.imageFile != null) ''
+ docker load -i ${container.imageFile}
+ ''}
+ '';
+ postStop = "docker rm -f ${name} || true";
+
serviceConfig = {
ExecStart = concatStringsSep " \\\n " ([
"${pkgs.docker}/bin/docker run"
@@ -220,13 +238,7 @@ let
++ map escapeShellArg container.cmd
);
- ExecStartPre = ["-${pkgs.docker}/bin/docker rm -f ${name}"
- "-${pkgs.docker}/bin/docker image prune -f"] ++
- (optional (container.imageFile != null)
- ["${pkgs.docker}/bin/docker load -i ${container.imageFile}"]);
-
- ExecStop = ''${pkgs.bash}/bin/sh -c "[ $SERVICE_RESULT = success ] || ${pkgs.docker}/bin/docker stop ${name}"'';
- ExecStopPost = "-${pkgs.docker}/bin/docker rm -f ${name}";
+ ExecStop = ''${pkgs.bash}/bin/sh -c "[ $SERVICE_RESULT = success ] || docker stop ${name}"'';
### There is no generalized way of supporting `reload` for docker
### containers. Some containers may respond well to SIGHUP sent to their
diff --git a/nixpkgs/nixos/modules/virtualisation/hyperv-guest.nix b/nixpkgs/nixos/modules/virtualisation/hyperv-guest.nix
index 0f1f052880c..adc2810a993 100644
--- a/nixpkgs/nixos/modules/virtualisation/hyperv-guest.nix
+++ b/nixpkgs/nixos/modules/virtualisation/hyperv-guest.nix
@@ -32,7 +32,7 @@ in {
];
kernelParams = [
- "video=hyperv_fb:${cfg.videoMode}"
+ "video=hyperv_fb:${cfg.videoMode} elevator=noop"
];
};
diff --git a/nixpkgs/nixos/modules/virtualisation/kvmgt.nix b/nixpkgs/nixos/modules/virtualisation/kvmgt.nix
index 36ef6d17df6..0902d2dc2cb 100644
--- a/nixpkgs/nixos/modules/virtualisation/kvmgt.nix
+++ b/nixpkgs/nixos/modules/virtualisation/kvmgt.nix
@@ -19,7 +19,8 @@ in {
virtualisation.kvmgt = {
enable = mkEnableOption ''
KVMGT (iGVT-g) VGPU support. Allows Qemu/KVM guests to share host's Intel integrated graphics card.
- Currently only one graphical device can be shared
+ Currently only one graphical device can be shared. To allow users to access the device without root add them
+ to the kvm group: <literal>users.extraUsers.&lt;yourusername&gt;.extraGroups = [ "kvm" ];</literal>
'';
# multi GPU support is under the question
device = mkOption {
@@ -35,9 +36,7 @@ in {
and find info about device via <command>cat /sys/bus/pci/devices/*/mdev_supported_types/i915-GVTg_V5_4/description</command>
'';
example = {
- i915-GVTg_V5_8 = {
- uuid = "a297db4a-f4c2-11e6-90f6-d3b88d6c9525";
- };
+ i915-GVTg_V5_8.uuid = "a297db4a-f4c2-11e6-90f6-d3b88d6c9525";
};
};
};
@@ -50,10 +49,7 @@ in {
};
boot.kernelModules = [ "kvmgt" ];
-
- boot.extraModprobeConfig = ''
- options i915 enable_gvt=1
- '';
+ boot.kernelParams = [ "i915.enable_gvt=1" ];
systemd.paths = mapAttrs' (name: value:
nameValuePair "kvmgt-${name}" {
@@ -65,6 +61,10 @@ in {
}
) cfg.vgpus;
+ services.udev.extraRules = ''
+ SUBSYSTEM=="vfio", OWNER="root", GROUP="kvm"
+ '';
+
systemd.services = mapAttrs' (name: value:
nameValuePair "kvmgt-${name}" {
description = "KVMGT VGPU ${name}";
diff --git a/nixpkgs/nixos/modules/virtualisation/libvirtd.nix b/nixpkgs/nixos/modules/virtualisation/libvirtd.nix
index 52d852894ce..9f7bac480e3 100644
--- a/nixpkgs/nixos/modules/virtualisation/libvirtd.nix
+++ b/nixpkgs/nixos/modules/virtualisation/libvirtd.nix
@@ -219,7 +219,7 @@ in {
wantedBy = [ "multi-user.target" ];
requires = [ "libvirtd-config.service" ];
after = [ "systemd-udev-settle.service" "libvirtd-config.service" ]
- ++ optional vswitch.enable "vswitchd.service";
+ ++ optional vswitch.enable "ovs-vswitchd.service";
environment.LIBVIRTD_ARGS = ''--config "${configFile}" ${concatStringsSep " " cfg.extraOptions}'';
diff --git a/nixpkgs/nixos/modules/virtualisation/openvswitch.nix b/nixpkgs/nixos/modules/virtualisation/openvswitch.nix
index 6b8ad83661f..c6a3ceddc3e 100644
--- a/nixpkgs/nixos/modules/virtualisation/openvswitch.nix
+++ b/nixpkgs/nixos/modules/virtualisation/openvswitch.nix
@@ -124,7 +124,7 @@ in {
'';
};
- systemd.services.vswitchd = {
+ systemd.services.ovs-vswitchd = {
description = "Open_vSwitch Daemon";
wantedBy = [ "multi-user.target" ];
bindsTo = [ "ovsdb.service" ];
@@ -139,6 +139,8 @@ in {
PIDFile = "/run/openvswitch/ovs-vswitchd.pid";
# Use service type 'forking' to correctly determine when vswitchd is ready.
Type = "forking";
+ Restart = "always";
+ RestartSec = 3;
};
};
@@ -182,4 +184,7 @@ in {
'';
};
})]));
+
+ meta.maintainers = with maintainers; [ netixx ];
+
}
diff --git a/nixpkgs/nixos/modules/virtualisation/virtualbox-image.nix b/nixpkgs/nixos/modules/virtualisation/virtualbox-image.nix
index ab65523592d..788b4d9d976 100644
--- a/nixpkgs/nixos/modules/virtualisation/virtualbox-image.nix
+++ b/nixpkgs/nixos/modules/virtualisation/virtualbox-image.nix
@@ -45,10 +45,41 @@ in {
The file name of the VirtualBox appliance.
'';
};
+ params = mkOption {
+ type = with types; attrsOf (oneOf [ str int bool (listOf str) ]);
+ example = {
+ audio = "alsa";
+ rtcuseutc = "on";
+ usb = "off";
+ };
+ description = ''
+ Parameters passed to the Virtualbox appliance.
+
+ Run <literal>VBoxManage modifyvm --help</literal> to see more options.
+ '';
+ };
};
};
config = {
+
+ virtualbox.params = mkMerge [
+ (mapAttrs (name: mkDefault) {
+ acpi = "on";
+ vram = 32;
+ nictype1 = "virtio";
+ nic1 = "nat";
+ audiocontroller = "ac97";
+ audio = "alsa";
+ audioout = "on";
+ rtcuseutc = "on";
+ usb = "on";
+ usbehci = "on";
+ mouse = "usbtablet";
+ })
+ (mkIf (pkgs.stdenv.hostPlatform.system == "i686-linux") { pae = "on"; })
+ ];
+
system.build.virtualBoxOVA = import ../../lib/make-disk-image.nix {
name = cfg.vmDerivationName;
@@ -69,12 +100,8 @@ in {
VBoxManage createvm --name "$vmName" --register \
--ostype ${if pkgs.stdenv.hostPlatform.system == "x86_64-linux" then "Linux26_64" else "Linux26"}
VBoxManage modifyvm "$vmName" \
- --memory ${toString cfg.memorySize} --acpi on --vram 32 \
- ${optionalString (pkgs.stdenv.hostPlatform.system == "i686-linux") "--pae on"} \
- --nictype1 virtio --nic1 nat \
- --audiocontroller ac97 --audio alsa --audioout on \
- --rtcuseutc on \
- --usb on --usbehci on --mouse usbtablet
+ --memory ${toString cfg.memorySize} \
+ ${lib.cli.toGNUCommandLineShell { } cfg.params}
VBoxManage storagectl "$vmName" --name SATA --add sata --portcount 4 --bootable on --hostiocache on
VBoxManage storageattach "$vmName" --storagectl SATA --port 0 --device 0 --type hdd \
--medium disk.vmdk
diff --git a/nixpkgs/nixos/release-combined.nix b/nixpkgs/nixos/release-combined.nix
index b46731863ca..9377a931a75 100644
--- a/nixpkgs/nixos/release-combined.nix
+++ b/nixpkgs/nixos/release-combined.nix
@@ -38,109 +38,98 @@ in rec {
nixpkgs = nixpkgsSrc;
})) [ "unstable" ];
- tested = pkgs.lib.hydraJob (pkgs.releaseTools.aggregate {
+ tested = pkgs.releaseTools.aggregate {
name = "nixos-${nixos.channel.version}";
meta = {
description = "Release-critical builds for the NixOS channel";
maintainers = with pkgs.lib.maintainers; [ eelco fpletz ];
};
- constituents =
- let
- # Except for the given systems, return the system-specific constituent
- except = systems: x: map (system: x.${system}) (pkgs.lib.subtractLists systems supportedSystems);
- all = x: except [] x;
- in [
- nixos.channel
- (all nixos.dummy)
- (all nixos.manual)
-
- nixos.iso_plasma5.x86_64-linux or []
- nixos.iso_minimal.aarch64-linux or []
- nixos.iso_minimal.i686-linux or []
- nixos.iso_minimal.x86_64-linux or []
- nixos.ova.x86_64-linux or []
- nixos.sd_image.aarch64-linux or []
-
- #(all nixos.tests.containers)
- (all nixos.tests.containers-imperative)
- (all nixos.tests.containers-ip)
- nixos.tests.chromium.x86_64-linux or []
- (all nixos.tests.firefox)
- (all nixos.tests.firewall)
- (all nixos.tests.fontconfig-default-fonts)
- (all nixos.tests.gnome3-xorg)
- (all nixos.tests.gnome3)
- (all nixos.tests.pantheon)
- nixos.tests.installer.zfsroot.x86_64-linux or [] # ZFS is 64bit only
- (except ["aarch64-linux"] nixos.tests.installer.lvm)
- (except ["aarch64-linux"] nixos.tests.installer.luksroot)
- (except ["aarch64-linux"] nixos.tests.installer.separateBoot)
- (except ["aarch64-linux"] nixos.tests.installer.separateBootFat)
- (except ["aarch64-linux"] nixos.tests.installer.simple)
- (except ["aarch64-linux"] nixos.tests.installer.simpleLabels)
- (except ["aarch64-linux"] nixos.tests.installer.simpleProvided)
- (except ["aarch64-linux"] nixos.tests.installer.simpleUefiSystemdBoot)
- (except ["aarch64-linux"] nixos.tests.installer.swraid)
- (except ["aarch64-linux"] nixos.tests.installer.btrfsSimple)
- (except ["aarch64-linux"] nixos.tests.installer.btrfsSubvols)
- (except ["aarch64-linux"] nixos.tests.installer.btrfsSubvolDefault)
- (except ["aarch64-linux"] nixos.tests.boot.biosCdrom)
- #(except ["aarch64-linux"] nixos.tests.boot.biosUsb) # disabled due to issue #15690
- (except ["aarch64-linux"] nixos.tests.boot.uefiCdrom)
- (except ["aarch64-linux"] nixos.tests.boot.uefiUsb)
- (all nixos.tests.boot-stage1)
- (all nixos.tests.hibernate)
- nixos.tests.docker.x86_64-linux or []
- (all nixos.tests.ecryptfs)
- (all nixos.tests.env)
- (all nixos.tests.ipv6)
- (all nixos.tests.i3wm)
- # 2018-06-06: keymap tests temporarily removed from tested job
- # since non-deterministic failure are blocking the channel (#41538)
- #(all nixos.tests.keymap.azerty)
- #(all nixos.tests.keymap.colemak)
- #(all nixos.tests.keymap.dvorak)
- #(all nixos.tests.keymap.dvp)
- #(all nixos.tests.keymap.neo)
- #(all nixos.tests.keymap.qwertz)
- (all nixos.tests.plasma5)
- (all nixos.tests.lightdm)
- (all nixos.tests.login)
- (all nixos.tests.misc)
- (all nixos.tests.mutableUsers)
- (all nixos.tests.nat.firewall)
- (all nixos.tests.nat.firewall-conntrack)
- (all nixos.tests.nat.standalone)
- (all nixos.tests.networking.scripted.loopback)
- (all nixos.tests.networking.scripted.static)
- (all nixos.tests.networking.scripted.dhcpSimple)
- (all nixos.tests.networking.scripted.dhcpOneIf)
- (all nixos.tests.networking.scripted.bond)
- (all nixos.tests.networking.scripted.bridge)
- (all nixos.tests.networking.scripted.macvlan)
- (all nixos.tests.networking.scripted.sit)
- (all nixos.tests.networking.scripted.vlan)
- (all nixos.tests.nfs3.simple)
- (all nixos.tests.nfs4.simple)
- (all nixos.tests.openssh)
- (all nixos.tests.php-pcre)
- (all nixos.tests.predictable-interface-names.predictable)
- (all nixos.tests.predictable-interface-names.unpredictable)
- (all nixos.tests.predictable-interface-names.predictableNetworkd)
- (all nixos.tests.predictable-interface-names.unpredictableNetworkd)
- (all nixos.tests.printing)
- (all nixos.tests.proxy)
- (all nixos.tests.sddm.default)
- (all nixos.tests.simple)
- (all nixos.tests.switchTest)
- (all nixos.tests.udisks2)
- (all nixos.tests.xfce)
-
- nixpkgs.tarball
- (all allSupportedNixpkgs.emacs)
- # The currently available aarch64 JDK is unfree
- (except ["aarch64-linux"] allSupportedNixpkgs.jdk)
- ];
- });
+ constituents = [
+ "nixos.channel"
+ "nixos.dummy.x86_64-linux"
+ "nixos.iso_minimal.aarch64-linux"
+ "nixos.iso_minimal.i686-linux"
+ "nixos.iso_minimal.x86_64-linux"
+ "nixos.iso_plasma5.x86_64-linux"
+ "nixos.manual.x86_64-linux"
+ "nixos.ova.x86_64-linux"
+ "nixos.sd_image.aarch64-linux"
+ "nixos.tests.boot.biosCdrom.x86_64-linux"
+ "nixos.tests.boot.biosUsb.x86_64-linux"
+ "nixos.tests.boot-stage1.x86_64-linux"
+ "nixos.tests.boot.uefiCdrom.x86_64-linux"
+ "nixos.tests.boot.uefiUsb.x86_64-linux"
+ "nixos.tests.chromium.x86_64-linux"
+ "nixos.tests.containers-imperative.x86_64-linux"
+ "nixos.tests.containers-ip.x86_64-linux"
+ "nixos.tests.docker.x86_64-linux"
+ "nixos.tests.ecryptfs.x86_64-linux"
+ "nixos.tests.env.x86_64-linux"
+ "nixos.tests.firefox-esr.x86_64-linux"
+ "nixos.tests.firefox.x86_64-linux"
+ "nixos.tests.firewall.x86_64-linux"
+ "nixos.tests.fontconfig-default-fonts.x86_64-linux"
+ "nixos.tests.gnome3.x86_64-linux"
+ "nixos.tests.gnome3-xorg.x86_64-linux"
+ "nixos.tests.hibernate.x86_64-linux"
+ "nixos.tests.i3wm.x86_64-linux"
+ "nixos.tests.installer.btrfsSimple.x86_64-linux"
+ "nixos.tests.installer.btrfsSubvolDefault.x86_64-linux"
+ "nixos.tests.installer.btrfsSubvols.x86_64-linux"
+ "nixos.tests.installer.luksroot.x86_64-linux"
+ "nixos.tests.installer.lvm.x86_64-linux"
+ "nixos.tests.installer.separateBootFat.x86_64-linux"
+ "nixos.tests.installer.separateBoot.x86_64-linux"
+ "nixos.tests.installer.simpleLabels.x86_64-linux"
+ "nixos.tests.installer.simpleProvided.x86_64-linux"
+ "nixos.tests.installer.simpleUefiSystemdBoot.x86_64-linux"
+ "nixos.tests.installer.simple.x86_64-linux"
+ "nixos.tests.installer.swraid.x86_64-linux"
+ "nixos.tests.ipv6.x86_64-linux"
+ "nixos.tests.keymap.azerty.x86_64-linux"
+ "nixos.tests.keymap.colemak.x86_64-linux"
+ "nixos.tests.keymap.dvorak.x86_64-linux"
+ "nixos.tests.keymap.dvp.x86_64-linux"
+ "nixos.tests.keymap.neo.x86_64-linux"
+ "nixos.tests.keymap.qwertz.x86_64-linux"
+ "nixos.tests.lightdm.x86_64-linux"
+ "nixos.tests.login.x86_64-linux"
+ "nixos.tests.misc.x86_64-linux"
+ "nixos.tests.mutableUsers.x86_64-linux"
+ "nixos.tests.nat.firewall-conntrack.x86_64-linux"
+ "nixos.tests.nat.firewall.x86_64-linux"
+ "nixos.tests.nat.standalone.x86_64-linux"
+ "nixos.tests.networking.scripted.bond.x86_64-linux"
+ "nixos.tests.networking.scripted.bridge.x86_64-linux"
+ "nixos.tests.networking.scripted.dhcpOneIf.x86_64-linux"
+ "nixos.tests.networking.scripted.dhcpSimple.x86_64-linux"
+ "nixos.tests.networking.scripted.loopback.x86_64-linux"
+ "nixos.tests.networking.scripted.macvlan.x86_64-linux"
+ "nixos.tests.networking.scripted.sit.x86_64-linux"
+ "nixos.tests.networking.scripted.static.x86_64-linux"
+ "nixos.tests.networking.scripted.vlan.x86_64-linux"
+ "nixos.tests.nfs3.simple.x86_64-linux"
+ "nixos.tests.nfs4.simple.x86_64-linux"
+ "nixos.tests.openssh.x86_64-linux"
+ "nixos.tests.pantheon.x86_64-linux"
+ "nixos.tests.php-pcre.x86_64-linux"
+ "nixos.tests.plasma5.x86_64-linux"
+ "nixos.tests.predictable-interface-names.predictableNetworkd.x86_64-linux"
+ "nixos.tests.predictable-interface-names.predictable.x86_64-linux"
+ "nixos.tests.predictable-interface-names.unpredictableNetworkd.x86_64-linux"
+ "nixos.tests.predictable-interface-names.unpredictable.x86_64-linux"
+ "nixos.tests.printing.x86_64-linux"
+ "nixos.tests.proxy.x86_64-linux"
+ "nixos.tests.sddm.default.x86_64-linux"
+ "nixos.tests.simple.x86_64-linux"
+ "nixos.tests.switchTest.x86_64-linux"
+ "nixos.tests.udisks2.x86_64-linux"
+ "nixos.tests.xfce.x86_64-linux"
+ "nixos.tests.zfs.installer.i686-linux"
+ "nixpkgs.emacs.x86_64-linux"
+ "nixpkgs.jdk.x86_64-linux"
+ "nixpkgs.tarball"
+ ];
+ };
}
diff --git a/nixpkgs/nixos/release-small.nix b/nixpkgs/nixos/release-small.nix
index 74c16e990f3..7b86a91357e 100644
--- a/nixpkgs/nixos/release-small.nix
+++ b/nixpkgs/nixos/release-small.nix
@@ -82,18 +82,42 @@ in rec {
vim;
};
- tested = lib.hydraJob (pkgs.releaseTools.aggregate {
+ tested = pkgs.releaseTools.aggregate {
name = "nixos-${nixos.channel.version}";
meta = {
description = "Release-critical builds for the NixOS channel";
maintainers = [ lib.maintainers.eelco ];
};
constituents =
- let all = x: map (system: x.${system}) supportedSystems; in
- [ nixpkgs.tarball
- (all nixpkgs.jdk)
- ]
- ++ lib.collect lib.isDerivation nixos;
- });
+ [ "nixos.channel"
+ "nixos.dummy.x86_64-linux"
+ "nixos.iso_minimal.x86_64-linux"
+ "nixos.manual.x86_64-linux"
+ "nixos.tests.boot.biosCdrom.x86_64-linux"
+ "nixos.tests.containers-imperative.x86_64-linux"
+ "nixos.tests.containers-ip.x86_64-linux"
+ "nixos.tests.firewall.x86_64-linux"
+ "nixos.tests.installer.lvm.x86_64-linux"
+ "nixos.tests.installer.separateBoot.x86_64-linux"
+ "nixos.tests.installer.simple.x86_64-linux"
+ "nixos.tests.ipv6.x86_64-linux"
+ "nixos.tests.login.x86_64-linux"
+ "nixos.tests.misc.x86_64-linux"
+ "nixos.tests.nat.firewall-conntrack.x86_64-linux"
+ "nixos.tests.nat.firewall.x86_64-linux"
+ "nixos.tests.nat.standalone.x86_64-linux"
+ "nixos.tests.nfs3.simple.x86_64-linux"
+ "nixos.tests.openssh.x86_64-linux"
+ "nixos.tests.php-pcre.x86_64-linux"
+ "nixos.tests.predictable-interface-names.predictable.x86_64-linux"
+ "nixos.tests.predictable-interface-names.predictableNetworkd.x86_64-linux"
+ "nixos.tests.predictable-interface-names.unpredictable.x86_64-linux"
+ "nixos.tests.predictable-interface-names.unpredictableNetworkd.x86_64-linux"
+ "nixos.tests.proxy.x86_64-linux"
+ "nixos.tests.simple.x86_64-linux"
+ "nixpkgs.jdk.x86_64-linux"
+ "nixpkgs.tarball"
+ ];
+ };
}
diff --git a/nixpkgs/nixos/release.nix b/nixpkgs/nixos/release.nix
index 512ba714397..6107f352971 100644
--- a/nixpkgs/nixos/release.nix
+++ b/nixpkgs/nixos/release.nix
@@ -20,7 +20,7 @@ let
allTestsForSystem = system:
import ./tests/all-tests.nix {
inherit system;
- pkgs = import nixpkgs { inherit system; };
+ pkgs = import ./.. { inherit system; };
callTest = t: {
${system} = hydraJob t.test;
};
@@ -28,7 +28,7 @@ let
allTests =
foldAttrs recursiveUpdate {} (map allTestsForSystem supportedSystems);
- pkgs = import nixpkgs { system = "x86_64-linux"; };
+ pkgs = import ./.. { system = "x86_64-linux"; };
versionModule =
@@ -41,7 +41,7 @@ let
makeIso =
{ module, type, system, ... }:
- with import nixpkgs { inherit system; };
+ with import ./.. { inherit system; };
hydraJob ((import lib/eval-config.nix {
inherit system;
@@ -54,7 +54,7 @@ let
makeSdImage =
{ module, system, ... }:
- with import nixpkgs { inherit system; };
+ with import ./.. { inherit system; };
hydraJob ((import lib/eval-config.nix {
inherit system;
@@ -65,7 +65,7 @@ let
makeSystemTarball =
{ module, maintainers ? ["viric"], system }:
- with import nixpkgs { inherit system; };
+ with import ./.. { inherit system; };
let
@@ -188,7 +188,7 @@ in rec {
# A bootable VirtualBox virtual appliance as an OVA file (i.e. packaged OVF).
ova = forMatchingSystems [ "x86_64-linux" ] (system:
- with import nixpkgs { inherit system; };
+ with import ./.. { inherit system; };
hydraJob ((import lib/eval-config.nix {
inherit system;
@@ -204,7 +204,7 @@ in rec {
# A disk image that can be imported to Amazon EC2 and registered as an AMI
amazonImage = forMatchingSystems [ "x86_64-linux" "aarch64-linux" ] (system:
- with import nixpkgs { inherit system; };
+ with import ./.. { inherit system; };
hydraJob ((import lib/eval-config.nix {
inherit system;
diff --git a/nixpkgs/nixos/tests/acme.nix b/nixpkgs/nixos/tests/acme.nix
index 6bd315ff1ea..e045f3415fa 100644
--- a/nixpkgs/nixos/tests/acme.nix
+++ b/nixpkgs/nixos/tests/acme.nix
@@ -1,17 +1,50 @@
let
commonConfig = ./common/letsencrypt/common.nix;
+
+ dnsScript = {writeScript, dnsAddress, bash, curl}: writeScript "dns-hook.sh" ''
+ #!${bash}/bin/bash
+ set -euo pipefail
+ echo '[INFO]' "[$2]" 'dns-hook.sh' $*
+ if [ "$1" = "present" ]; then
+ ${curl}/bin/curl --data '{"host": "'"$2"'", "value": "'"$3"'"}' http://${dnsAddress}:8055/set-txt
+ else
+ ${curl}/bin/curl --data '{"host": "'"$2"'"}' http://${dnsAddress}:8055/clear-txt
+ fi
+ '';
+
in import ./make-test-python.nix {
name = "acme";
nodes = rec {
- letsencrypt = ./common/letsencrypt;
+ letsencrypt = { nodes, lib, ... }: {
+ imports = [ ./common/letsencrypt ];
+ networking.nameservers = lib.mkForce [
+ nodes.dnsserver.config.networking.primaryIPAddress
+ ];
+ };
+
+ dnsserver = { nodes, pkgs, ... }: {
+ networking.firewall.allowedTCPPorts = [ 8055 53 ];
+ networking.firewall.allowedUDPPorts = [ 53 ];
+ systemd.services.pebble-challtestsrv = {
+ enable = true;
+ description = "Pebble ACME challenge test server";
+ wantedBy = [ "network.target" ];
+ serviceConfig = {
+ ExecStart = "${pkgs.pebble}/bin/pebble-challtestsrv -dns01 ':53' -defaultIPv6 '' -defaultIPv4 '${nodes.webserver.config.networking.primaryIPAddress}'";
+ # Required to bind on privileged ports.
+ User = "root";
+ Group = "root";
+ };
+ };
+ };
- acmeStandalone = { config, pkgs, ... }: {
+ acmeStandalone = { nodes, lib, config, pkgs, ... }: {
imports = [ commonConfig ];
+ networking.nameservers = lib.mkForce [
+ nodes.dnsserver.config.networking.primaryIPAddress
+ ];
networking.firewall.allowedTCPPorts = [ 80 ];
- networking.extraHosts = ''
- ${config.networking.primaryIPAddress} standalone.com
- '';
security.acme = {
server = "https://acme-v02.api.letsencrypt.org/dir";
certs."standalone.com" = {
@@ -29,14 +62,12 @@ in import ./make-test-python.nix {
};
};
- webserver = { config, pkgs, ... }: {
+ webserver = { nodes, config, pkgs, lib, ... }: {
imports = [ commonConfig ];
networking.firewall.allowedTCPPorts = [ 80 443 ];
-
- networking.extraHosts = ''
- ${config.networking.primaryIPAddress} a.example.com
- ${config.networking.primaryIPAddress} b.example.com
- '';
+ networking.nameservers = lib.mkForce [
+ nodes.dnsserver.config.networking.primaryIPAddress
+ ];
# A target remains active. Use this to probe the fact that
# a service fired eventhough it is not RemainAfterExit
@@ -44,6 +75,7 @@ in import ./make-test-python.nix {
systemd.services."acme-a.example.com" = {
wants = [ "acme-finished-a.example.com.target" ];
before = [ "acme-finished-a.example.com.target" ];
+ after = [ "nginx.service" ];
};
services.nginx.enable = true;
@@ -61,14 +93,11 @@ in import ./make-test-python.nix {
nesting.clone = [
({pkgs, ...}: {
-
- networking.extraHosts = ''
- ${config.networking.primaryIPAddress} b.example.com
- '';
systemd.targets."acme-finished-b.example.com" = {};
systemd.services."acme-b.example.com" = {
wants = [ "acme-finished-b.example.com.target" ];
before = [ "acme-finished-b.example.com.target" ];
+ after = [ "nginx.service" ];
};
services.nginx.virtualHosts."b.example.com" = {
enableACME = true;
@@ -79,15 +108,48 @@ in import ./make-test-python.nix {
'';
};
})
+ ({pkgs, config, nodes, lib, ...}: {
+ security.acme.certs."example.com" = {
+ domain = "*.example.com";
+ dnsProvider = "exec";
+ dnsPropagationCheck = false;
+ credentialsFile = with pkgs; writeText "wildcard.env" ''
+ EXEC_PATH=${dnsScript { inherit writeScript bash curl; dnsAddress = nodes.dnsserver.config.networking.primaryIPAddress; }}
+ '';
+ user = config.services.nginx.user;
+ group = config.services.nginx.group;
+ };
+ systemd.targets."acme-finished-example.com" = {};
+ systemd.services."acme-example.com" = {
+ wants = [ "acme-finished-example.com.target" ];
+ before = [ "acme-finished-example.com.target" "nginx.service" ];
+ wantedBy = [ "nginx.service" ];
+ };
+ services.nginx.virtualHosts."c.example.com" = {
+ forceSSL = true;
+ sslCertificate = config.security.acme.certs."example.com".directory + "/cert.pem";
+ sslTrustedCertificate = config.security.acme.certs."example.com".directory + "/full.pem";
+ sslCertificateKey = config.security.acme.certs."example.com".directory + "/key.pem";
+ locations."/".root = pkgs.runCommand "docroot" {} ''
+ mkdir -p "$out"
+ echo hello world > "$out/index.html"
+ '';
+ };
+ })
];
};
- client = commonConfig;
+ client = {nodes, lib, ...}: {
+ imports = [ commonConfig ];
+ networking.nameservers = lib.mkForce [
+ nodes.dnsserver.config.networking.primaryIPAddress
+ ];
+ };
};
testScript = {nodes, ...}:
let
- newServerSystem = nodes.webserver2.config.system.build.toplevel;
+ newServerSystem = nodes.webserver.config.system.build.toplevel;
switchToNewServer = "${newServerSystem}/bin/switch-to-configuration test";
in
# Note, wait_for_unit does not work for oneshot services that do not have RemainAfterExit=true,
@@ -97,6 +159,17 @@ in import ./make-test-python.nix {
# can use them to probe that a oneshot fired. It is a bit ugly, but it is the best we can do
''
client.start()
+ dnsserver.start()
+
+ letsencrypt.wait_for_unit("default.target")
+ dnsserver.wait_for_unit("pebble-challtestsrv.service")
+ client.succeed(
+ 'curl --data \'{"host": "acme-v02.api.letsencrypt.org", "addresses": ["${nodes.letsencrypt.config.networking.primaryIPAddress}"]}\' http://${nodes.dnsserver.config.networking.primaryIPAddress}:8055/add-a'
+ )
+ client.succeed(
+ 'curl --data \'{"host": "standalone.com", "addresses": ["${nodes.acmeStandalone.config.networking.primaryIPAddress}"]}\' http://${nodes.dnsserver.config.networking.primaryIPAddress}:8055/add-a'
+ )
+
letsencrypt.start()
acmeStandalone.start()
@@ -129,5 +202,17 @@ in import ./make-test-python.nix {
client.succeed(
"curl --cacert /tmp/ca.crt https://b.example.com/ | grep -qF 'hello world'"
)
+
+ with subtest("Can request wildcard certificates using DNS-01 challenge"):
+ webserver.succeed(
+ "${switchToNewServer}"
+ )
+ webserver.succeed(
+ "/run/current-system/fine-tune/child-2/bin/switch-to-configuration test"
+ )
+ webserver.wait_for_unit("acme-finished-example.com.target")
+ client.succeed(
+ "curl --cacert /tmp/ca.crt https://c.example.com/ | grep -qF 'hello world'"
+ )
'';
}
diff --git a/nixpkgs/nixos/tests/all-tests.nix b/nixpkgs/nixos/tests/all-tests.nix
index 6bace8ffe6d..51b463747b0 100644
--- a/nixpkgs/nixos/tests/all-tests.nix
+++ b/nixpkgs/nixos/tests/all-tests.nix
@@ -32,13 +32,14 @@ in
bees = handleTest ./bees.nix {};
bind = handleTest ./bind.nix {};
bittorrent = handleTest ./bittorrent.nix {};
- buildkite-agent = handleTest ./buildkite-agent.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 {};
borgbackup = handleTest ./borgbackup.nix {};
buildbot = handleTest ./buildbot.nix {};
caddy = handleTest ./caddy.nix {};
cadvisor = handleTestOn ["x86_64-linux"] ./cadvisor.nix {};
+ cage = handleTest ./cage.nix {};
cassandra = handleTest ./cassandra.nix {};
ceph-single-node = handleTestOn ["x86_64-linux"] ./ceph-single-node.nix {};
ceph-multi-node = handleTestOn ["x86_64-linux"] ./ceph-multi-node.nix {};
@@ -65,7 +66,7 @@ in
couchdb = handleTest ./couchdb.nix {};
deluge = handleTest ./deluge.nix {};
dhparams = handleTest ./dhparams.nix {};
- dnscrypt-proxy = handleTestOn ["x86_64-linux"] ./dnscrypt-proxy.nix {};
+ dnscrypt-proxy2 = handleTestOn ["x86_64-linux"] ./dnscrypt-proxy2.nix {};
docker = handleTestOn ["x86_64-linux"] ./docker.nix {};
docker-containers = handleTestOn ["x86_64-linux"] ./docker-containers.nix {};
docker-edge = handleTestOn ["x86_64-linux"] ./docker-edge.nix {};
@@ -88,6 +89,7 @@ in
fancontrol = handleTest ./fancontrol.nix {};
ferm = handleTest ./ferm.nix {};
firefox = handleTest ./firefox.nix {};
+ firefox-esr = handleTest ./firefox.nix { esr = true; };
firewall = handleTest ./firewall.nix {};
fish = handleTest ./fish.nix {};
flannel = handleTestOn ["x86_64-linux"] ./flannel.nix {};
@@ -96,6 +98,8 @@ in
freeswitch = handleTest ./freeswitch.nix {};
fsck = handleTest ./fsck.nix {};
gotify-server = handleTest ./gotify-server.nix {};
+ grocy = handleTest ./grocy.nix {};
+ gitdaemon = handleTest ./gitdaemon.nix {};
gitea = handleTest ./gitea.nix {};
gitlab = handleTest ./gitlab.nix {};
gitolite = handleTest ./gitolite.nix {};
@@ -131,10 +135,12 @@ in
initrd-network-ssh = handleTest ./initrd-network-ssh {};
initrdNetwork = handleTest ./initrd-network.nix {};
installer = handleTest ./installer.nix {};
+ iodine = handleTest ./iodine.nix {};
ipv6 = handleTest ./ipv6.nix {};
jackett = handleTest ./jackett.nix {};
jellyfin = handleTest ./jellyfin.nix {};
jenkins = handleTest ./jenkins.nix {};
+ jirafeau = handleTest ./jirafeau.nix {};
kafka = handleTest ./kafka.nix {};
keepalived = handleTest ./keepalived.nix {};
kerberos = handleTest ./kerberos/default.nix {};
@@ -143,6 +149,7 @@ in
kernel-testing = handleTest ./kernel-testing.nix {};
keymap = handleTest ./keymap.nix {};
knot = handleTest ./knot.nix {};
+ krb5 = discoverTests (import ./krb5 {});
kubernetes.dns = handleTestOn ["x86_64-linux"] ./kubernetes/dns.nix {};
# kubernetes.e2e should eventually replace kubernetes.rbac when it works
#kubernetes.e2e = handleTestOn ["x86_64-linux"] ./kubernetes/e2e.nix {};
@@ -213,8 +220,7 @@ in
openldap = handleTest ./openldap.nix {};
opensmtpd = handleTest ./opensmtpd.nix {};
openssh = handleTest ./openssh.nix {};
- # openstack-image-userdata doesn't work in a sandbox as the simulated openstack instance needs network access
- #openstack-image-userdata = (handleTestOn ["x86_64-linux"] ./openstack-image.nix {}).userdata or {};
+ openstack-image-userdata = (handleTestOn ["x86_64-linux"] ./openstack-image.nix {}).userdata or {};
openstack-image-metadata = (handleTestOn ["x86_64-linux"] ./openstack-image.nix {}).metadata or {};
orangefs = handleTest ./orangefs.nix {};
os-prober = handleTestOn ["x86_64-linux"] ./os-prober.nix {};
@@ -249,6 +255,7 @@ in
radicale = handleTest ./radicale.nix {};
redis = handleTest ./redis.nix {};
redmine = handleTest ./redmine.nix {};
+ restic = handleTest ./restic.nix {};
roundcube = handleTest ./roundcube.nix {};
rspamd = handleTest ./rspamd.nix {};
rss2email = handleTest ./rss2email.nix {};
@@ -256,7 +263,9 @@ in
runInMachine = handleTest ./run-in-machine.nix {};
rxe = handleTest ./rxe.nix {};
samba = handleTest ./samba.nix {};
+ sanoid = handleTest ./sanoid.nix {};
sddm = handleTest ./sddm.nix {};
+ service-runner = handleTest ./service-runner.nix {};
shiori = handleTest ./shiori.nix {};
signal-desktop = handleTest ./signal-desktop.nix {};
simple = handleTest ./simple.nix {};
@@ -269,13 +278,15 @@ in
strongswan-swanctl = handleTest ./strongswan-swanctl.nix {};
sudo = handleTest ./sudo.nix {};
switchTest = handleTest ./switch-test.nix {};
+ sympa = handleTest ./sympa.nix {};
syncthing-init = handleTest ./syncthing-init.nix {};
syncthing-relay = handleTest ./syncthing-relay.nix {};
systemd = handleTest ./systemd.nix {};
systemd-analyze = handleTest ./systemd-analyze.nix {};
systemd-confinement = handleTest ./systemd-confinement.nix {};
systemd-timesyncd = handleTest ./systemd-timesyncd.nix {};
- systemd-networkd-wireguard = handleTest ./systemd-networkd-wireguard.nix {};
+ systemd-networkd-vrf = handleTest ./systemd-networkd-vrf.nix {};
+ systemd-networkd = handleTest ./systemd-networkd.nix {};
systemd-nspawn = handleTest ./systemd-nspawn.nix {};
pdns-recursor = handleTest ./pdns-recursor.nix {};
taskserver = handleTest ./taskserver.nix {};
@@ -307,6 +318,7 @@ in
xss-lock = handleTest ./xss-lock.nix {};
yabar = handleTest ./yabar.nix {};
yggdrasil = handleTest ./yggdrasil.nix {};
+ zfs = handleTest ./zfs.nix {};
zsh-history = handleTest ./zsh-history.nix {};
zookeeper = handleTest ./zookeeper.nix {};
}
diff --git a/nixpkgs/nixos/tests/buildbot.nix b/nixpkgs/nixos/tests/buildbot.nix
index f5c8c4863b6..0d979dc2d05 100644
--- a/nixpkgs/nixos/tests/buildbot.nix
+++ b/nixpkgs/nixos/tests/buildbot.nix
@@ -1,12 +1,11 @@
+# Test ensures buildbot master comes up correctly and workers can connect
+
{ system ? builtins.currentSystem,
config ? {},
pkgs ? import ../.. { inherit system config; }
}:
-with import ../lib/testing.nix { inherit system pkgs; };
-
-# Test ensures buildbot master comes up correctly and workers can connect
-makeTest {
+import ./make-test-python.nix {
name = "buildbot";
nodes = {
@@ -39,75 +38,76 @@ makeTest {
services.openssh.enable = true;
networking.firewall.allowedTCPPorts = [ 22 9418 ];
environment.systemPackages = with pkgs; [ git ];
+ systemd.services.git-daemon = {
+ description = "Git daemon for the test";
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network.target" "sshd.service" ];
+
+ serviceConfig.Restart = "always";
+ path = with pkgs; [ coreutils git openssh ];
+ environment = { HOME = "/root"; };
+ preStart = ''
+ git config --global user.name 'Nobody Fakeuser'
+ git config --global user.email 'nobody\@fakerepo.com'
+ rm -rvf /srv/repos/fakerepo.git /tmp/fakerepo
+ mkdir -pv /srv/repos/fakerepo ~/.ssh
+ ssh-keyscan -H gitrepo > ~/.ssh/known_hosts
+ cat ~/.ssh/known_hosts
+
+ mkdir -p /src/repos/fakerepo
+ cd /srv/repos/fakerepo
+ rm -rf *
+ git init
+ echo -e '#!/bin/sh\necho fakerepo' > fakerepo.sh
+ cat fakerepo.sh
+ touch .git/git-daemon-export-ok
+ git add fakerepo.sh .git/git-daemon-export-ok
+ git commit -m fakerepo
+ '';
+ script = ''
+ git daemon --verbose --export-all --base-path=/srv/repos --reuseaddr
+ '';
+ };
};
};
testScript = ''
- #Start up and populate fake repo
- $gitrepo->waitForUnit("multi-user.target");
- print($gitrepo->execute(" \
- git config --global user.name 'Nobody Fakeuser' && \
- git config --global user.email 'nobody\@fakerepo.com' && \
- rm -rvf /srv/repos/fakerepo.git /tmp/fakerepo && \
- mkdir -pv /srv/repos/fakerepo ~/.ssh && \
- ssh-keyscan -H gitrepo > ~/.ssh/known_hosts && \
- cat ~/.ssh/known_hosts && \
- cd /srv/repos/fakerepo && \
- git init && \
- echo -e '#!/bin/sh\necho fakerepo' > fakerepo.sh && \
- cat fakerepo.sh && \
- touch .git/git-daemon-export-ok && \
- git add fakerepo.sh .git/git-daemon-export-ok && \
- git commit -m fakerepo && \
- git daemon --verbose --export-all --base-path=/srv/repos --reuseaddr & \
- "));
-
- # Test gitrepo
- $bbmaster->waitForUnit("network-online.target");
- #$bbmaster->execute("nc -z gitrepo 9418");
- print($bbmaster->execute(" \
- rm -rfv /tmp/fakerepo && \
- git clone git://gitrepo/fakerepo /tmp/fakerepo && \
- pwd && \
- ls -la && \
- ls -la /tmp/fakerepo \
- "));
-
- # Test start master and connect worker
- $bbmaster->waitForUnit("buildbot-master.service");
- $bbmaster->waitUntilSucceeds("curl -s --head http://bbmaster:8010") =~ /200 OK/;
- $bbworker->waitForUnit("network-online.target");
- $bbworker->execute("nc -z bbmaster 8010");
- $bbworker->execute("nc -z bbmaster 9989");
- $bbworker->waitForUnit("buildbot-worker.service");
- print($bbworker->execute("ls -la /home/bbworker/worker"));
-
+ gitrepo.wait_for_unit("git-daemon.service")
+ gitrepo.wait_for_unit("multi-user.target")
- # Test stop buildbot master and worker
- print($bbmaster->execute(" \
- systemctl -l --no-pager status buildbot-master && \
- systemctl stop buildbot-master \
- "));
- $bbworker->fail("nc -z bbmaster 8010");
- $bbworker->fail("nc -z bbmaster 9989");
- print($bbworker->execute(" \
- systemctl -l --no-pager status buildbot-worker && \
- systemctl stop buildbot-worker && \
- ls -la /home/bbworker/worker \
- "));
+ with subtest("Repo is accessible via git daemon"):
+ bbmaster.wait_for_unit("network-online.target")
+ bbmaster.succeed("rm -rfv /tmp/fakerepo")
+ bbmaster.succeed("git clone git://gitrepo/fakerepo /tmp/fakerepo")
+ with subtest("Master service and worker successfully connect"):
+ bbmaster.wait_for_unit("buildbot-master.service")
+ bbmaster.wait_until_succeeds("curl --fail -s --head http://bbmaster:8010")
+ bbworker.wait_for_unit("network-online.target")
+ bbworker.succeed("nc -z bbmaster 8010")
+ bbworker.succeed("nc -z bbmaster 9989")
+ bbworker.wait_for_unit("buildbot-worker.service")
- # Test buildbot daemon mode
- $bbmaster->execute("buildbot create-master /tmp");
- $bbmaster->execute("mv -fv /tmp/master.cfg.sample /tmp/master.cfg");
- $bbmaster->execute("sed -i 's/8010/8011/' /tmp/master.cfg");
- $bbmaster->execute("buildbot start /tmp");
- $bbworker->execute("nc -z bbmaster 8011");
- $bbworker->waitUntilSucceeds("curl -s --head http://bbmaster:8011") =~ /200 OK/;
- $bbmaster->execute("buildbot stop /tmp");
- $bbworker->fail("nc -z bbmaster 8011");
+ with subtest("Stop buildbot worker"):
+ bbmaster.succeed("systemctl -l --no-pager status buildbot-master")
+ bbmaster.succeed("systemctl stop buildbot-master")
+ bbworker.fail("nc -z bbmaster 8010")
+ bbworker.fail("nc -z bbmaster 9989")
+ bbworker.succeed("systemctl -l --no-pager status buildbot-worker")
+ bbworker.succeed("systemctl stop buildbot-worker")
+ with subtest("Buildbot daemon mode works"):
+ bbmaster.succeed(
+ "buildbot create-master /tmp",
+ "mv -fv /tmp/master.cfg.sample /tmp/master.cfg",
+ "sed -i 's/8010/8011/' /tmp/master.cfg",
+ "buildbot start /tmp",
+ "nc -z bbmaster 8011",
+ )
+ bbworker.wait_until_succeeds("curl --fail -s --head http://bbmaster:8011")
+ bbmaster.wait_until_succeeds("buildbot stop /tmp")
+ bbworker.fail("nc -z bbmaster 8011")
'';
meta.maintainers = with pkgs.stdenv.lib.maintainers; [ nand0p ];
-}
+} {}
diff --git a/nixpkgs/nixos/tests/buildkite-agent.nix b/nixpkgs/nixos/tests/buildkite-agents.nix
index 3c824c9aedf..a6f33e0143c 100644
--- a/nixpkgs/nixos/tests/buildkite-agent.nix
+++ b/nixpkgs/nixos/tests/buildkite-agents.nix
@@ -6,18 +6,13 @@ import ./make-test-python.nix ({ pkgs, ... }:
maintainers = [ flokli ];
};
- nodes = {
- node1 = { pkgs, ... }: {
- services.buildkite-agent = {
- enable = true;
+ machine = { pkgs, ... }: {
+ services.buildkite-agents = {
+ one = {
privateSshKeyPath = (import ./ssh-keys.nix pkgs).snakeOilPrivateKey;
tokenPath = (pkgs.writeText "my-token" "5678");
};
- };
- # don't configure ssh key, run as a separate user
- node2 = { pkgs, ...}: {
- services.buildkite-agent = {
- enable = true;
+ two = {
tokenPath = (pkgs.writeText "my-token" "1234");
};
};
@@ -28,9 +23,9 @@ import ./make-test-python.nix ({ pkgs, ... }:
# we can't wait on the unit to start up, as we obviously can't connect to buildkite,
# but we can look whether files are set up correctly
- node1.wait_for_file("/var/lib/buildkite-agent/buildkite-agent.cfg")
- node1.wait_for_file("/var/lib/buildkite-agent/.ssh/id_rsa")
+ machine.wait_for_file("/var/lib/buildkite-agent-one/buildkite-agent.cfg")
+ machine.wait_for_file("/var/lib/buildkite-agent-one/.ssh/id_rsa")
- node2.wait_for_file("/var/lib/buildkite-agent/buildkite-agent.cfg")
+ machine.wait_for_file("/var/lib/buildkite-agent-two/buildkite-agent.cfg")
'';
})
diff --git a/nixpkgs/nixos/tests/cage.nix b/nixpkgs/nixos/tests/cage.nix
new file mode 100644
index 00000000000..a6f73e00c06
--- /dev/null
+++ b/nixpkgs/nixos/tests/cage.nix
@@ -0,0 +1,43 @@
+import ./make-test-python.nix ({ pkgs, ...} :
+
+{
+ name = "cage";
+ meta = with pkgs.stdenv.lib.maintainers; {
+ maintainers = [ matthewbauer flokli ];
+ };
+
+ machine = { ... }:
+
+ {
+ imports = [ ./common/user-account.nix ];
+ services.cage = {
+ enable = true;
+ user = "alice";
+ program = "${pkgs.xterm}/bin/xterm -cm -pc"; # disable color and bold to make OCR easier
+ };
+
+ # this needs a fairly recent kernel, otherwise:
+ # [backend/drm/util.c:215] Unable to add DRM framebuffer: No such file or directory
+ # [backend/drm/legacy.c:15] Virtual-1: Failed to set CRTC: No such file or directory
+ # [backend/drm/util.c:215] Unable to add DRM framebuffer: No such file or directory
+ # [backend/drm/legacy.c:15] Virtual-1: Failed to set CRTC: No such file or directory
+ # [backend/drm/drm.c:618] Failed to initialize renderer on connector 'Virtual-1': initial page-flip failed
+ # [backend/drm/drm.c:701] Failed to initialize renderer for plane
+ boot.kernelPackages = pkgs.linuxPackages_latest;
+
+ virtualisation.memorySize = 1024;
+ };
+
+ enableOCR = true;
+
+ testScript = { nodes, ... }: let
+ user = nodes.machine.config.users.users.alice;
+ in ''
+ with subtest("Wait for cage to boot up"):
+ start_all()
+ machine.wait_for_file("/run/user/${toString user.uid}/wayland-0.lock")
+ machine.wait_until_succeeds("pgrep xterm")
+ machine.wait_for_text("alice@machine")
+ machine.screenshot("screen")
+ '';
+})
diff --git a/nixpkgs/nixos/tests/chromium.nix b/nixpkgs/nixos/tests/chromium.nix
index 3844255bd8a..fc5d3a5c52f 100644
--- a/nixpkgs/nixos/tests/chromium.nix
+++ b/nixpkgs/nixos/tests/chromium.nix
@@ -8,7 +8,7 @@
}
}:
-with import ../lib/testing.nix { inherit system pkgs; };
+with import ../lib/testing-python.nix { inherit system pkgs; };
with pkgs.lib;
mapAttrs (channel: chromiumPkg: makeTest rec {
@@ -21,9 +21,11 @@ mapAttrs (channel: chromiumPkg: makeTest rec {
enableOCR = true;
+ user = "alice";
+
machine.imports = [ ./common/user-account.nix ./common/x11.nix ];
machine.virtualisation.memorySize = 2047;
- machine.test-support.displayManager.auto.user = "alice";
+ machine.test-support.displayManager.auto.user = user;
machine.environment.systemPackages = [ chromiumPkg ];
startupHTML = pkgs.writeText "chromium-startup.html" ''
@@ -47,155 +49,218 @@ mapAttrs (channel: chromiumPkg: makeTest rec {
xdoScript = pkgs.writeText "${name}.xdo" text;
in "${pkgs.xdotool}/bin/xdotool '${xdoScript}'";
in ''
+ import shlex
+ from contextlib import contextmanager, _GeneratorContextManager
+
+
# Run as user alice
- sub ru ($) {
- my $esc = $_[0] =~ s/'/'\\${"'"}'/gr;
- return "su - alice -c '$esc'";
- }
-
- sub createNewWin {
- $machine->nest("creating a new Chromium window", sub {
- $machine->execute(ru "${xdo "new-window" ''
- search --onlyvisible --name "startup done"
- windowfocus --sync
- windowactivate --sync
- ''}");
- $machine->execute(ru "${xdo "new-window" ''
- key Ctrl+n
- ''}");
- });
- }
-
- sub closeWin {
- Machine::retry sub {
- $machine->execute(ru "${xdo "close-window" ''
- search --onlyvisible --name "new tab"
- windowfocus --sync
- windowactivate --sync
- ''}");
- $machine->execute(ru "${xdo "close-window" ''
- key Ctrl+w
- ''}");
- for (1..20) {
- my ($status, $out) = $machine->execute(ru "${xdo "wait-for-close" ''
- search --onlyvisible --name "new tab"
- ''}");
- return 1 if $status != 0;
- $machine->sleep(1);
- }
- }
- }
-
- sub waitForNewWin {
- my $ret = 0;
- $machine->nest("waiting for new Chromium window to appear", sub {
- for (1..20) {
- my ($status, $out) = $machine->execute(ru "${xdo "wait-for-window" ''
- search --onlyvisible --name "new tab"
- windowfocus --sync
- windowactivate --sync
- ''}");
- if ($status == 0) {
- $ret = 1;
-
- # XXX: Somehow Chromium is not accepting keystrokes for a few
- # seconds after a new window has appeared, so let's wait a while.
- $machine->sleep(10);
-
- last;
- }
- $machine->sleep(1);
- }
- });
- return $ret;
- }
-
- sub createAndWaitForNewWin {
- for (1..3) {
- createNewWin;
- return 1 if waitForNewWin;
- }
- die "new window didn't appear within 60 seconds";
- }
-
- sub testNewWin {
- my ($desc, $code) = @_;
- createAndWaitForNewWin;
- subtest($desc, $code);
- closeWin;
- }
-
- $machine->waitForX;
-
- my $url = "file://${startupHTML}";
- $machine->execute(ru "ulimit -c unlimited; chromium \"$url\" & disown");
- $machine->waitForText(qr/startup done/);
- $machine->waitUntilSucceeds(ru "${xdo "check-startup" ''
- search --sync --onlyvisible --name "startup done"
- # close first start help popup
- key -delay 1000 Escape
- windowfocus --sync
- windowactivate --sync
- ''}");
-
- createAndWaitForNewWin;
- $machine->screenshot("empty_windows");
- closeWin;
-
- $machine->screenshot("startup_done");
-
- testNewWin "check sandbox", sub {
- $machine->succeed(ru "${xdo "type-url" ''
- search --sync --onlyvisible --name "new tab"
- windowfocus --sync
- type --delay 1000 "chrome://sandbox"
- ''}");
-
- $machine->succeed(ru "${xdo "submit-url" ''
- search --sync --onlyvisible --name "new tab"
- windowfocus --sync
- key --delay 1000 Return
- ''}");
-
- $machine->screenshot("sandbox_info");
-
- $machine->succeed(ru "${xdo "find-window" ''
- search --sync --onlyvisible --name "sandbox status"
- windowfocus --sync
- ''}");
- $machine->succeed(ru "${xdo "copy-sandbox-info" ''
- key --delay 1000 Ctrl+a Ctrl+c
- ''}");
-
- my $clipboard = $machine->succeed(ru "${pkgs.xclip}/bin/xclip -o");
- die "sandbox not working properly: $clipboard"
- unless $clipboard =~ /layer 1 sandbox.*namespace/mi
- && $clipboard =~ /pid namespaces.*yes/mi
- && $clipboard =~ /network namespaces.*yes/mi
- && $clipboard =~ /seccomp.*sandbox.*yes/mi
- && $clipboard =~ /you are adequately sandboxed/mi;
-
- $machine->sleep(1);
- $machine->succeed(ru "${xdo "find-window-after-copy" ''
- search --onlyvisible --name "sandbox status"
- ''}");
-
- my $clipboard = $machine->succeed(ru "echo void | ${pkgs.xclip}/bin/xclip -i");
- $machine->succeed(ru "${xdo "copy-sandbox-info" ''
- key --delay 1000 Ctrl+a Ctrl+c
- ''}");
-
- my $clipboard = $machine->succeed(ru "${pkgs.xclip}/bin/xclip -o");
- die "copying twice in a row does not work properly: $clipboard"
- unless $clipboard =~ /layer 1 sandbox.*namespace/mi
- && $clipboard =~ /pid namespaces.*yes/mi
- && $clipboard =~ /network namespaces.*yes/mi
- && $clipboard =~ /seccomp.*sandbox.*yes/mi
- && $clipboard =~ /you are adequately sandboxed/mi;
-
- $machine->screenshot("afer_copy_from_chromium");
- };
-
- $machine->shutdown;
+ def ru(cmd):
+ return "su - ${user} -c " + shlex.quote(cmd)
+
+
+ def create_new_win():
+ with machine.nested("Creating a new Chromium window"):
+ machine.execute(
+ ru(
+ "${xdo "new-window" ''
+ search --onlyvisible --name "startup done"
+ windowfocus --sync
+ windowactivate --sync
+ ''}"
+ )
+ )
+ machine.execute(
+ ru(
+ "${xdo "new-window" ''
+ key Ctrl+n
+ ''}"
+ )
+ )
+
+
+ def close_win():
+ def try_close(_):
+ machine.execute(
+ ru(
+ "${xdo "close-window" ''
+ search --onlyvisible --name "new tab"
+ windowfocus --sync
+ windowactivate --sync
+ ''}"
+ )
+ )
+ machine.execute(
+ ru(
+ "${xdo "close-window" ''
+ key Ctrl+w
+ ''}"
+ )
+ )
+ for _ in range(1, 20):
+ status, out = machine.execute(
+ ru(
+ "${xdo "wait-for-close" ''
+ search --onlyvisible --name "new tab"
+ ''}"
+ )
+ )
+ if status != 0:
+ return True
+ machine.sleep(1)
+ return False
+
+ retry(try_close)
+
+
+ def wait_for_new_win():
+ ret = False
+ with machine.nested("Waiting for new Chromium window to appear"):
+ for _ in range(1, 20):
+ status, out = machine.execute(
+ ru(
+ "${xdo "wait-for-window" ''
+ search --onlyvisible --name "new tab"
+ windowfocus --sync
+ windowactivate --sync
+ ''}"
+ )
+ )
+ if status == 0:
+ ret = True
+ machine.sleep(10)
+ break
+ machine.sleep(1)
+ return ret
+
+
+ def create_and_wait_for_new_win():
+ for _ in range(1, 3):
+ create_new_win()
+ if wait_for_new_win():
+ return True
+ assert False, "new window did not appear within 60 seconds"
+
+
+ @contextmanager
+ def test_new_win(description):
+ create_and_wait_for_new_win()
+ with machine.nested(description):
+ yield
+ close_win()
+
+
+ machine.wait_for_x()
+
+ url = "file://${startupHTML}"
+ machine.succeed(ru(f'ulimit -c unlimited; chromium "{url}" & disown'))
+ machine.wait_for_text("startup done")
+ machine.wait_until_succeeds(
+ ru(
+ "${xdo "check-startup" ''
+ search --sync --onlyvisible --name "startup done"
+ # close first start help popup
+ key -delay 1000 Escape
+ windowfocus --sync
+ windowactivate --sync
+ ''}"
+ )
+ )
+
+ create_and_wait_for_new_win()
+ machine.screenshot("empty_windows")
+ close_win()
+
+ machine.screenshot("startup_done")
+
+ with test_new_win("check sandbox"):
+ machine.succeed(
+ ru(
+ "${xdo "type-url" ''
+ search --sync --onlyvisible --name "new tab"
+ windowfocus --sync
+ type --delay 1000 "chrome://sandbox"
+ ''}"
+ )
+ )
+
+ machine.succeed(
+ ru(
+ "${xdo "submit-url" ''
+ search --sync --onlyvisible --name "new tab"
+ windowfocus --sync
+ key --delay 1000 Return
+ ''}"
+ )
+ )
+
+ machine.screenshot("sandbox_info")
+
+ machine.succeed(
+ ru(
+ "${xdo "find-window" ''
+ search --sync --onlyvisible --name "sandbox status"
+ windowfocus --sync
+ ''}"
+ )
+ )
+ machine.succeed(
+ ru(
+ "${xdo "copy-sandbox-info" ''
+ key --delay 1000 Ctrl+a Ctrl+c
+ ''}"
+ )
+ )
+
+ clipboard = machine.succeed(
+ ru("${pkgs.xclip}/bin/xclip -o")
+ )
+
+ filters = [
+ "layer 1 sandbox.*namespace",
+ "pid namespaces.*yes",
+ "network namespaces.*yes",
+ "seccomp.*sandbox.*yes",
+ "you are adequately sandboxed",
+ ]
+ if not all(
+ re.search(filter, clipboard, flags=re.DOTALL | re.IGNORECASE)
+ for filter in filters
+ ):
+ assert False, f"sandbox not working properly: {clipboard}"
+
+ machine.sleep(1)
+ machine.succeed(
+ ru(
+ "${xdo "find-window-after-copy" ''
+ search --onlyvisible --name "sandbox status"
+ ''}"
+ )
+ )
+
+ clipboard = machine.succeed(
+ ru(
+ "echo void | ${pkgs.xclip}/bin/xclip -i"
+ )
+ )
+ machine.succeed(
+ ru(
+ "${xdo "copy-sandbox-info" ''
+ key --delay 1000 Ctrl+a Ctrl+c
+ ''}"
+ )
+ )
+
+ clipboard = machine.succeed(
+ ru("${pkgs.xclip}/bin/xclip -o")
+ )
+ if not all(
+ re.search(filter, clipboard, flags=re.DOTALL | re.IGNORECASE)
+ for filter in filters
+ ):
+ assert False, f"copying twice in a row does not work properly: {clipboard}"
+
+ machine.screenshot("after_copy_from_chromium")
+
+ machine.shutdown()
'';
}) channelMap
diff --git a/nixpkgs/nixos/tests/common/letsencrypt/common.nix b/nixpkgs/nixos/tests/common/letsencrypt/common.nix
index c530de817bf..bd559c8dacc 100644
--- a/nixpkgs/nixos/tests/common/letsencrypt/common.nix
+++ b/nixpkgs/nixos/tests/common/letsencrypt/common.nix
@@ -5,5 +5,8 @@ in {
nodes.letsencrypt.config.networking.primaryIPAddress
];
+ security.acme.acceptTerms = true;
+ security.acme.email = "webmaster@example.com";
+
security.pki.certificateFiles = [ letsencrypt-ca ];
}
diff --git a/nixpkgs/nixos/tests/containers-imperative.nix b/nixpkgs/nixos/tests/containers-imperative.nix
index 61df74042cb..c4f2002918f 100644
--- a/nixpkgs/nixos/tests/containers-imperative.nix
+++ b/nixpkgs/nixos/tests/containers-imperative.nix
@@ -46,6 +46,15 @@ import ./make-test-python.nix ({ pkgs, ...} : {
};
}
'';
+ brokenCfg = pkgs.writeText "broken.nix" ''
+ {
+ assertions = [
+ { assertion = false;
+ message = "I never evaluate";
+ }
+ ];
+ }
+ '';
in ''
with subtest("Make sure we have a NixOS tree (required by ‘nixos-container create’)"):
machine.succeed("PAGER=cat nix-env -qa -A nixos.hello >&2")
@@ -130,5 +139,11 @@ import ./make-test-python.nix ({ pkgs, ...} : {
with subtest("Ensure that the container path is gone"):
print(machine.succeed("ls -lsa /var/lib/containers"))
machine.succeed(f"test ! -e /var/lib/containers/{id1}")
+
+ with subtest("Ensure that a failed container creation doesn'leave any state"):
+ machine.fail(
+ "nixos-container create b0rk --config-file ${brokenCfg}"
+ )
+ machine.succeed(f"test ! -e /var/lib/containers/b0rk")
'';
})
diff --git a/nixpkgs/nixos/tests/corerad.nix b/nixpkgs/nixos/tests/corerad.nix
index 950c9abc899..741fa448f68 100644
--- a/nixpkgs/nixos/tests/corerad.nix
+++ b/nixpkgs/nixos/tests/corerad.nix
@@ -17,7 +17,7 @@ import ./make-test-python.nix (
configFile = pkgs.writeText "corerad.toml" ''
[[interfaces]]
name = "eth1"
- send_advertisements = true
+ advertise = true
[[interfaces.prefix]]
prefix = "::/64"
'';
diff --git a/nixpkgs/nixos/tests/dnscrypt-proxy.nix b/nixpkgs/nixos/tests/dnscrypt-proxy2.nix
index 98153d5c904..b614d912a9f 100644
--- a/nixpkgs/nixos/tests/dnscrypt-proxy.nix
+++ b/nixpkgs/nixos/tests/dnscrypt-proxy2.nix
@@ -1,5 +1,5 @@
import ./make-test-python.nix ({ pkgs, ... }: {
- name = "dnscrypt-proxy";
+ name = "dnscrypt-proxy2";
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ joachifm ];
};
@@ -13,9 +13,16 @@ import ./make-test-python.nix ({ pkgs, ... }: {
{
security.apparmor.enable = true;
- services.dnscrypt-proxy.enable = true;
- services.dnscrypt-proxy.localPort = localProxyPort;
- services.dnscrypt-proxy.extraArgs = [ "-X libdcplugin_example.so" ];
+ services.dnscrypt-proxy2.enable = true;
+ services.dnscrypt-proxy2.settings = {
+ listen_addresses = [ "127.0.0.1:${toString localProxyPort}" ];
+ sources.public-resolvers = {
+ urls = [ "https://download.dnscrypt.info/resolvers-list/v2/public-resolvers.md" ];
+ cache_file = "public-resolvers.md";
+ minisign_key = "RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3";
+ refresh_delay = 72;
+ };
+ };
services.dnsmasq.enable = true;
services.dnsmasq.servers = [ "127.0.0.1#${toString localProxyPort}" ];
@@ -24,12 +31,6 @@ import ./make-test-python.nix ({ pkgs, ... }: {
testScript = ''
client.wait_for_unit("dnsmasq")
-
- # The daemon is socket activated; sending a single ping should activate it.
- client.fail("systemctl is-active dnscrypt-proxy")
- client.execute(
- "${pkgs.iputils}/bin/ping -c1 example.com"
- )
- client.wait_until_succeeds("systemctl is-active dnscrypt-proxy")
+ client.wait_for_unit("dnscrypt-proxy2")
'';
})
diff --git a/nixpkgs/nixos/tests/docker-containers.nix b/nixpkgs/nixos/tests/docker-containers.nix
index 9be9bfa80ce..0e318a52d9f 100644
--- a/nixpkgs/nixos/tests/docker-containers.nix
+++ b/nixpkgs/nixos/tests/docker-containers.nix
@@ -1,30 +1,27 @@
# Test Docker containers as systemd units
-import ./make-test.nix ({ pkgs, lib, ... }:
-
-{
+import ./make-test-python.nix ({ pkgs, lib, ... }: {
name = "docker-containers";
meta = {
maintainers = with lib.maintainers; [ benley mkaito ];
};
nodes = {
- docker = { pkgs, ... }:
- {
- virtualisation.docker.enable = true;
+ docker = { pkgs, ... }: {
+ virtualisation.docker.enable = true;
- docker-containers.nginx = {
- image = "nginx-container";
- imageFile = pkgs.dockerTools.examples.nginx;
- ports = ["8181:80"];
- };
+ docker-containers.nginx = {
+ image = "nginx-container";
+ imageFile = pkgs.dockerTools.examples.nginx;
+ ports = ["8181:80"];
};
+ };
};
testScript = ''
- startAll;
- $docker->waitForUnit("docker-nginx.service");
- $docker->waitForOpenPort(8181);
- $docker->waitUntilSucceeds("curl http://localhost:8181|grep Hello");
+ start_all()
+ docker.wait_for_unit("docker-nginx.service")
+ docker.wait_for_open_port(8181)
+ docker.wait_until_succeeds("curl http://localhost:8181 | grep Hello")
'';
})
diff --git a/nixpkgs/nixos/tests/docker-tools.nix b/nixpkgs/nixos/tests/docker-tools.nix
index 07fac533680..51b472fcf9c 100644
--- a/nixpkgs/nixos/tests/docker-tools.nix
+++ b/nixpkgs/nixos/tests/docker-tools.nix
@@ -1,87 +1,158 @@
# this test creates a simple GNU image with docker tools and sees if it executes
-import ./make-test.nix ({ pkgs, ... }: {
+import ./make-test-python.nix ({ pkgs, ... }: {
name = "docker-tools";
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ lnl7 ];
};
nodes = {
- docker =
- { ... }: {
- virtualisation = {
- diskSize = 2048;
- docker.enable = true;
- };
+ docker = { ... }: {
+ virtualisation = {
+ diskSize = 2048;
+ docker.enable = true;
};
+ };
};
- testScript =
- ''
- $docker->waitForUnit("sockets.target");
-
- # Ensure Docker images use a stable date by default
- $docker->succeed("docker load --input='${pkgs.dockerTools.examples.bash}'");
- $docker->succeed("[ '1970-01-01T00:00:01Z' = \"\$(docker inspect ${pkgs.dockerTools.examples.bash.imageName} | ${pkgs.jq}/bin/jq -r .[].Created)\" ]");
-
- $docker->succeed("docker run --rm ${pkgs.dockerTools.examples.bash.imageName} bash --version");
- $docker->succeed("docker rmi ${pkgs.dockerTools.examples.bash.imageName}");
-
- # Check if the nix store is correctly initialized by listing dependencies of the installed Nix binary
- $docker->succeed("docker load --input='${pkgs.dockerTools.examples.nix}'");
- $docker->succeed("docker run --rm ${pkgs.dockerTools.examples.nix.imageName} nix-store -qR ${pkgs.nix}");
- $docker->succeed("docker rmi ${pkgs.dockerTools.examples.nix.imageName}");
-
- # To test the pullImage tool
- $docker->succeed("docker load --input='${pkgs.dockerTools.examples.nixFromDockerHub}'");
- $docker->succeed("docker run --rm nix:2.2.1 nix-store --version");
- $docker->succeed("docker rmi nix:2.2.1");
-
- # To test runAsRoot and entry point
- $docker->succeed("docker load --input='${pkgs.dockerTools.examples.nginx}'");
- $docker->succeed("docker run --name nginx -d -p 8000:80 ${pkgs.dockerTools.examples.nginx.imageName}");
- $docker->waitUntilSucceeds('curl http://localhost:8000/');
- $docker->succeed("docker rm --force nginx");
- $docker->succeed("docker rmi '${pkgs.dockerTools.examples.nginx.imageName}'");
-
- # An pulled image can be used as base image
- $docker->succeed("docker load --input='${pkgs.dockerTools.examples.onTopOfPulledImage}'");
- $docker->succeed("docker run --rm ontopofpulledimage hello");
- $docker->succeed("docker rmi ontopofpulledimage");
-
- # Regression test for issue #34779
- $docker->succeed("docker load --input='${pkgs.dockerTools.examples.runAsRootExtraCommands}'");
- $docker->succeed("docker run --rm runasrootextracommands cat extraCommands");
- $docker->succeed("docker run --rm runasrootextracommands cat runAsRoot");
- $docker->succeed("docker rmi '${pkgs.dockerTools.examples.runAsRootExtraCommands.imageName}'");
-
- # Ensure Docker images can use an unstable date
- $docker->succeed("docker load --input='${pkgs.dockerTools.examples.bash}'");
- $docker->succeed("[ '1970-01-01T00:00:01Z' != \"\$(docker inspect ${pkgs.dockerTools.examples.unstableDate.imageName} | ${pkgs.jq}/bin/jq -r .[].Created)\" ]");
-
- # Ensure Layered Docker images work
- $docker->succeed("docker load --input='${pkgs.dockerTools.examples.layered-image}'");
- $docker->succeed("docker run --rm ${pkgs.dockerTools.examples.layered-image.imageName}");
- $docker->succeed("docker run --rm ${pkgs.dockerTools.examples.layered-image.imageName} cat extraCommands");
-
- # Ensure building an image on top of a layered Docker images work
- $docker->succeed("docker load --input='${pkgs.dockerTools.examples.layered-on-top}'");
- $docker->succeed("docker run --rm ${pkgs.dockerTools.examples.layered-on-top.imageName}");
-
- # Ensure layers are shared between images
- $docker->succeed("docker load --input='${pkgs.dockerTools.examples.another-layered-image}'");
- $docker->succeed("docker inspect ${pkgs.dockerTools.examples.layered-image.imageName} | ${pkgs.jq}/bin/jq -r '.[] | .RootFS.Layers | .[]' | sort > layers1.sha256");
- $docker->succeed("docker inspect ${pkgs.dockerTools.examples.another-layered-image.imageName} | ${pkgs.jq}/bin/jq -r '.[] | .RootFS.Layers | .[]' | sort > layers2.sha256");
- $docker->succeed('[ $(comm -1 -2 layers1.sha256 layers2.sha256 | wc -l) -ne 0 ]');
-
- # Ensure order of layers is correct
- $docker->succeed("docker load --input='${pkgs.dockerTools.examples.layersOrder}'");
- $docker->succeed("docker run --rm ${pkgs.dockerTools.examples.layersOrder.imageName} cat /tmp/layer1 | grep -q layer1");
- # This is to be sure the order of layers of the parent image is preserved
- $docker->succeed("docker run --rm ${pkgs.dockerTools.examples.layersOrder.imageName} cat /tmp/layer2 | grep -q layer2");
- $docker->succeed("docker run --rm ${pkgs.dockerTools.examples.layersOrder.imageName} cat /tmp/layer3 | grep -q layer3");
-
- # Ensure image with only 2 layers can be loaded
- $docker->succeed("docker load --input='${pkgs.dockerTools.examples.two-layered-image}'");
- '';
+ testScript = with pkgs.dockerTools; ''
+ unix_time_second1 = "1970-01-01T00:00:01Z"
+
+ docker.wait_for_unit("sockets.target")
+
+ with subtest("Ensure Docker images use a stable date by default"):
+ docker.succeed(
+ "docker load --input='${examples.bash}'"
+ )
+ assert unix_time_second1 in docker.succeed(
+ "docker inspect ${examples.bash.imageName} "
+ + "| ${pkgs.jq}/bin/jq -r .[].Created",
+ )
+
+ docker.succeed("docker run --rm ${examples.bash.imageName} bash --version")
+ docker.succeed("docker rmi ${examples.bash.imageName}")
+
+ with subtest(
+ "Check if the nix store is correctly initialized by listing "
+ "dependencies of the installed Nix binary"
+ ):
+ docker.succeed(
+ "docker load --input='${examples.nix}'",
+ "docker run --rm ${examples.nix.imageName} nix-store -qR ${pkgs.nix}",
+ "docker rmi ${examples.nix.imageName}",
+ )
+
+ with subtest("The pullImage tool works"):
+ docker.succeed(
+ "docker load --input='${examples.nixFromDockerHub}'",
+ "docker run --rm nix:2.2.1 nix-store --version",
+ "docker rmi nix:2.2.1",
+ )
+
+ with subtest("runAsRoot and entry point work"):
+ docker.succeed(
+ "docker load --input='${examples.nginx}'",
+ "docker run --name nginx -d -p 8000:80 ${examples.nginx.imageName}",
+ )
+ docker.wait_until_succeeds("curl http://localhost:8000/")
+ docker.succeed(
+ "docker rm --force nginx", "docker rmi '${examples.nginx.imageName}'",
+ )
+
+ with subtest("A pulled image can be used as base image"):
+ docker.succeed(
+ "docker load --input='${examples.onTopOfPulledImage}'",
+ "docker run --rm ontopofpulledimage hello",
+ "docker rmi ontopofpulledimage",
+ )
+
+ with subtest("Regression test for issue #34779"):
+ docker.succeed(
+ "docker load --input='${examples.runAsRootExtraCommands}'",
+ "docker run --rm runasrootextracommands cat extraCommands",
+ "docker run --rm runasrootextracommands cat runAsRoot",
+ "docker rmi '${examples.runAsRootExtraCommands.imageName}'",
+ )
+
+ with subtest("Ensure Docker images can use an unstable date"):
+ docker.succeed(
+ "docker load --input='${examples.bash}'"
+ )
+ 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 work"):
+ docker.succeed(
+ "docker load --input='${examples.layered-image}'",
+ "docker run --rm ${examples.layered-image.imageName}",
+ "docker run --rm ${examples.layered-image.imageName} cat extraCommands",
+ )
+
+ with subtest("Ensure building an image on top of a layered Docker images work"):
+ docker.succeed(
+ "docker load --input='${examples.layered-on-top}'",
+ "docker run --rm ${examples.layered-on-top.imageName}",
+ )
+
+
+ def set_of_layers(image_name):
+ return set(
+ docker.succeed(
+ f"docker inspect {image_name} "
+ + "| ${pkgs.jq}/bin/jq -r '.[] | .RootFS.Layers | .[]'"
+ ).split()
+ )
+
+
+ with subtest("Ensure layers are shared between images"):
+ docker.succeed(
+ "docker load --input='${examples.another-layered-image}'"
+ )
+ layers1 = set_of_layers("${examples.layered-image.imageName}")
+ layers2 = set_of_layers("${examples.another-layered-image.imageName}")
+ assert bool(layers1 & layers2)
+
+ with subtest("Ensure order of layers is correct"):
+ docker.succeed(
+ "docker load --input='${examples.layersOrder}'"
+ )
+
+ for index in 1, 2, 3:
+ assert f"layer{index}" in docker.succeed(
+ f"docker run --rm ${examples.layersOrder.imageName} cat /tmp/layer{index}"
+ )
+
+ with subtest("Ensure image with only 2 layers can be loaded"):
+ docker.succeed(
+ "docker load --input='${examples.two-layered-image}'"
+ )
+
+ with subtest(
+ "Ensure the bulk layer doesn't miss store paths (regression test for #78744)"
+ ):
+ docker.succeed(
+ "docker load --input='${pkgs.dockerTools.examples.bulk-layer}'",
+ # Ensure the two output paths (ls and hello) are in the layer
+ "docker run bulk-layer ls /bin/hello",
+ )
+
+ with subtest("Ensure correct behavior when no store is needed"):
+ # This check tests two requirements simultaneously
+ # 1. buildLayeredImage can build images that don't need a store.
+ # 2. Layers of symlinks are eliminated by the customization layer.
+ #
+ docker.succeed(
+ "docker load --input='${pkgs.dockerTools.examples.no-store-paths}'"
+ )
+
+ # Busybox will not recognize argv[0] and print an error message with argv[0],
+ # but it confirms that the custom-true symlink is present.
+ docker.succeed("docker run --rm no-store-paths custom-true |& grep custom-true")
+
+ # 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")
+ '';
})
diff --git a/nixpkgs/nixos/tests/firefox.nix b/nixpkgs/nixos/tests/firefox.nix
index 56ddabbae77..7071baceba7 100644
--- a/nixpkgs/nixos/tests/firefox.nix
+++ b/nixpkgs/nixos/tests/firefox.nix
@@ -1,4 +1,4 @@
-import ./make-test-python.nix ({ pkgs, ... }: {
+import ./make-test-python.nix ({ pkgs, esr ? false, ... }: {
name = "firefox";
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ eelco shlevy ];
@@ -8,7 +8,9 @@ import ./make-test-python.nix ({ pkgs, ... }: {
{ pkgs, ... }:
{ imports = [ ./common/x11.nix ];
- environment.systemPackages = [ pkgs.firefox pkgs.xdotool ];
+ environment.systemPackages =
+ (if esr then [ pkgs.firefox-esr ] else [ pkgs.firefox ])
+ ++ [ pkgs.xdotool ];
};
testScript = ''
diff --git a/nixpkgs/nixos/tests/gitdaemon.nix b/nixpkgs/nixos/tests/gitdaemon.nix
new file mode 100644
index 00000000000..b610caf06fb
--- /dev/null
+++ b/nixpkgs/nixos/tests/gitdaemon.nix
@@ -0,0 +1,64 @@
+import ./make-test-python.nix ({ pkgs, ... }:
+
+let
+ hashes = pkgs.writeText "hashes" ''
+ b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c /project/bar
+ '';
+in {
+ name = "gitdaemon";
+
+ meta = with pkgs.stdenv.lib.maintainers; {
+ maintainers = [ tilpner ];
+ };
+
+ nodes = {
+ server =
+ { config, ... }: {
+ networking.firewall.allowedTCPPorts = [ config.services.gitDaemon.port ];
+
+ environment.systemPackages = [ pkgs.git ];
+
+ services.gitDaemon = {
+ enable = true;
+ basePath = "/git";
+ };
+ };
+
+ client =
+ { pkgs, ... }: {
+ environment.systemPackages = [ pkgs.git ];
+ };
+ };
+
+ testScript = ''
+ start_all()
+
+ with subtest("create project.git"):
+ server.succeed(
+ "mkdir /git",
+ "git init --bare /git/project.git",
+ "touch /git/project.git/git-daemon-export-ok",
+ )
+
+ with subtest("add file to project.git"):
+ server.succeed(
+ "git clone /git/project.git /project",
+ "echo foo > /project/bar",
+ "git config --global user.email 'you@example.com'",
+ "git config --global user.name 'Your Name'",
+ "git -C /project add bar",
+ "git -C /project commit -m 'quux'",
+ "git -C /project push",
+ "rm -r /project",
+ )
+
+ with subtest("git daemon starts"):
+ server.wait_for_unit("git-daemon.service")
+
+ with subtest("client can clone project.git"):
+ client.succeed(
+ "git clone git://server/project.git /project",
+ "sha256sum -c ${hashes}",
+ )
+ '';
+})
diff --git a/nixpkgs/nixos/tests/glusterfs.nix b/nixpkgs/nixos/tests/glusterfs.nix
index 8f9cb8973d5..cb07bc09511 100644
--- a/nixpkgs/nixos/tests/glusterfs.nix
+++ b/nixpkgs/nixos/tests/glusterfs.nix
@@ -4,10 +4,11 @@ let
client = { pkgs, ... } : {
environment.systemPackages = [ pkgs.glusterfs ];
fileSystems = pkgs.lib.mkVMOverride
- [ { mountPoint = "/gluster";
- fsType = "glusterfs";
- device = "server1:/gv0";
- } ];
+ { "/gluster" =
+ { device = "server1:/gv0";
+ fsType = "glusterfs";
+ };
+ };
};
server = { pkgs, ... } : {
@@ -22,11 +23,11 @@ let
virtualisation.emptyDiskImages = [ 1024 ];
fileSystems = pkgs.lib.mkVMOverride
- [ { mountPoint = "/data";
- device = "/dev/disk/by-label/data";
- fsType = "ext4";
- }
- ];
+ { "/data" =
+ { device = "/dev/disk/by-label/data";
+ fsType = "ext4";
+ };
+ };
};
in {
name = "glusterfs";
diff --git a/nixpkgs/nixos/tests/grocy.nix b/nixpkgs/nixos/tests/grocy.nix
new file mode 100644
index 00000000000..7fa479ed2c4
--- /dev/null
+++ b/nixpkgs/nixos/tests/grocy.nix
@@ -0,0 +1,47 @@
+import ./make-test-python.nix ({ pkgs, ... }: {
+ name = "grocy";
+ meta = with pkgs.stdenv.lib.maintainers; {
+ maintainers = [ ma27 ];
+ };
+
+ machine = { pkgs, ... }: {
+ services.grocy = {
+ enable = true;
+ hostName = "localhost";
+ nginx.enableSSL = false;
+ };
+ environment.systemPackages = [ pkgs.jq ];
+ };
+
+ testScript = ''
+ machine.start()
+ machine.wait_for_open_port(80)
+ machine.wait_for_unit("multi-user.target")
+
+ machine.succeed("curl -sSf http://localhost")
+
+ machine.succeed(
+ "curl -c cookies -sSf -X POST http://localhost/login -d 'username=admin&password=admin'"
+ )
+
+ cookie = machine.succeed(
+ "grep -v '^#' cookies | awk '{ print $7 }' | sed -e '/^$/d' | perl -pe 'chomp'"
+ )
+
+ machine.succeed(
+ f"curl -sSf -X POST http://localhost/api/objects/tasks -b 'grocy_session={cookie}' "
+ + '-d \'{"assigned_to_user_id":1,"name":"Test Task","due_date":"1970-01-01"}\'''
+ + " --header 'Content-Type: application/json'"
+ )
+
+ task_name = machine.succeed(
+ f"curl -sSf http://localhost/api/tasks -b 'grocy_session={cookie}' --header 'Accept: application/json' | jq '.[].name' | xargs echo | perl -pe 'chomp'"
+ )
+
+ assert task_name == "Test Task"
+
+ machine.succeed("curl -sSfI http://localhost/api/tasks 2>&1 | grep '401 Unauthorized'")
+
+ machine.shutdown()
+ '';
+})
diff --git a/nixpkgs/nixos/tests/ihatemoney.nix b/nixpkgs/nixos/tests/ihatemoney.nix
index 14db17fe5e6..7df0ea0b691 100644
--- a/nixpkgs/nixos/tests/ihatemoney.nix
+++ b/nixpkgs/nixos/tests/ihatemoney.nix
@@ -1,13 +1,5 @@
-{ system ? builtins.currentSystem
-, config ? {}
-, pkgs ? import ../.. { inherit system config; }
-}:
-
let
- inherit (import ../lib/testing.nix { inherit system pkgs; }) makeTest;
-in
-map (
- backend: makeTest {
+ f = backend: import ./make-test-python.nix ({ pkgs, ... }: {
name = "ihatemoney-${backend}";
machine = { lib, ... }: {
services.ihatemoney = {
@@ -30,23 +22,34 @@ map (
};
};
testScript = ''
- $machine->waitForOpenPort(8000);
- $machine->waitForUnit("uwsgi.service");
- my $return = $machine->succeed("curl -X POST http://localhost:8000/api/projects -d 'name=yay&id=yay&password=yay&contact_email=yay\@example.com'");
- die "wrong project id $return" unless "\"yay\"\n" eq $return;
- my $timestamp = $machine->succeed("stat --printf %Y /var/lib/ihatemoney/secret_key");
- my $owner = $machine->succeed("stat --printf %U:%G /var/lib/ihatemoney/secret_key");
- die "wrong ownership for the secret key: $owner, is uwsgi running as the right user ?" unless $owner eq "ihatemoney:ihatemoney";
- $machine->shutdown();
- $machine->start();
- $machine->waitForOpenPort(8000);
- $machine->waitForUnit("uwsgi.service");
- # check that the database is really persistent
- print $machine->succeed("curl --basic -u yay:yay http://localhost:8000/api/projects/yay");
- # check that the secret key is really persistent
- my $timestamp2 = $machine->succeed("stat --printf %Y /var/lib/ihatemoney/secret_key");
- die unless $timestamp eq $timestamp2;
- $machine->succeed("curl http://localhost:8000 | grep ihatemoney");
+ machine.wait_for_open_port(8000)
+ machine.wait_for_unit("uwsgi.service")
+
+ 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'"
+ )
+ owner, timestamp = machine.succeed(
+ "stat --printf %U:%G___%Y /var/lib/ihatemoney/secret_key"
+ ).split("___")
+ assert "ihatemoney:ihatemoney" == owner
+
+ with subtest("Restart machine and service"):
+ machine.shutdown()
+ machine.start()
+ machine.wait_for_open_port(8000)
+ machine.wait_for_unit("uwsgi.service")
+
+ with subtest("check that the database is really persistent"):
+ machine.succeed("curl --basic -u yay:yay http://localhost:8000/api/projects/yay")
+
+ with subtest("check that the secret key is really persistent"):
+ timestamp2 = machine.succeed("stat --printf %Y /var/lib/ihatemoney/secret_key")
+ assert timestamp == timestamp2
+
+ assert "ihatemoney" in machine.succeed("curl http://localhost:8000")
'';
- }
-) [ "sqlite" "postgresql" ]
+ });
+in {
+ ihatemoney-sqlite = f "sqlite";
+ ihatemoney-postgresql = f "postgresql";
+}
diff --git a/nixpkgs/nixos/tests/initrd-network.nix b/nixpkgs/nixos/tests/initrd-network.nix
index 4796ff9b7c8..9c35b730576 100644
--- a/nixpkgs/nixos/tests/initrd-network.nix
+++ b/nixpkgs/nixos/tests/initrd-network.nix
@@ -1,4 +1,4 @@
-import ./make-test-python.nix ({ pkgs, ...} : {
+import ./make-test-python.nix ({ pkgs, lib, ...} : {
name = "initrd-network";
meta.maintainers = [ pkgs.stdenv.lib.maintainers.eelco ];
@@ -8,15 +8,26 @@ import ./make-test-python.nix ({ pkgs, ...} : {
boot.initrd.network.enable = true;
boot.initrd.network.postCommands =
''
+ ip addr show
+ ip route show
ip addr | grep 10.0.2.15 || exit 1
ping -c1 10.0.2.2 || exit 1
'';
+ # Check if cleanup was done correctly
+ boot.initrd.postMountCommands = lib.mkAfter
+ ''
+ ip addr show
+ ip route show
+ ip addr | grep 10.0.2.15 && exit 1
+ ping -c1 10.0.2.2 && exit 1
+ '';
};
testScript =
''
start_all()
machine.wait_for_unit("multi-user.target")
- machine.succeed("ip link >&2")
+ machine.succeed("ip addr show >&2")
+ machine.succeed("ip route show >&2")
'';
})
diff --git a/nixpkgs/nixos/tests/installed-tests/default.nix b/nixpkgs/nixos/tests/installed-tests/default.nix
index 8e997ee4aeb..a189ef63f22 100644
--- a/nixpkgs/nixos/tests/installed-tests/default.nix
+++ b/nixpkgs/nixos/tests/installed-tests/default.nix
@@ -90,7 +90,9 @@ in
graphene = callInstalledTest ./graphene.nix {};
ibus = callInstalledTest ./ibus.nix {};
libgdata = callInstalledTest ./libgdata.nix {};
+ glib-testing = callInstalledTest ./glib-testing.nix {};
libxmlb = callInstalledTest ./libxmlb.nix {};
+ malcontent = callInstalledTest ./malcontent.nix {};
ostree = callInstalledTest ./ostree.nix {};
xdg-desktop-portal = callInstalledTest ./xdg-desktop-portal.nix {};
}
diff --git a/nixpkgs/nixos/tests/installed-tests/fwupd.nix b/nixpkgs/nixos/tests/installed-tests/fwupd.nix
index b9f761e9958..6a0ceb57dda 100644
--- a/nixpkgs/nixos/tests/installed-tests/fwupd.nix
+++ b/nixpkgs/nixos/tests/installed-tests/fwupd.nix
@@ -1,11 +1,11 @@
-{ pkgs, makeInstalledTest, ... }:
+{ pkgs, lib, makeInstalledTest, ... }:
makeInstalledTest {
tested = pkgs.fwupd;
testConfig = {
services.fwupd.enable = true;
- services.fwupd.blacklistPlugins = []; # don't blacklist test plugin
+ services.fwupd.blacklistPlugins = lib.mkForce []; # don't blacklist test plugin
services.fwupd.enableTestRemote = true;
virtualisation.memorySize = 768;
};
diff --git a/nixpkgs/nixos/tests/installed-tests/glib-testing.nix b/nixpkgs/nixos/tests/installed-tests/glib-testing.nix
new file mode 100644
index 00000000000..7a06cf792bd
--- /dev/null
+++ b/nixpkgs/nixos/tests/installed-tests/glib-testing.nix
@@ -0,0 +1,5 @@
+{ pkgs, makeInstalledTest, ... }:
+
+makeInstalledTest {
+ tested = pkgs.glib-testing;
+}
diff --git a/nixpkgs/nixos/tests/installed-tests/malcontent.nix b/nixpkgs/nixos/tests/installed-tests/malcontent.nix
new file mode 100644
index 00000000000..d4e214c4198
--- /dev/null
+++ b/nixpkgs/nixos/tests/installed-tests/malcontent.nix
@@ -0,0 +1,5 @@
+{ pkgs, makeInstalledTest, ... }:
+
+makeInstalledTest {
+ tested = pkgs.malcontent;
+}
diff --git a/nixpkgs/nixos/tests/installed-tests/xdg-desktop-portal.nix b/nixpkgs/nixos/tests/installed-tests/xdg-desktop-portal.nix
index b16008ff4ad..90529d37ee0 100644
--- a/nixpkgs/nixos/tests/installed-tests/xdg-desktop-portal.nix
+++ b/nixpkgs/nixos/tests/installed-tests/xdg-desktop-portal.nix
@@ -2,4 +2,8 @@
makeInstalledTest {
tested = pkgs.xdg-desktop-portal;
+
+ # Ton of breakage.
+ # https://github.com/flatpak/xdg-desktop-portal/pull/428
+ meta.broken = true;
}
diff --git a/nixpkgs/nixos/tests/installer.nix b/nixpkgs/nixos/tests/installer.nix
index eb1f4f192dd..983861911e0 100644
--- a/nixpkgs/nixos/tests/installer.nix
+++ b/nixpkgs/nixos/tests/installer.nix
@@ -3,7 +3,7 @@
pkgs ? import ../.. { inherit system config; }
}:
-with import ../lib/testing.nix { inherit system pkgs; };
+with import ../lib/testing-python.nix { inherit system pkgs; };
with pkgs.lib;
let
@@ -67,161 +67,193 @@ let
, grubIdentifier, preBootCommands, extraConfig
, testCloneConfig
}:
- let
- iface = if grubVersion == 1 then "ide" else "virtio";
- isEfi = bootLoader == "systemd-boot" || (bootLoader == "grub" && grubUseEfi);
-
- # FIXME don't duplicate the -enable-kvm etc. flags here yet again!
- qemuFlags =
- (if system == "x86_64-linux" then "-m 768 " else "-m 512 ") +
- (optionalString (system == "x86_64-linux") "-cpu kvm64 ") +
- (optionalString (system == "aarch64-linux") "-enable-kvm -machine virt,gic-version=host -cpu host ");
-
- hdFlags = ''hda => "vm-state-machine/machine.qcow2", hdaInterface => "${iface}", ''
- + optionalString isEfi (if pkgs.stdenv.isAarch64
- then ''bios => "${pkgs.OVMF.fd}/FV/QEMU_EFI.fd", ''
- else ''bios => "${pkgs.OVMF.fd}/FV/OVMF.fd", '');
+ let iface = if grubVersion == 1 then "ide" else "virtio";
+ isEfi = bootLoader == "systemd-boot" || (bootLoader == "grub" && grubUseEfi);
+ bios = if pkgs.stdenv.isAarch64 then "QEMU_EFI.fd" else "OVMF.fd";
in if !isEfi && !(pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) then
throw "Non-EFI boot methods are only supported on i686 / x86_64"
else ''
+ def assemble_qemu_flags():
+ flags = "-cpu host"
+ ${if system == "x86_64-linux"
+ then ''flags += " -m 768"''
+ else ''flags += " -m 512 -enable-kvm -machine virt,gic-version=host"''
+ }
+ return flags
- $machine->start;
- # Make sure that we get a login prompt etc.
- $machine->succeed("echo hello");
- #$machine->waitForUnit('getty@tty2');
- #$machine->waitForUnit("rogue");
- $machine->waitForUnit("nixos-manual");
+ qemu_flags = {"qemuFlags": assemble_qemu_flags()}
- # Wait for hard disks to appear in /dev
- $machine->succeed("udevadm settle");
+ hd_flags = {
+ "hdaInterface": "${iface}",
+ "hda": "vm-state-machine/machine.qcow2",
+ }
+ ${optionalString isEfi ''
+ hd_flags.update(
+ bios="${pkgs.OVMF.fd}/FV/${bios}"
+ )''
+ }
+ default_flags = {**hd_flags, **qemu_flags}
- # Partition the disk.
- ${createPartitions}
- # Create the NixOS configuration.
- $machine->succeed("nixos-generate-config --root /mnt");
+ def create_machine_named(name):
+ return create_machine({**default_flags, "name": "boot-after-install"})
- $machine->succeed("cat /mnt/etc/nixos/hardware-configuration.nix >&2");
- $machine->copyFileFromHost(
- "${ makeConfig { inherit bootLoader grubVersion grubDevice grubIdentifier grubUseEfi extraConfig; } }",
- "/mnt/etc/nixos/configuration.nix");
+ machine.start()
- # Perform the installation.
- $machine->succeed("nixos-install < /dev/null >&2");
+ with subtest("Assert readiness of login prompt"):
+ machine.succeed("echo hello")
+ machine.wait_for_unit("nixos-manual")
- # Do it again to make sure it's idempotent.
- $machine->succeed("nixos-install < /dev/null >&2");
+ with subtest("Wait for hard disks to appear in /dev"):
+ machine.succeed("udevadm settle")
- $machine->succeed("umount /mnt/boot || true");
- $machine->succeed("umount /mnt");
- $machine->succeed("sync");
+ ${createPartitions}
- $machine->shutdown;
+ with subtest("Create the NixOS configuration"):
+ machine.succeed("nixos-generate-config --root /mnt")
+ machine.succeed("cat /mnt/etc/nixos/hardware-configuration.nix >&2")
+ machine.copy_from_host(
+ "${ makeConfig {
+ inherit bootLoader grubVersion grubDevice grubIdentifier
+ grubUseEfi extraConfig;
+ }
+ }",
+ "/mnt/etc/nixos/configuration.nix",
+ )
+
+ with subtest("Perform the installation"):
+ machine.succeed("nixos-install < /dev/null >&2")
+
+ with subtest("Do it again to make sure it's idempotent"):
+ machine.succeed("nixos-install < /dev/null >&2")
+
+ with subtest("Shutdown system after installation"):
+ machine.succeed("umount /mnt/boot || true")
+ machine.succeed("umount /mnt")
+ machine.succeed("sync")
+ machine.shutdown()
# Now see if we can boot the installation.
- $machine = createMachine({ ${hdFlags} qemuFlags => "${qemuFlags}", name => "boot-after-install" });
+ machine = create_machine_named("boot-after-install")
# For example to enter LUKS passphrase.
${preBootCommands}
- # Did /boot get mounted?
- $machine->waitForUnit("local-fs.target");
-
- ${if bootLoader == "grub" then
- ''$machine->succeed("test -e /boot/grub");''
- else
- ''$machine->succeed("test -e /boot/loader/loader.conf");''
- }
-
- # Check whether /root has correct permissions.
- $machine->succeed("stat -c '%a' /root") =~ /700/ or die;
-
- # Did the swap device get activated?
- # uncomment once https://bugs.freedesktop.org/show_bug.cgi?id=86930 is resolved
- $machine->waitForUnit("swap.target");
- $machine->succeed("cat /proc/swaps | grep -q /dev");
-
- # Check that the store is in good shape
- $machine->succeed("nix-store --verify --check-contents >&2");
-
- # Check whether the channel works.
- $machine->succeed("nix-env -iA nixos.procps >&2");
- $machine->succeed("type -tP ps | tee /dev/stderr") =~ /.nix-profile/
- or die "nix-env failed";
-
- # Check that the daemon works, and that non-root users can run builds (this will build a new profile generation through the daemon)
- $machine->succeed("su alice -l -c 'nix-env -iA nixos.procps' >&2");
-
- # We need a writable Nix store on next boot.
- $machine->copyFileFromHost(
- "${ makeConfig { inherit bootLoader grubVersion grubDevice grubIdentifier grubUseEfi extraConfig; forceGrubReinstallCount = 1; } }",
- "/etc/nixos/configuration.nix");
-
- # Check whether nixos-rebuild works.
- $machine->succeed("nixos-rebuild switch >&2");
-
- # Test nixos-option.
- $machine->succeed("nixos-option boot.initrd.kernelModules | grep virtio_console");
- $machine->succeed("nixos-option boot.initrd.kernelModules | grep 'List of modules'");
- $machine->succeed("nixos-option boot.initrd.kernelModules | grep qemu-guest.nix");
-
- $machine->shutdown;
+ with subtest("Assert that /boot get mounted"):
+ machine.wait_for_unit("local-fs.target")
+ ${if bootLoader == "grub"
+ then ''machine.succeed("test -e /boot/grub")''
+ else ''machine.succeed("test -e /boot/loader/loader.conf")''
+ }
+
+ with subtest("Check whether /root has correct permissions"):
+ assert "700" in machine.succeed("stat -c '%a' /root")
+
+ with subtest("Assert swap device got activated"):
+ # uncomment once https://bugs.freedesktop.org/show_bug.cgi?id=86930 is resolved
+ machine.wait_for_unit("swap.target")
+ machine.succeed("cat /proc/swaps | grep -q /dev")
+
+ with subtest("Check that the store is in good shape"):
+ machine.succeed("nix-store --verify --check-contents >&2")
+
+ with subtest("Check whether the channel works"):
+ machine.succeed("nix-env -iA nixos.procps >&2")
+ assert ".nix-profile" in machine.succeed("type -tP ps | tee /dev/stderr")
+
+ with subtest(
+ "Check that the daemon works, and that non-root users can run builds "
+ "(this will build a new profile generation through the daemon)"
+ ):
+ machine.succeed("su alice -l -c 'nix-env -iA nixos.procps' >&2")
+
+ with subtest("Configure system with writable Nix store on next boot"):
+ # we're not using copy_from_host here because the installer image
+ # doesn't know about the host-guest sharing mechanism.
+ machine.copy_from_host_via_shell(
+ "${ makeConfig {
+ inherit bootLoader grubVersion grubDevice grubIdentifier
+ grubUseEfi extraConfig;
+ forceGrubReinstallCount = 1;
+ }
+ }",
+ "/etc/nixos/configuration.nix",
+ )
+
+ with subtest("Check whether nixos-rebuild works"):
+ machine.succeed("nixos-rebuild switch >&2")
+
+ with subtest("Test nixos-option"):
+ kernel_modules = machine.succeed("nixos-option boot.initrd.kernelModules")
+ assert "virtio_console" in kernel_modules
+ assert "List of modules" in kernel_modules
+ assert "qemu-guest.nix" in kernel_modules
+
+ machine.shutdown()
# Check whether a writable store build works
- $machine = createMachine({ ${hdFlags} qemuFlags => "${qemuFlags}", name => "rebuild-switch" });
+ machine = create_machine_named("rebuild-switch")
${preBootCommands}
- $machine->waitForUnit("multi-user.target");
- $machine->copyFileFromHost(
- "${ makeConfig { inherit bootLoader grubVersion grubDevice grubIdentifier grubUseEfi extraConfig; forceGrubReinstallCount = 2; } }",
- "/etc/nixos/configuration.nix");
- $machine->succeed("nixos-rebuild boot >&2");
- $machine->shutdown;
+ machine.wait_for_unit("multi-user.target")
+
+ # we're not using copy_from_host here because the installer image
+ # doesn't know about the host-guest sharing mechanism.
+ machine.copy_from_host_via_shell(
+ "${ makeConfig {
+ inherit bootLoader grubVersion grubDevice grubIdentifier
+ grubUseEfi extraConfig;
+ forceGrubReinstallCount = 2;
+ }
+ }",
+ "/etc/nixos/configuration.nix",
+ )
+ machine.succeed("nixos-rebuild boot >&2")
+ machine.shutdown()
# And just to be sure, check that the machine still boots after
# "nixos-rebuild switch".
- $machine = createMachine({ ${hdFlags} qemuFlags => "${qemuFlags}", "boot-after-rebuild-switch" });
+ machine = create_machine_named("boot-after-rebuild-switch")
${preBootCommands}
- $machine->waitForUnit("network.target");
- $machine->shutdown;
+ machine.wait_for_unit("network.target")
+ machine.shutdown()
# Tests for validating clone configuration entries in grub menu
- ${optionalString testCloneConfig ''
- # Reboot Machine
- $machine = createMachine({ ${hdFlags} qemuFlags => "${qemuFlags}", name => "clone-default-config" });
- ${preBootCommands}
- $machine->waitForUnit("multi-user.target");
-
- # Booted configuration name should be Home
- # This is not the name that shows in the grub menu.
- # The default configuration is always shown as "Default"
- $machine->succeed("cat /run/booted-system/configuration-name >&2");
- $machine->succeed("cat /run/booted-system/configuration-name | grep Home");
+ ''
+ + optionalString testCloneConfig ''
+ # Reboot Machine
+ machine = create_machine_named("clone-default-config")
+ ${preBootCommands}
+ machine.wait_for_unit("multi-user.target")
- # We should find **not** a file named /etc/gitconfig
- $machine->fail("test -e /etc/gitconfig");
+ with subtest("Booted configuration name should be 'Home'"):
+ # This is not the name that shows in the grub menu.
+ # The default configuration is always shown as "Default"
+ machine.succeed("cat /run/booted-system/configuration-name >&2")
+ assert "Home" in machine.succeed("cat /run/booted-system/configuration-name")
- # Set grub to boot the second configuration
- $machine->succeed("grub-reboot 1");
+ with subtest("We should **not** find a file named /etc/gitconfig"):
+ machine.fail("test -e /etc/gitconfig")
- $machine->shutdown;
+ with subtest("Set grub to boot the second configuration"):
+ machine.succeed("grub-reboot 1")
- # Reboot Machine
- $machine = createMachine({ ${hdFlags} qemuFlags => "${qemuFlags}", name => "clone-alternate-config" });
- ${preBootCommands}
+ machine.shutdown()
- $machine->waitForUnit("multi-user.target");
- # Booted configuration name should be Work
- $machine->succeed("cat /run/booted-system/configuration-name >&2");
- $machine->succeed("cat /run/booted-system/configuration-name | grep Work");
+ # Reboot Machine
+ machine = create_machine_named("clone-alternate-config")
+ ${preBootCommands}
- # We should find a file named /etc/gitconfig
- $machine->succeed("test -e /etc/gitconfig");
+ machine.wait_for_unit("multi-user.target")
+ with subtest("Booted configuration name should be Work"):
+ machine.succeed("cat /run/booted-system/configuration-name >&2")
+ assert "Work" in machine.succeed("cat /run/booted-system/configuration-name")
- $machine->shutdown;
- ''}
+ with subtest("We should find a file named /etc/gitconfig"):
+ machine.succeed("test -e /etc/gitconfig")
+ machine.shutdown()
'';
@@ -243,63 +275,63 @@ let
nodes = {
# The configuration of the machine used to run "nixos-install".
- machine =
- { pkgs, ... }:
-
- { imports =
- [ ../modules/profiles/installation-device.nix
- ../modules/profiles/base.nix
- extraInstallerConfig
- ];
-
- virtualisation.diskSize = 8 * 1024;
- virtualisation.memorySize = 1024;
-
- # Use a small /dev/vdb as the root disk for the
- # installer. This ensures the target disk (/dev/vda) is
- # the same during and after installation.
- virtualisation.emptyDiskImages = [ 512 ];
- virtualisation.bootDevice =
- if grubVersion == 1 then "/dev/sdb" else "/dev/vdb";
- virtualisation.qemu.diskInterface =
- if grubVersion == 1 then "scsi" else "virtio";
-
- boot.loader.systemd-boot.enable = mkIf (bootLoader == "systemd-boot") true;
-
- hardware.enableAllFirmware = mkForce false;
-
- # The test cannot access the network, so any packages we
- # need must be included in the VM.
- system.extraDependencies = with pkgs;
- [ sudo
- libxml2.bin
- libxslt.bin
- desktop-file-utils
- docbook5
- docbook_xsl_ns
- unionfs-fuse
- ntp
- nixos-artwork.wallpapers.simple-dark-gray-bottom
- perlPackages.XMLLibXML
- perlPackages.ListCompare
- shared-mime-info
- texinfo
- xorg.lndir
-
- # add curl so that rather than seeing the test attempt to download
- # curl's tarball, we see what it's trying to download
- curl
- ]
- ++ optional (bootLoader == "grub" && grubVersion == 1) pkgs.grub
- ++ optionals (bootLoader == "grub" && grubVersion == 2) [ pkgs.grub2 pkgs.grub2_efi ];
-
- nix.binaryCaches = mkForce [ ];
- nix.extraOptions =
- ''
- hashed-mirrors =
- connect-timeout = 1
- '';
- };
+ machine = { pkgs, ... }: {
+ imports = [
+ ../modules/profiles/installation-device.nix
+ ../modules/profiles/base.nix
+ extraInstallerConfig
+ ];
+
+ virtualisation.diskSize = 8 * 1024;
+ virtualisation.memorySize = 1024;
+
+ # Use a small /dev/vdb as the root disk for the
+ # installer. This ensures the target disk (/dev/vda) is
+ # the same during and after installation.
+ virtualisation.emptyDiskImages = [ 512 ];
+ virtualisation.bootDevice =
+ if grubVersion == 1 then "/dev/sdb" else "/dev/vdb";
+ virtualisation.qemu.diskInterface =
+ if grubVersion == 1 then "scsi" else "virtio";
+
+ boot.loader.systemd-boot.enable = mkIf (bootLoader == "systemd-boot") true;
+
+ hardware.enableAllFirmware = mkForce false;
+
+ # The test cannot access the network, so any packages we
+ # need must be included in the VM.
+ system.extraDependencies = with pkgs; [
+ desktop-file-utils
+ docbook5
+ docbook_xsl_ns
+ libxml2.bin
+ libxslt.bin
+ nixos-artwork.wallpapers.simple-dark-gray-bottom
+ ntp
+ perlPackages.ListCompare
+ perlPackages.XMLLibXML
+ shared-mime-info
+ sudo
+ texinfo
+ unionfs-fuse
+ xorg.lndir
+
+ # add curl so that rather than seeing the test attempt to download
+ # curl's tarball, we see what it's trying to download
+ curl
+ ]
+ ++ optional (bootLoader == "grub" && grubVersion == 1) pkgs.grub
+ ++ optionals (bootLoader == "grub" && grubVersion == 2) [
+ pkgs.grub2
+ pkgs.grub2_efi
+ ];
+
+ nix.binaryCaches = mkForce [ ];
+ nix.extraOptions = ''
+ hashed-mirrors =
+ connect-timeout = 1
+ '';
+ };
};
@@ -310,13 +342,13 @@ let
};
};
- makeLuksRootTest = name: luksFormatOpts: makeInstallerTest name
- { createPartitions = ''
- $machine->succeed(
+ makeLuksRootTest = name: luksFormatOpts: makeInstallerTest name {
+ createPartitions = ''
+ machine.succeed(
"flock /dev/vda parted --script /dev/vda -- mklabel msdos"
- . " mkpart primary ext2 1M 50MB" # /boot
- . " mkpart primary linux-swap 50M 1024M"
- . " mkpart primary 1024M -1s", # LUKS
+ + " mkpart primary ext2 1M 50MB" # /boot
+ + " mkpart primary linux-swap 50M 1024M"
+ + " mkpart primary 1024M -1s", # LUKS
"udevadm settle",
"mkswap /dev/vda2 -L swap",
"swapon -L swap",
@@ -328,77 +360,74 @@ let
"mkfs.ext3 -L boot /dev/vda1",
"mkdir -p /mnt/boot",
"mount LABEL=boot /mnt/boot",
- );
- '';
- extraConfig = ''
- boot.kernelParams = lib.mkAfter [ "console=tty0" ];
- '';
- enableOCR = true;
- preBootCommands = ''
- $machine->start;
- $machine->waitForText(qr/Passphrase for/);
- $machine->sendChars("supersecret\n");
- '';
- };
+ )
+ '';
+ extraConfig = ''
+ boot.kernelParams = lib.mkAfter [ "console=tty0" ];
+ '';
+ enableOCR = true;
+ preBootCommands = ''
+ machine.start()
+ machine.wait_for_text("Passphrase for")
+ machine.send_chars("supersecret\n")
+ '';
+ };
# The (almost) simplest partitioning scheme: a swap partition and
# one big filesystem partition.
- simple-test-config = { createPartitions =
- ''
- $machine->succeed(
- "flock /dev/vda parted --script /dev/vda -- mklabel msdos"
- . " mkpart primary linux-swap 1M 1024M"
- . " mkpart primary ext2 1024M -1s",
- "udevadm settle",
- "mkswap /dev/vda1 -L swap",
- "swapon -L swap",
- "mkfs.ext3 -L nixos /dev/vda2",
- "mount LABEL=nixos /mnt",
- );
- '';
- };
-
- simple-uefi-grub-config =
- { createPartitions =
- ''
- $machine->succeed(
- "flock /dev/vda parted --script /dev/vda -- mklabel gpt"
- . " mkpart ESP fat32 1M 50MiB" # /boot
- . " set 1 boot on"
- . " mkpart primary linux-swap 50MiB 1024MiB"
- . " mkpart primary ext2 1024MiB -1MiB", # /
- "udevadm settle",
- "mkswap /dev/vda2 -L swap",
- "swapon -L swap",
- "mkfs.ext3 -L nixos /dev/vda3",
- "mount LABEL=nixos /mnt",
- "mkfs.vfat -n BOOT /dev/vda1",
- "mkdir -p /mnt/boot",
- "mount LABEL=BOOT /mnt/boot",
- );
- '';
- bootLoader = "grub";
- grubUseEfi = true;
- };
+ simple-test-config = {
+ createPartitions = ''
+ machine.succeed(
+ "flock /dev/vda parted --script /dev/vda -- mklabel msdos"
+ + " mkpart primary linux-swap 1M 1024M"
+ + " mkpart primary ext2 1024M -1s",
+ "udevadm settle",
+ "mkswap /dev/vda1 -L swap",
+ "swapon -L swap",
+ "mkfs.ext3 -L nixos /dev/vda2",
+ "mount LABEL=nixos /mnt",
+ )
+ '';
+ };
+
+ simple-uefi-grub-config = {
+ createPartitions = ''
+ machine.succeed(
+ "flock /dev/vda parted --script /dev/vda -- mklabel gpt"
+ + " mkpart ESP fat32 1M 50MiB" # /boot
+ + " set 1 boot on"
+ + " mkpart primary linux-swap 50MiB 1024MiB"
+ + " mkpart primary ext2 1024MiB -1MiB", # /
+ "udevadm settle",
+ "mkswap /dev/vda2 -L swap",
+ "swapon -L swap",
+ "mkfs.ext3 -L nixos /dev/vda3",
+ "mount LABEL=nixos /mnt",
+ "mkfs.vfat -n BOOT /dev/vda1",
+ "mkdir -p /mnt/boot",
+ "mount LABEL=BOOT /mnt/boot",
+ )
+ '';
+ bootLoader = "grub";
+ grubUseEfi = true;
+ };
- clone-test-extraconfig = { extraConfig =
- ''
- environment.systemPackages = [ pkgs.grub2 ];
- boot.loader.grub.configurationName = "Home";
- nesting.clone = [
- {
- boot.loader.grub.configurationName = lib.mkForce "Work";
-
- environment.etc = {
- "gitconfig".text = "
- [core]
- gitproxy = none for work.com
- ";
- };
- }
- ];
- '';
- testCloneConfig = true;
+ clone-test-extraconfig = {
+ extraConfig = ''
+ environment.systemPackages = [ pkgs.grub2 ];
+ boot.loader.grub.configurationName = "Home";
+ nesting.clone = [ {
+ boot.loader.grub.configurationName = lib.mkForce "Work";
+
+ environment.etc = {
+ "gitconfig".text = "
+ [core]
+ gitproxy = none for work.com
+ ";
+ };
+ } ];
+ '';
+ testCloneConfig = true;
};
@@ -415,27 +444,26 @@ in {
simpleClone = makeInstallerTest "simpleClone" (simple-test-config // clone-test-extraconfig);
# Simple GPT/UEFI configuration using systemd-boot with 3 partitions: ESP, swap & root filesystem
- simpleUefiSystemdBoot = makeInstallerTest "simpleUefiSystemdBoot"
- { createPartitions =
- ''
- $machine->succeed(
- "flock /dev/vda parted --script /dev/vda -- mklabel gpt"
- . " mkpart ESP fat32 1M 50MiB" # /boot
- . " set 1 boot on"
- . " mkpart primary linux-swap 50MiB 1024MiB"
- . " mkpart primary ext2 1024MiB -1MiB", # /
- "udevadm settle",
- "mkswap /dev/vda2 -L swap",
- "swapon -L swap",
- "mkfs.ext3 -L nixos /dev/vda3",
- "mount LABEL=nixos /mnt",
- "mkfs.vfat -n BOOT /dev/vda1",
- "mkdir -p /mnt/boot",
- "mount LABEL=BOOT /mnt/boot",
- );
- '';
- bootLoader = "systemd-boot";
- };
+ simpleUefiSystemdBoot = makeInstallerTest "simpleUefiSystemdBoot" {
+ createPartitions = ''
+ machine.succeed(
+ "flock /dev/vda parted --script /dev/vda -- mklabel gpt"
+ + " mkpart ESP fat32 1M 50MiB" # /boot
+ + " set 1 boot on"
+ + " mkpart primary linux-swap 50MiB 1024MiB"
+ + " mkpart primary ext2 1024MiB -1MiB", # /
+ "udevadm settle",
+ "mkswap /dev/vda2 -L swap",
+ "swapon -L swap",
+ "mkfs.ext3 -L nixos /dev/vda3",
+ "mount LABEL=nixos /mnt",
+ "mkfs.vfat -n BOOT /dev/vda1",
+ "mkdir -p /mnt/boot",
+ "mount LABEL=BOOT /mnt/boot",
+ )
+ '';
+ bootLoader = "systemd-boot";
+ };
simpleUefiGrub = makeInstallerTest "simpleUefiGrub" simple-uefi-grub-config;
@@ -443,107 +471,99 @@ in {
simpleUefiGrubClone = makeInstallerTest "simpleUefiGrubClone" (simple-uefi-grub-config // clone-test-extraconfig);
# Same as the previous, but now with a separate /boot partition.
- separateBoot = makeInstallerTest "separateBoot"
- { createPartitions =
- ''
- $machine->succeed(
- "flock /dev/vda parted --script /dev/vda -- mklabel msdos"
- . " mkpart primary ext2 1M 50MB" # /boot
- . " mkpart primary linux-swap 50MB 1024M"
- . " mkpart primary ext2 1024M -1s", # /
- "udevadm settle",
- "mkswap /dev/vda2 -L swap",
- "swapon -L swap",
- "mkfs.ext3 -L nixos /dev/vda3",
- "mount LABEL=nixos /mnt",
- "mkfs.ext3 -L boot /dev/vda1",
- "mkdir -p /mnt/boot",
- "mount LABEL=boot /mnt/boot",
- );
- '';
- };
+ separateBoot = makeInstallerTest "separateBoot" {
+ createPartitions = ''
+ machine.succeed(
+ "flock /dev/vda parted --script /dev/vda -- mklabel msdos"
+ + " mkpart primary ext2 1M 50MB" # /boot
+ + " mkpart primary linux-swap 50MB 1024M"
+ + " mkpart primary ext2 1024M -1s", # /
+ "udevadm settle",
+ "mkswap /dev/vda2 -L swap",
+ "swapon -L swap",
+ "mkfs.ext3 -L nixos /dev/vda3",
+ "mount LABEL=nixos /mnt",
+ "mkfs.ext3 -L boot /dev/vda1",
+ "mkdir -p /mnt/boot",
+ "mount LABEL=boot /mnt/boot",
+ )
+ '';
+ };
# Same as the previous, but with fat32 /boot.
- separateBootFat = makeInstallerTest "separateBootFat"
- { createPartitions =
- ''
- $machine->succeed(
- "flock /dev/vda parted --script /dev/vda -- mklabel msdos"
- . " mkpart primary ext2 1M 50MB" # /boot
- . " mkpart primary linux-swap 50MB 1024M"
- . " mkpart primary ext2 1024M -1s", # /
- "udevadm settle",
- "mkswap /dev/vda2 -L swap",
- "swapon -L swap",
- "mkfs.ext3 -L nixos /dev/vda3",
- "mount LABEL=nixos /mnt",
- "mkfs.vfat -n BOOT /dev/vda1",
- "mkdir -p /mnt/boot",
- "mount LABEL=BOOT /mnt/boot",
- );
- '';
- };
+ separateBootFat = makeInstallerTest "separateBootFat" {
+ createPartitions = ''
+ machine.succeed(
+ "flock /dev/vda parted --script /dev/vda -- mklabel msdos"
+ + " mkpart primary ext2 1M 50MB" # /boot
+ + " mkpart primary linux-swap 50MB 1024M"
+ + " mkpart primary ext2 1024M -1s", # /
+ "udevadm settle",
+ "mkswap /dev/vda2 -L swap",
+ "swapon -L swap",
+ "mkfs.ext3 -L nixos /dev/vda3",
+ "mount LABEL=nixos /mnt",
+ "mkfs.vfat -n BOOT /dev/vda1",
+ "mkdir -p /mnt/boot",
+ "mount LABEL=BOOT /mnt/boot",
+ )
+ '';
+ };
# zfs on / with swap
- zfsroot = makeInstallerTest "zfs-root"
- {
- extraInstallerConfig = {
- boot.supportedFilesystems = [ "zfs" ];
- };
-
- extraConfig = ''
- boot.supportedFilesystems = [ "zfs" ];
-
- # Using by-uuid overrides the default of by-id, and is unique
- # to the qemu disks, as they don't produce by-id paths for
- # some reason.
- boot.zfs.devNodes = "/dev/disk/by-uuid/";
- networking.hostId = "00000000";
- '';
-
- createPartitions =
- ''
- $machine->succeed(
- "flock /dev/vda parted --script /dev/vda -- mklabel msdos"
- . " mkpart primary linux-swap 1M 1024M"
- . " mkpart primary 1024M -1s",
- "udevadm settle",
+ zfsroot = makeInstallerTest "zfs-root" {
+ extraInstallerConfig = {
+ boot.supportedFilesystems = [ "zfs" ];
+ };
- "mkswap /dev/vda1 -L swap",
- "swapon -L swap",
+ extraConfig = ''
+ boot.supportedFilesystems = [ "zfs" ];
- "zpool create rpool /dev/vda2",
- "zfs create -o mountpoint=legacy rpool/root",
- "mount -t zfs rpool/root /mnt",
+ # Using by-uuid overrides the default of by-id, and is unique
+ # to the qemu disks, as they don't produce by-id paths for
+ # some reason.
+ boot.zfs.devNodes = "/dev/disk/by-uuid/";
+ networking.hostId = "00000000";
+ '';
- "udevadm settle"
- );
- '';
- };
+ createPartitions = ''
+ machine.succeed(
+ "flock /dev/vda parted --script /dev/vda -- mklabel msdos"
+ + " mkpart primary linux-swap 1M 1024M"
+ + " mkpart primary 1024M -1s",
+ "udevadm settle",
+ "mkswap /dev/vda1 -L swap",
+ "swapon -L swap",
+ "zpool create rpool /dev/vda2",
+ "zfs create -o mountpoint=legacy rpool/root",
+ "mount -t zfs rpool/root /mnt",
+ "udevadm settle",
+ )
+ '';
+ };
# Create two physical LVM partitions combined into one volume group
# that contains the logical swap and root partitions.
- lvm = makeInstallerTest "lvm"
- { createPartitions =
- ''
- $machine->succeed(
- "flock /dev/vda parted --script /dev/vda -- mklabel msdos"
- . " mkpart primary 1M 2048M" # PV1
- . " set 1 lvm on"
- . " mkpart primary 2048M -1s" # PV2
- . " set 2 lvm on",
- "udevadm settle",
- "pvcreate /dev/vda1 /dev/vda2",
- "vgcreate MyVolGroup /dev/vda1 /dev/vda2",
- "lvcreate --size 1G --name swap MyVolGroup",
- "lvcreate --size 2G --name nixos MyVolGroup",
- "mkswap -f /dev/MyVolGroup/swap -L swap",
- "swapon -L swap",
- "mkfs.xfs -L nixos /dev/MyVolGroup/nixos",
- "mount LABEL=nixos /mnt",
- );
- '';
- };
+ lvm = makeInstallerTest "lvm" {
+ createPartitions = ''
+ machine.succeed(
+ "flock /dev/vda parted --script /dev/vda -- mklabel msdos"
+ + " mkpart primary 1M 2048M" # PV1
+ + " set 1 lvm on"
+ + " mkpart primary 2048M -1s" # PV2
+ + " set 2 lvm on",
+ "udevadm settle",
+ "pvcreate /dev/vda1 /dev/vda2",
+ "vgcreate MyVolGroup /dev/vda1 /dev/vda2",
+ "lvcreate --size 1G --name swap MyVolGroup",
+ "lvcreate --size 2G --name nixos MyVolGroup",
+ "mkswap -f /dev/MyVolGroup/swap -L swap",
+ "swapon -L swap",
+ "mkfs.xfs -L nixos /dev/MyVolGroup/nixos",
+ "mount LABEL=nixos /mnt",
+ )
+ '';
+ };
# Boot off an encrypted root partition with the default LUKS header format
luksroot = makeLuksRootTest "luksroot-format1" "";
@@ -557,14 +577,14 @@ in {
# Test whether opening encrypted filesystem with keyfile
# Checks for regression of missing cryptsetup, when no luks device without
# keyfile is configured
- encryptedFSWithKeyfile = makeInstallerTest "encryptedFSWithKeyfile"
- { createPartitions = ''
- $machine->succeed(
+ encryptedFSWithKeyfile = makeInstallerTest "encryptedFSWithKeyfile" {
+ createPartitions = ''
+ machine.succeed(
"flock /dev/vda parted --script /dev/vda -- mklabel msdos"
- . " mkpart primary ext2 1M 50MB" # /boot
- . " mkpart primary linux-swap 50M 1024M"
- . " mkpart primary 1024M 1280M" # LUKS with keyfile
- . " mkpart primary 1280M -1s",
+ + " mkpart primary ext2 1M 50MB" # /boot
+ + " mkpart primary linux-swap 50M 1024M"
+ + " mkpart primary 1024M 1280M" # LUKS with keyfile
+ + " mkpart primary 1280M -1s",
"udevadm settle",
"mkswap /dev/vda2 -L swap",
"swapon -L swap",
@@ -579,89 +599,88 @@ in {
"cryptsetup luksOpen --key-file /mnt/keyfile /dev/vda3 crypt",
"mkfs.ext3 -L test /dev/mapper/crypt",
"cryptsetup luksClose crypt",
- "mkdir -p /mnt/test"
- );
- '';
- extraConfig = ''
- fileSystems."/test" =
- { device = "/dev/disk/by-label/test";
- fsType = "ext3";
- encrypted.enable = true;
- encrypted.blkDev = "/dev/vda3";
- encrypted.label = "crypt";
- encrypted.keyFile = "/mnt-root/keyfile";
- };
- '';
- };
-
+ "mkdir -p /mnt/test",
+ )
+ '';
+ extraConfig = ''
+ fileSystems."/test" = {
+ device = "/dev/disk/by-label/test";
+ fsType = "ext3";
+ encrypted.enable = true;
+ encrypted.blkDev = "/dev/vda3";
+ encrypted.label = "crypt";
+ encrypted.keyFile = "/mnt-root/keyfile";
+ };
+ '';
+ };
- swraid = makeInstallerTest "swraid"
- { createPartitions =
- ''
- $machine->succeed(
- "flock /dev/vda parted --script /dev/vda --"
- . " mklabel msdos"
- . " mkpart primary ext2 1M 100MB" # /boot
- . " mkpart extended 100M -1s"
- . " mkpart logical 102M 2102M" # md0 (root), first device
- . " mkpart logical 2103M 4103M" # md0 (root), second device
- . " mkpart logical 4104M 4360M" # md1 (swap), first device
- . " mkpart logical 4361M 4617M", # md1 (swap), second device
- "udevadm settle",
- "ls -l /dev/vda* >&2",
- "cat /proc/partitions >&2",
- "udevadm control --stop-exec-queue",
- "mdadm --create --force /dev/md0 --metadata 1.2 --level=raid1 --raid-devices=2 /dev/vda5 /dev/vda6",
- "mdadm --create --force /dev/md1 --metadata 1.2 --level=raid1 --raid-devices=2 /dev/vda7 /dev/vda8",
- "udevadm control --start-exec-queue",
- "udevadm settle",
- "mkswap -f /dev/md1 -L swap",
- "swapon -L swap",
- "mkfs.ext3 -L nixos /dev/md0",
- "mount LABEL=nixos /mnt",
- "mkfs.ext3 -L boot /dev/vda1",
- "mkdir /mnt/boot",
- "mount LABEL=boot /mnt/boot",
- "udevadm settle",
- );
- '';
- preBootCommands = ''
- $machine->start;
- $machine->fail("dmesg | grep 'immediate safe mode'");
- '';
- };
+ swraid = makeInstallerTest "swraid" {
+ createPartitions = ''
+ machine.succeed(
+ "flock /dev/vda parted --script /dev/vda --"
+ + " mklabel msdos"
+ + " mkpart primary ext2 1M 100MB" # /boot
+ + " mkpart extended 100M -1s"
+ + " mkpart logical 102M 2102M" # md0 (root), first device
+ + " mkpart logical 2103M 4103M" # md0 (root), second device
+ + " mkpart logical 4104M 4360M" # md1 (swap), first device
+ + " mkpart logical 4361M 4617M", # md1 (swap), second device
+ "udevadm settle",
+ "ls -l /dev/vda* >&2",
+ "cat /proc/partitions >&2",
+ "udevadm control --stop-exec-queue",
+ "mdadm --create --force /dev/md0 --metadata 1.2 --level=raid1 "
+ + "--raid-devices=2 /dev/vda5 /dev/vda6",
+ "mdadm --create --force /dev/md1 --metadata 1.2 --level=raid1 "
+ + "--raid-devices=2 /dev/vda7 /dev/vda8",
+ "udevadm control --start-exec-queue",
+ "udevadm settle",
+ "mkswap -f /dev/md1 -L swap",
+ "swapon -L swap",
+ "mkfs.ext3 -L nixos /dev/md0",
+ "mount LABEL=nixos /mnt",
+ "mkfs.ext3 -L boot /dev/vda1",
+ "mkdir /mnt/boot",
+ "mount LABEL=boot /mnt/boot",
+ "udevadm settle",
+ )
+ '';
+ preBootCommands = ''
+ machine.start()
+ machine.fail("dmesg | grep 'immediate safe mode'")
+ '';
+ };
# Test a basic install using GRUB 1.
- grub1 = makeInstallerTest "grub1"
- { createPartitions =
- ''
- $machine->succeed(
- "flock /dev/sda parted --script /dev/sda -- mklabel msdos"
- . " mkpart primary linux-swap 1M 1024M"
- . " mkpart primary ext2 1024M -1s",
- "udevadm settle",
- "mkswap /dev/sda1 -L swap",
- "swapon -L swap",
- "mkfs.ext3 -L nixos /dev/sda2",
- "mount LABEL=nixos /mnt",
- "mkdir -p /mnt/tmp",
- );
- '';
- grubVersion = 1;
- grubDevice = "/dev/sda";
- };
+ grub1 = makeInstallerTest "grub1" {
+ createPartitions = ''
+ machine.succeed(
+ "flock /dev/sda parted --script /dev/sda -- mklabel msdos"
+ + " mkpart primary linux-swap 1M 1024M"
+ + " mkpart primary ext2 1024M -1s",
+ "udevadm settle",
+ "mkswap /dev/sda1 -L swap",
+ "swapon -L swap",
+ "mkfs.ext3 -L nixos /dev/sda2",
+ "mount LABEL=nixos /mnt",
+ "mkdir -p /mnt/tmp",
+ )
+ '';
+ grubVersion = 1;
+ grubDevice = "/dev/sda";
+ };
# Test using labels to identify volumes in grub
simpleLabels = makeInstallerTest "simpleLabels" {
createPartitions = ''
- $machine->succeed(
- "sgdisk -Z /dev/vda",
- "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda",
- "mkswap /dev/vda2 -L swap",
- "swapon -L swap",
- "mkfs.ext4 -L root /dev/vda3",
- "mount LABEL=root /mnt",
- );
+ machine.succeed(
+ "sgdisk -Z /dev/vda",
+ "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda",
+ "mkswap /dev/vda2 -L swap",
+ "swapon -L swap",
+ "mkfs.ext4 -L root /dev/vda3",
+ "mount LABEL=root /mnt",
+ )
'';
grubIdentifier = "label";
};
@@ -670,22 +689,23 @@ in {
# TODO: Fix udev so the symlinks are unneeded in /dev/disks
simpleProvided = makeInstallerTest "simpleProvided" {
createPartitions = ''
- my $UUID = "\$(blkid -s UUID -o value /dev/vda2)";
- $machine->succeed(
- "sgdisk -Z /dev/vda",
- "sgdisk -n 1:0:+1M -n 2:0:+100M -n 3:0:+1G -N 4 -t 1:ef02 -t 2:8300 -t 3:8200 -t 4:8300 -c 2:boot -c 4:root /dev/vda",
- "mkswap /dev/vda3 -L swap",
- "swapon -L swap",
- "mkfs.ext4 -L boot /dev/vda2",
- "mkfs.ext4 -L root /dev/vda4",
- );
- $machine->execute("ln -s ../../vda2 /dev/disk/by-uuid/$UUID");
- $machine->execute("ln -s ../../vda4 /dev/disk/by-label/root");
- $machine->succeed(
- "mount /dev/disk/by-label/root /mnt",
- "mkdir /mnt/boot",
- "mount /dev/disk/by-uuid/$UUID /mnt/boot"
- );
+ uuid = "$(blkid -s UUID -o value /dev/vda2)"
+ machine.succeed(
+ "sgdisk -Z /dev/vda",
+ "sgdisk -n 1:0:+1M -n 2:0:+100M -n 3:0:+1G -N 4 -t 1:ef02 -t 2:8300 "
+ + "-t 3:8200 -t 4:8300 -c 2:boot -c 4:root /dev/vda",
+ "mkswap /dev/vda3 -L swap",
+ "swapon -L swap",
+ "mkfs.ext4 -L boot /dev/vda2",
+ "mkfs.ext4 -L root /dev/vda4",
+ )
+ machine.execute(f"ln -s ../../vda2 /dev/disk/by-uuid/{uuid}")
+ machine.execute("ln -s ../../vda4 /dev/disk/by-label/root")
+ machine.succeed(
+ "mount /dev/disk/by-label/root /mnt",
+ "mkdir /mnt/boot",
+ f"mount /dev/disk/by-uuid/{uuid} /mnt/boot",
+ )
'';
grubIdentifier = "provided";
};
@@ -693,61 +713,62 @@ in {
# Simple btrfs grub testing
btrfsSimple = makeInstallerTest "btrfsSimple" {
createPartitions = ''
- $machine->succeed(
- "sgdisk -Z /dev/vda",
- "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda",
- "mkswap /dev/vda2 -L swap",
- "swapon -L swap",
- "mkfs.btrfs -L root /dev/vda3",
- "mount LABEL=root /mnt",
- );
+ machine.succeed(
+ "sgdisk -Z /dev/vda",
+ "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda",
+ "mkswap /dev/vda2 -L swap",
+ "swapon -L swap",
+ "mkfs.btrfs -L root /dev/vda3",
+ "mount LABEL=root /mnt",
+ )
'';
};
# Test to see if we can detect /boot and /nix on subvolumes
btrfsSubvols = makeInstallerTest "btrfsSubvols" {
createPartitions = ''
- $machine->succeed(
- "sgdisk -Z /dev/vda",
- "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda",
- "mkswap /dev/vda2 -L swap",
- "swapon -L swap",
- "mkfs.btrfs -L root /dev/vda3",
- "btrfs device scan",
- "mount LABEL=root /mnt",
- "btrfs subvol create /mnt/boot",
- "btrfs subvol create /mnt/nixos",
- "btrfs subvol create /mnt/nixos/default",
- "umount /mnt",
- "mount -o defaults,subvol=nixos/default LABEL=root /mnt",
- "mkdir /mnt/boot",
- "mount -o defaults,subvol=boot LABEL=root /mnt/boot",
- );
+ machine.succeed(
+ "sgdisk -Z /dev/vda",
+ "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda",
+ "mkswap /dev/vda2 -L swap",
+ "swapon -L swap",
+ "mkfs.btrfs -L root /dev/vda3",
+ "btrfs device scan",
+ "mount LABEL=root /mnt",
+ "btrfs subvol create /mnt/boot",
+ "btrfs subvol create /mnt/nixos",
+ "btrfs subvol create /mnt/nixos/default",
+ "umount /mnt",
+ "mount -o defaults,subvol=nixos/default LABEL=root /mnt",
+ "mkdir /mnt/boot",
+ "mount -o defaults,subvol=boot LABEL=root /mnt/boot",
+ )
'';
};
# Test to see if we can detect default and aux subvolumes correctly
btrfsSubvolDefault = makeInstallerTest "btrfsSubvolDefault" {
createPartitions = ''
- $machine->succeed(
- "sgdisk -Z /dev/vda",
- "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda",
- "mkswap /dev/vda2 -L swap",
- "swapon -L swap",
- "mkfs.btrfs -L root /dev/vda3",
- "btrfs device scan",
- "mount LABEL=root /mnt",
- "btrfs subvol create /mnt/badpath",
- "btrfs subvol create /mnt/badpath/boot",
- "btrfs subvol create /mnt/nixos",
- "btrfs subvol set-default \$(btrfs subvol list /mnt | grep 'nixos' | awk '{print \$2}') /mnt",
- "umount /mnt",
- "mount -o defaults LABEL=root /mnt",
- "mkdir -p /mnt/badpath/boot", # Help ensure the detection mechanism is actually looking up subvolumes
- "mkdir /mnt/boot",
- "mount -o defaults,subvol=badpath/boot LABEL=root /mnt/boot",
- );
+ machine.succeed(
+ "sgdisk -Z /dev/vda",
+ "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda",
+ "mkswap /dev/vda2 -L swap",
+ "swapon -L swap",
+ "mkfs.btrfs -L root /dev/vda3",
+ "btrfs device scan",
+ "mount LABEL=root /mnt",
+ "btrfs subvol create /mnt/badpath",
+ "btrfs subvol create /mnt/badpath/boot",
+ "btrfs subvol create /mnt/nixos",
+ "btrfs subvol set-default "
+ + "$(btrfs subvol list /mnt | grep 'nixos' | awk '{print \$2}') /mnt",
+ "umount /mnt",
+ "mount -o defaults LABEL=root /mnt",
+ "mkdir -p /mnt/badpath/boot", # Help ensure the detection mechanism
+ # is actually looking up subvolumes
+ "mkdir /mnt/boot",
+ "mount -o defaults,subvol=badpath/boot LABEL=root /mnt/boot",
+ )
'';
};
-
}
diff --git a/nixpkgs/nixos/tests/iodine.nix b/nixpkgs/nixos/tests/iodine.nix
new file mode 100644
index 00000000000..8bd9603a6d6
--- /dev/null
+++ b/nixpkgs/nixos/tests/iodine.nix
@@ -0,0 +1,63 @@
+import ./make-test-python.nix (
+ { pkgs, ... }: let
+ domain = "whatever.example.com";
+ in
+ {
+ name = "iodine";
+ nodes = {
+ server =
+ { ... }:
+
+ {
+ networking.firewall = {
+ allowedUDPPorts = [ 53 ];
+ trustedInterfaces = [ "dns0" ];
+ };
+ boot.kernel.sysctl = {
+ "net.ipv4.ip_forward" = 1;
+ "net.ipv6.ip_forward" = 1;
+ };
+
+ services.iodine.server = {
+ enable = true;
+ ip = "10.53.53.1/24";
+ passwordFile = "${builtins.toFile "password" "foo"}";
+ inherit domain;
+ };
+
+ # test resource: accessible only via tunnel
+ services.openssh = {
+ enable = true;
+ openFirewall = false;
+ };
+ };
+
+ client =
+ { ... }: {
+ services.iodine.clients.testClient = {
+ # test that ProtectHome is "read-only"
+ passwordFile = "/root/pw";
+ relay = "server";
+ server = domain;
+ };
+ systemd.tmpfiles.rules = [
+ "f /root/pw 0666 root root - foo"
+ ];
+ environment.systemPackages = [
+ pkgs.nagiosPluginsOfficial
+ ];
+ };
+
+ };
+
+ testScript = ''
+ start_all()
+
+ server.wait_for_unit("sshd")
+ server.wait_for_unit("iodined")
+ client.wait_for_unit("iodine-testClient")
+
+ client.succeed("check_ssh -H 10.53.53.1")
+ '';
+ }
+)
diff --git a/nixpkgs/nixos/tests/jirafeau.nix b/nixpkgs/nixos/tests/jirafeau.nix
new file mode 100644
index 00000000000..0f5af7f718a
--- /dev/null
+++ b/nixpkgs/nixos/tests/jirafeau.nix
@@ -0,0 +1,22 @@
+import ./make-test-python.nix ({ lib, ... }:
+
+with lib;
+
+{
+ name = "jirafeau";
+ meta.maintainers = with maintainers; [ davidtwco ];
+
+ nodes.machine = { pkgs, ... }: {
+ services.jirafeau = {
+ enable = true;
+ };
+ };
+
+ testScript = ''
+ machine.start()
+ machine.wait_for_unit("phpfpm-jirafeau.service")
+ machine.wait_for_unit("nginx.service")
+ machine.wait_for_open_port(80)
+ machine.succeed("curl -sSfL http://localhost/ | grep 'Jirafeau'")
+ '';
+})
diff --git a/nixpkgs/nixos/tests/keymap.nix b/nixpkgs/nixos/tests/keymap.nix
index 2b4c1ab7b05..09d5d2a6c9e 100644
--- a/nixpkgs/nixos/tests/keymap.nix
+++ b/nixpkgs/nixos/tests/keymap.nix
@@ -3,14 +3,13 @@
pkgs ? import ../.. { inherit system config; }
}:
-with import ../lib/testing.nix { inherit system pkgs; };
+with import ../lib/testing-python.nix { inherit system pkgs; };
let
readyFile = "/tmp/readerReady";
resultFile = "/tmp/readerResult";
testReader = pkgs.writeScript "test-input-reader" ''
- #!${pkgs.stdenv.shell}
rm -f ${resultFile} ${resultFile}.tmp
logger "testReader: START: Waiting for $1 characters, expecting '$2'."
touch ${readyFile}
@@ -27,56 +26,75 @@ let
'';
- mkKeyboardTest = layout: { extraConfig ? {}, tests }: with pkgs.lib; let
- combinedTests = foldAttrs (acc: val: acc ++ val) [] (builtins.attrValues tests);
- perlStr = val: "'${escape ["'" "\\"] val}'";
- lq = length combinedTests.qwerty;
- le = length combinedTests.expect;
- msg = "length mismatch between qwerty (${toString lq}) and expect (${toString le}) lists!";
- send = concatMapStringsSep ", " perlStr combinedTests.qwerty;
- expect = if (lq == le) then concatStrings combinedTests.expect else throw msg;
-
- in makeTest {
+ mkKeyboardTest = layout: { extraConfig ? {}, tests }: with pkgs.lib; makeTest {
name = "keymap-${layout}";
+ machine.console.keyMap = mkOverride 900 layout;
machine.services.xserver.desktopManager.xterm.enable = false;
- machine.i18n.consoleKeyMap = mkOverride 900 layout;
machine.services.xserver.layout = mkOverride 900 layout;
machine.imports = [ ./common/x11.nix extraConfig ];
testScript = ''
-
- sub mkTest ($$) {
- my ($desc, $cmd) = @_;
-
- subtest $desc, sub {
- # prepare and start testReader
- $machine->execute("rm -f ${readyFile} ${resultFile}");
- $machine->succeed("$cmd ${testReader} ${toString le} ".q(${escapeShellArg expect} & ));
-
- if ($desc eq "Xorg keymap") {
- # make sure the xterm window is open and has focus
- $machine->waitForWindow(qr/testterm/);
- $machine->waitUntilSucceeds("${pkgs.xdotool}/bin/xdotool search --sync --onlyvisible --class testterm windowfocus --sync");
- }
-
- # wait for reader to be ready
- $machine->waitForFile("${readyFile}");
- $machine->sleep(1);
-
- # send all keys
- foreach ((${send})) { $machine->sendKeys($_); };
-
- # wait for result and check
- $machine->waitForFile("${resultFile}");
- $machine->succeed("grep -q 'PASS:' ${resultFile}");
- };
- };
-
- $machine->waitForX;
-
- mkTest "VT keymap", "openvt -sw --";
- mkTest "Xorg keymap", "DISPLAY=:0 xterm -title testterm -class testterm -fullscreen -e";
+ import json
+ import shlex
+
+
+ def run_test_case(cmd, xorg_keymap, test_case_name, inputs, expected):
+ with subtest(test_case_name):
+ assert len(inputs) == len(expected)
+ machine.execute("rm -f ${readyFile} ${resultFile}")
+
+ # set up process that expects all the keys to be entered
+ machine.succeed(
+ "{} {} {} {} &".format(
+ cmd,
+ "${testReader}",
+ len(inputs),
+ shlex.quote("".join(expected)),
+ )
+ )
+
+ if xorg_keymap:
+ # make sure the xterm window is open and has focus
+ machine.wait_for_window("testterm")
+ machine.wait_until_succeeds(
+ "${pkgs.xdotool}/bin/xdotool search --sync --onlyvisible "
+ "--class testterm windowfocus --sync"
+ )
+
+ # wait for reader to be ready
+ machine.wait_for_file("${readyFile}")
+ machine.sleep(1)
+
+ # send all keys
+ for key in inputs:
+ machine.send_key(key)
+
+ # wait for result and check
+ machine.wait_for_file("${resultFile}")
+ machine.succeed("grep -q 'PASS:' ${resultFile}")
+
+
+ with open("${pkgs.writeText "tests.json" (builtins.toJSON tests)}") as json_file:
+ tests = json.load(json_file)
+
+ keymap_environments = {
+ "VT Keymap": "openvt -sw --",
+ "Xorg Keymap": "DISPLAY=:0 xterm -title testterm -class testterm -fullscreen -e",
+ }
+
+ machine.wait_for_x()
+
+ for keymap_env_name, command in keymap_environments.items():
+ with subtest(keymap_env_name):
+ for test_case_name, test_data in tests.items():
+ run_test_case(
+ command,
+ False,
+ test_case_name,
+ test_data["qwerty"],
+ test_data["expect"],
+ )
'';
};
@@ -89,7 +107,7 @@ in pkgs.lib.mapAttrs mkKeyboardTest {
altgr.expect = [ "~" "#" "{" "[" "|" ];
};
- extraConfig.i18n.consoleKeyMap = "azerty/fr";
+ extraConfig.console.keyMap = "azerty/fr";
extraConfig.services.xserver.layout = "fr";
};
@@ -99,7 +117,7 @@ in pkgs.lib.mapAttrs mkKeyboardTest {
homerow.expect = [ "a" "r" "s" "t" "n" "e" "i" "o" ];
};
- extraConfig.i18n.consoleKeyMap = "colemak/colemak";
+ extraConfig.console.keyMap = "colemak/colemak";
extraConfig.services.xserver.layout = "us";
extraConfig.services.xserver.xkbVariant = "colemak";
};
@@ -151,7 +169,7 @@ in pkgs.lib.mapAttrs mkKeyboardTest {
altgr.expect = [ "@" "|" "{" "[" "]" "}" ];
};
- extraConfig.i18n.consoleKeyMap = "de";
+ extraConfig.console.keyMap = "de";
extraConfig.services.xserver.layout = "de";
};
}
diff --git a/nixpkgs/nixos/tests/knot.nix b/nixpkgs/nixos/tests/knot.nix
index 0588cf86ac0..8bab917a351 100644
--- a/nixpkgs/nixos/tests/knot.nix
+++ b/nixpkgs/nixos/tests/knot.nix
@@ -28,6 +28,13 @@ let
name = "knot-zones";
paths = [ exampleZone delegatedZone ];
};
+ # DO NOT USE pkgs.writeText IN PRODUCTION. This put secrets in the nix store!
+ tsigFile = pkgs.writeText "tsig.conf" ''
+ key:
+ - id: slave_key
+ algorithm: hmac-sha256
+ secret: zOYgOgnzx3TGe5J5I/0kxd7gTcxXhLYMEq3Ek3fY37s=
+ '';
in {
name = "knot";
meta = with pkgs.stdenv.lib.maintainers; {
@@ -48,6 +55,7 @@ in {
};
services.knot.enable = true;
services.knot.extraArgs = [ "-v" ];
+ services.knot.keyFiles = [ tsigFile ];
services.knot.extraConfig = ''
server:
listen: 0.0.0.0@53
@@ -56,6 +64,7 @@ in {
acl:
- id: slave_acl
address: 192.168.0.2
+ key: slave_key
action: transfer
remote:
@@ -103,6 +112,7 @@ in {
];
};
services.knot.enable = true;
+ services.knot.keyFiles = [ tsigFile ];
services.knot.extraArgs = [ "-v" ];
services.knot.extraConfig = ''
server:
@@ -117,6 +127,7 @@ in {
remote:
- id: master
address: 192.168.0.1@53
+ key: slave_key
template:
- id: default
@@ -155,10 +166,10 @@ in {
];
};
environment.systemPackages = [ pkgs.knot-dns ];
- };
+ };
};
- testScript = { nodes, ... }: let
+ testScript = { nodes, ... }: let
master4 = (lib.head nodes.master.config.networking.interfaces.eth1.ipv4.addresses).address;
master6 = (lib.head nodes.master.config.networking.interfaces.eth1.ipv6.addresses).address;
diff --git a/nixpkgs/nixos/tests/krb5/deprecated-config.nix b/nixpkgs/nixos/tests/krb5/deprecated-config.nix
index 7d7926309c9..be6ebce9e05 100644
--- a/nixpkgs/nixos/tests/krb5/deprecated-config.nix
+++ b/nixpkgs/nixos/tests/krb5/deprecated-config.nix
@@ -1,7 +1,7 @@
# Verifies that the configuration suggested in deprecated example values
# will result in the expected output.
-import ../make-test.nix ({ pkgs, ...} : {
+import ../make-test-python.nix ({ pkgs, ...} : {
name = "krb5-with-deprecated-config";
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ eqyiel ];
@@ -43,6 +43,8 @@ import ../make-test.nix ({ pkgs, ...} : {
'';
in ''
- $machine->succeed("diff /etc/krb5.conf ${snapshot}");
+ machine.succeed(
+ "diff /etc/krb5.conf ${snapshot}"
+ )
'';
})
diff --git a/nixpkgs/nixos/tests/krb5/example-config.nix b/nixpkgs/nixos/tests/krb5/example-config.nix
index f01cf6988ee..be195b51393 100644
--- a/nixpkgs/nixos/tests/krb5/example-config.nix
+++ b/nixpkgs/nixos/tests/krb5/example-config.nix
@@ -1,7 +1,7 @@
# Verifies that the configuration suggested in (non-deprecated) example values
# will result in the expected output.
-import ../make-test.nix ({ pkgs, ...} : {
+import ../make-test-python.nix ({ pkgs, ...} : {
name = "krb5-with-example-config";
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ eqyiel ];
@@ -101,6 +101,8 @@ import ../make-test.nix ({ pkgs, ...} : {
default = SYSLOG:NOTICE
'';
in ''
- $machine->succeed("diff /etc/krb5.conf ${snapshot}");
+ machine.succeed(
+ "diff /etc/krb5.conf ${snapshot}"
+ )
'';
})
diff --git a/nixpkgs/nixos/tests/kubernetes/dns.nix b/nixpkgs/nixos/tests/kubernetes/dns.nix
index 46bcb01a526..638942e1540 100644
--- a/nixpkgs/nixos/tests/kubernetes/dns.nix
+++ b/nixpkgs/nixos/tests/kubernetes/dns.nix
@@ -3,8 +3,6 @@ with import ./base.nix { inherit system; };
let
domain = "my.zyx";
- certs = import ./certs.nix { externalDomain = domain; kubelets = [ "machine1" "machine2" ]; };
-
redisPod = pkgs.writeText "redis-pod.json" (builtins.toJSON {
kind = "Pod";
apiVersion = "v1";
diff --git a/nixpkgs/nixos/tests/lorri/default.nix b/nixpkgs/nixos/tests/lorri/default.nix
index 53074385a65..198171082d8 100644
--- a/nixpkgs/nixos/tests/lorri/default.nix
+++ b/nixpkgs/nixos/tests/lorri/default.nix
@@ -15,12 +15,12 @@ import ../make-test-python.nix {
# Start the daemon and wait until it is ready
machine.execute("lorri daemon > lorri.stdout 2> lorri.stderr &")
- machine.wait_until_succeeds("grep --fixed-strings 'lorri: ready' lorri.stdout")
+ machine.wait_until_succeeds("grep --fixed-strings 'ready' lorri.stdout")
# Ping the daemon
- machine.execute("lorri ping_ $(readlink -f shell.nix)")
+ machine.succeed("lorri internal__ping shell.nix")
# Wait for the daemon to finish the build
- machine.wait_until_succeeds("grep --fixed-strings 'OutputPaths' lorri.stdout")
+ machine.wait_until_succeeds("grep --fixed-strings 'Completed' lorri.stdout")
'';
}
diff --git a/nixpkgs/nixos/tests/matrix-synapse.nix b/nixpkgs/nixos/tests/matrix-synapse.nix
index fca53009083..f3623aa3c09 100644
--- a/nixpkgs/nixos/tests/matrix-synapse.nix
+++ b/nixpkgs/nixos/tests/matrix-synapse.nix
@@ -35,12 +35,31 @@ in {
nodes = {
# Since 0.33.0, matrix-synapse doesn't allow underscores in server names
- serverpostgres = args: {
+ serverpostgres = { pkgs, ... }: {
services.matrix-synapse = {
enable = true;
database_type = "psycopg2";
tls_certificate_path = "${cert}";
tls_private_key_path = "${key}";
+ database_args = {
+ password = "synapse";
+ };
+ };
+ services.postgresql = {
+ enable = true;
+
+ # The database name and user are configured by the following options:
+ # - services.matrix-synapse.database_name
+ # - services.matrix-synapse.database_user
+ #
+ # The values used here represent the default values of the module.
+ initialScript = pkgs.writeText "synapse-init.sql" ''
+ CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
+ CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
+ TEMPLATE template0
+ LC_COLLATE = "C"
+ LC_CTYPE = "C";
+ '';
};
};
diff --git a/nixpkgs/nixos/tests/misc.nix b/nixpkgs/nixos/tests/misc.nix
index ca28bc31cf1..17260ce6406 100644
--- a/nixpkgs/nixos/tests/misc.nix
+++ b/nixpkgs/nixos/tests/misc.nix
@@ -1,6 +1,6 @@
# Miscellaneous small tests that don't warrant their own VM run.
-import ./make-test.nix ({ pkgs, ...} : rec {
+import ./make-test-python.nix ({ pkgs, ...} : rec {
name = "misc";
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ eelco ];
@@ -34,109 +34,97 @@ import ./make-test.nix ({ pkgs, ...} : rec {
testScript =
''
- subtest "nix-db", sub {
- my $json = $machine->succeed("nix path-info --json ${foo}");
- $json =~ /"narHash":"sha256:0afw0d9j1hvwiz066z93jiddc33nxg6i6qyp26vnqyglpyfivlq5"/ or die "narHash not set";
- $json =~ /"narSize":128/ or die "narSize not set";
- };
+ import json
- subtest "nixos-version", sub {
- $machine->succeed("[ `nixos-version | wc -w` = 2 ]");
- };
- subtest "nixos-rebuild", sub {
- $machine->succeed("nixos-rebuild --help | grep 'NixOS module' ");
- };
+ def get_path_info(path):
+ result = machine.succeed(f"nix path-info --json {path}")
+ parsed = json.loads(result)
+ return parsed
- # Sanity check for uid/gid assignment.
- subtest "users-groups", sub {
- $machine->succeed("[ `id -u messagebus` = 4 ]");
- $machine->succeed("[ `id -g messagebus` = 4 ]");
- $machine->succeed("[ `getent group users` = 'users:x:100:' ]");
- };
- # Regression test for GMP aborts on QEMU.
- subtest "gmp", sub {
- $machine->succeed("expr 1 + 2");
- };
+ with subtest("nix-db"):
+ info = get_path_info("${foo}")
- # Test that the swap file got created.
- subtest "swapfile", sub {
- $machine->waitForUnit("root-swapfile.swap");
- $machine->succeed("ls -l /root/swapfile | grep 134217728");
- };
+ if (
+ info[0]["narHash"]
+ != "sha256:0afw0d9j1hvwiz066z93jiddc33nxg6i6qyp26vnqyglpyfivlq5"
+ ):
+ raise Exception("narHash not set")
- # Test whether kernel.poweroff_cmd is set.
- subtest "poweroff_cmd", sub {
- $machine->succeed("[ -x \"\$(cat /proc/sys/kernel/poweroff_cmd)\" ]")
- };
+ if info[0]["narSize"] != 128:
+ raise Exception("narSize not set")
- # Test whether the blkio controller is properly enabled.
- subtest "blkio-cgroup", sub {
- $machine->succeed("[ -n \"\$(cat /sys/fs/cgroup/blkio/blkio.sectors)\" ]")
- };
+ with subtest("nixos-version"):
+ machine.succeed("[ `nixos-version | wc -w` = 2 ]")
- # Test whether we have a reboot record in wtmp.
- subtest "reboot-wtmp", sub {
- $machine->shutdown;
- $machine->waitForUnit('multi-user.target');
- $machine->succeed("last | grep reboot >&2");
- };
+ with subtest("nixos-rebuild"):
+ assert "NixOS module" in machine.succeed("nixos-rebuild --help")
- # Test whether we can override environment variables.
- subtest "override-env-var", sub {
- $machine->succeed('[ "$EDITOR" = emacs ]');
- };
+ with subtest("Sanity check for uid/gid assignment"):
+ assert "4" == machine.succeed("id -u messagebus").strip()
+ assert "4" == machine.succeed("id -g messagebus").strip()
+ assert "users:x:100:" == machine.succeed("getent group users").strip()
- # Test whether hostname (and by extension nss_myhostname) works.
- subtest "hostname", sub {
- $machine->succeed('[ "`hostname`" = machine ]');
- #$machine->succeed('[ "`hostname -s`" = machine ]');
- };
+ with subtest("Regression test for GMP aborts on QEMU."):
+ machine.succeed("expr 1 + 2")
- # Test whether systemd-udevd automatically loads modules for our hardware.
- $machine->succeed("systemctl start systemd-udev-settle.service");
- subtest "udev-auto-load", sub {
- $machine->waitForUnit('systemd-udev-settle.service');
- $machine->succeed('lsmod | grep mousedev');
- };
+ with subtest("the swap file got created"):
+ machine.wait_for_unit("root-swapfile.swap")
+ machine.succeed("ls -l /root/swapfile | grep 134217728")
- # Test whether systemd-tmpfiles-clean works.
- subtest "tmpfiles", sub {
- $machine->succeed('touch /tmp/foo');
- $machine->succeed('systemctl start systemd-tmpfiles-clean');
- $machine->succeed('[ -e /tmp/foo ]');
- $machine->succeed('date -s "@$(($(date +%s) + 1000000))"'); # move into the future
- $machine->succeed('systemctl start systemd-tmpfiles-clean');
- $machine->fail('[ -e /tmp/foo ]');
- };
+ with subtest("whether kernel.poweroff_cmd is set"):
+ machine.succeed('[ -x "$(cat /proc/sys/kernel/poweroff_cmd)" ]')
- # Test whether automounting works.
- subtest "automount", sub {
- $machine->fail("grep '/tmp2 tmpfs' /proc/mounts");
- $machine->succeed("touch /tmp2/x");
- $machine->succeed("grep '/tmp2 tmpfs' /proc/mounts");
- };
+ with subtest("whether the blkio controller is properly enabled"):
+ machine.succeed("[ -e /sys/fs/cgroup/blkio/blkio.reset_stats ]")
- subtest "shell-vars", sub {
- $machine->succeed('[ -n "$NIX_PATH" ]');
- };
+ with subtest("whether we have a reboot record in wtmp"):
+ machine.shutdown
+ machine.wait_for_unit("multi-user.target")
+ machine.succeed("last | grep reboot >&2")
- subtest "nix-db", sub {
- $machine->succeed("nix-store -qR /run/current-system | grep nixos-");
- };
+ with subtest("whether we can override environment variables"):
+ machine.succeed('[ "$EDITOR" = emacs ]')
- # Test sysctl
- subtest "sysctl", sub {
- $machine->waitForUnit("systemd-sysctl.service");
- $machine->succeed('[ `sysctl -ne vm.swappiness` = 1 ]');
- $machine->execute('sysctl vm.swappiness=60');
- $machine->succeed('[ `sysctl -ne vm.swappiness` = 60 ]');
- };
+ with subtest("whether hostname (and by extension nss_myhostname) works"):
+ assert "machine" == machine.succeed("hostname").strip()
+ assert "machine" == machine.succeed("hostname -s").strip()
- # Test boot parameters
- subtest "bootparam", sub {
- $machine->succeed('grep -Fq vsyscall=emulate /proc/cmdline');
- };
+ with subtest("whether systemd-udevd automatically loads modules for our hardware"):
+ machine.succeed("systemctl start systemd-udev-settle.service")
+ machine.wait_for_unit("systemd-udev-settle.service")
+ assert "mousedev" in machine.succeed("lsmod")
+
+ with subtest("whether systemd-tmpfiles-clean works"):
+ machine.succeed(
+ "touch /tmp/foo", "systemctl start systemd-tmpfiles-clean", "[ -e /tmp/foo ]"
+ )
+ # move into the future
+ machine.succeed(
+ 'date -s "@$(($(date +%s) + 1000000))"',
+ "systemctl start systemd-tmpfiles-clean",
+ )
+ machine.fail("[ -e /tmp/foo ]")
+
+ with subtest("whether automounting works"):
+ machine.fail("grep '/tmp2 tmpfs' /proc/mounts")
+ machine.succeed("touch /tmp2/x")
+ machine.succeed("grep '/tmp2 tmpfs' /proc/mounts")
+
+ with subtest("shell-vars"):
+ machine.succeed('[ -n "$NIX_PATH" ]')
+
+ with subtest("nix-db"):
+ machine.succeed("nix-store -qR /run/current-system | grep nixos-")
+
+ with subtest("Test sysctl"):
+ machine.wait_for_unit("systemd-sysctl.service")
+ assert "1" == machine.succeed("sysctl -ne vm.swappiness").strip()
+ machine.execute("sysctl vm.swappiness=60")
+ assert "60" == machine.succeed("sysctl -ne vm.swappiness").strip()
+
+ with subtest("Test boot parameters"):
+ assert "vsyscall=emulate" in machine.succeed("cat /proc/cmdline")
'';
})
diff --git a/nixpkgs/nixos/tests/nesting.nix b/nixpkgs/nixos/tests/nesting.nix
index 6388b67a6e4..a75806b24ff 100644
--- a/nixpkgs/nixos/tests/nesting.nix
+++ b/nixpkgs/nixos/tests/nesting.nix
@@ -29,10 +29,10 @@ import ./make-test-python.nix {
)
clone.succeed("cowsay hey")
clone.succeed("hello")
-
- children.wait_for_unit("default.target")
- children.succeed("cowsay hey")
- children.fail("hello")
+
+ children.wait_for_unit("default.target")
+ children.succeed("cowsay hey")
+ children.fail("hello")
with subtest("Nested children do not inherit from parent"):
children.succeed(
diff --git a/nixpkgs/nixos/tests/networking.nix b/nixpkgs/nixos/tests/networking.nix
index 9448a104073..0a6507d2dc8 100644
--- a/nixpkgs/nixos/tests/networking.nix
+++ b/nixpkgs/nixos/tests/networking.nix
@@ -533,7 +533,7 @@ let
useNetworkd = networkd;
useDHCP = false;
interfaces.eth1 = {
- preferTempAddress = true;
+ tempAddress = "default";
ipv4.addresses = mkOverride 0 [ ];
ipv6.addresses = mkOverride 0 [ ];
useDHCP = true;
@@ -546,7 +546,7 @@ let
useNetworkd = networkd;
useDHCP = false;
interfaces.eth1 = {
- preferTempAddress = false;
+ tempAddress = "enabled";
ipv4.addresses = mkOverride 0 [ ];
ipv6.addresses = mkOverride 0 [ ];
useDHCP = true;
@@ -655,6 +655,31 @@ let
), "The IPv6 routing table has not been properly cleaned:\n{}".format(ipv6Residue)
'';
};
+ # even with disabled networkd, systemd.network.links should work
+ # (as it's handled by udev, not networkd)
+ link = {
+ name = "Link";
+ nodes.client = { pkgs, ... }: {
+ virtualisation.vlans = [ 1 ];
+ networking = {
+ useNetworkd = networkd;
+ useDHCP = false;
+ };
+ systemd.network.links."50-foo" = {
+ matchConfig = {
+ Name = "foo";
+ Driver = "dummy";
+ };
+ linkConfig.MTUBytes = "1442";
+ };
+ };
+ testScript = ''
+ print(client.succeed("ip l add name foo type dummy"))
+ print(client.succeed("stat /etc/systemd/network/50-foo.link"))
+ client.succeed("udevadm settle")
+ assert "mtu 1442" in client.succeed("ip l show dummy0")
+ '';
+ };
};
in mapAttrs (const (attrs: makeTest (attrs // {
diff --git a/nixpkgs/nixos/tests/nfs/simple.nix b/nixpkgs/nixos/tests/nfs/simple.nix
index a1a09ee0f45..c49ebddc2fd 100644
--- a/nixpkgs/nixos/tests/nfs/simple.nix
+++ b/nixpkgs/nixos/tests/nfs/simple.nix
@@ -5,13 +5,13 @@ let
client =
{ pkgs, ... }:
{ fileSystems = pkgs.lib.mkVMOverride
- [ { mountPoint = "/data";
- # nfs4 exports the export with fsid=0 as a virtual root directory
- device = if (version == 4) then "server:/" else "server:/data";
- fsType = "nfs";
- options = [ "vers=${toString version}" ];
- }
- ];
+ { "/data" =
+ { # nfs4 exports the export with fsid=0 as a virtual root directory
+ device = if (version == 4) then "server:/" else "server:/data";
+ fsType = "nfs";
+ options = [ "vers=${toString version}" ];
+ };
+ };
networking.firewall.enable = false; # FIXME: only open statd
};
diff --git a/nixpkgs/nixos/tests/nsd.nix b/nixpkgs/nixos/tests/nsd.nix
index c3c91e71b5c..bcc14e817a8 100644
--- a/nixpkgs/nixos/tests/nsd.nix
+++ b/nixpkgs/nixos/tests/nsd.nix
@@ -5,7 +5,7 @@ let
# for a host utility with IPv6 support
environment.systemPackages = [ pkgs.bind ];
};
-in import ./make-test.nix ({ pkgs, ...} : {
+in import ./make-test-python.nix ({ pkgs, ...} : {
name = "nsd";
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ aszlig ];
@@ -65,37 +65,35 @@ in import ./make-test.nix ({ pkgs, ...} : {
};
testScript = ''
- startAll;
+ start_all()
- $clientv4->waitForUnit("network.target");
- $clientv6->waitForUnit("network.target");
- $server->waitForUnit("nsd.service");
+ clientv4.wait_for_unit("network.target")
+ clientv6.wait_for_unit("network.target")
+ server.wait_for_unit("nsd.service")
- sub assertHost {
- my ($type, $rr, $query, $expected) = @_;
- my $self = $type eq 4 ? $clientv4 : $clientv6;
- my $out = $self->succeed("host -$type -t $rr $query");
- $self->log("output: $out");
- chomp $out;
- die "DNS IPv$type query on $query gave '$out' instead of '$expected'"
- if ($out !~ $expected);
- }
- foreach (4, 6) {
- subtest "ipv$_", sub {
- assertHost($_, "a", "example.com", qr/has no [^ ]+ record/);
- assertHost($_, "aaaa", "example.com", qr/has no [^ ]+ record/);
+ def assert_host(type, rr, query, expected):
+ self = clientv4 if type == 4 else clientv6
+ out = self.succeed(f"host -{type} -t {rr} {query}").rstrip()
+ self.log(f"output: {out}")
+ assert re.search(
+ expected, out
+ ), f"DNS IPv{type} query on {query} gave '{out}' instead of '{expected}'"
- assertHost($_, "soa", "example.com", qr/SOA.*?noc\.example\.com/);
- assertHost($_, "a", "ipv4.example.com", qr/address 1.2.3.4$/);
- assertHost($_, "aaaa", "ipv6.example.com", qr/address abcd::eeff$/);
- assertHost($_, "a", "deleg.example.com", qr/address 9.8.7.6$/);
- assertHost($_, "aaaa", "deleg.example.com", qr/address fedc::bbaa$/);
+ for ipv in 4, 6:
+ with subtest(f"IPv{ipv}"):
+ assert_host(ipv, "a", "example.com", "has no [^ ]+ record")
+ assert_host(ipv, "aaaa", "example.com", "has no [^ ]+ record")
- assertHost($_, "a", "root", qr/address 1.8.7.4$/);
- assertHost($_, "aaaa", "root", qr/address acbd::4$/);
- };
- }
+ assert_host(ipv, "soa", "example.com", "SOA.*?noc\.example\.com")
+ assert_host(ipv, "a", "ipv4.example.com", "address 1.2.3.4$")
+ assert_host(ipv, "aaaa", "ipv6.example.com", "address abcd::eeff$")
+
+ assert_host(ipv, "a", "deleg.example.com", "address 9.8.7.6$")
+ assert_host(ipv, "aaaa", "deleg.example.com", "address fedc::bbaa$")
+
+ assert_host(ipv, "a", "root", "address 1.8.7.4$")
+ assert_host(ipv, "aaaa", "root", "address acbd::4$")
'';
})
diff --git a/nixpkgs/nixos/tests/openarena.nix b/nixpkgs/nixos/tests/openarena.nix
index b315426532b..395ed9153ea 100644
--- a/nixpkgs/nixos/tests/openarena.nix
+++ b/nixpkgs/nixos/tests/openarena.nix
@@ -1,41 +1,71 @@
-import ./make-test-python.nix ({ pkgs, ...} : {
+import ./make-test-python.nix ({ pkgs, ...} :
+
+let
+ client =
+ { pkgs, ... }:
+
+ { imports = [ ./common/x11.nix ];
+ hardware.opengl.driSupport = true;
+ environment.systemPackages = [ pkgs.openarena ];
+ };
+
+in {
name = "openarena";
meta = with pkgs.stdenv.lib.maintainers; {
- maintainers = [ tomfitzhenry ];
+ maintainers = [ fpletz ];
};
- machine =
- { pkgs, ... }:
+ nodes =
+ { server =
+ { services.openarena = {
+ enable = true;
+ extraFlags = [ "+set g_gametype 0" "+map oa_dm7" "+addbot Angelyss" "+addbot Arachna" ];
+ openPorts = true;
+ };
+ };
- { imports = [];
- environment.systemPackages = with pkgs; [
- socat
- ];
- services.openarena = {
- enable = true;
- extraFlags = [
- "+set dedicated 2"
- "+set sv_hostname 'My NixOS server'"
- "+map oa_dm1"
- ];
- };
+ client1 = client;
+ client2 = client;
};
testScript =
''
- machine.wait_for_unit("openarena.service")
- machine.wait_until_succeeds("ss --numeric --udp --listening | grep -q 27960")
+ start_all()
- # The log line containing 'resolve address' is last and only message that occurs after
- # the server starts accepting clients.
- machine.wait_until_succeeds(
- "journalctl -u openarena.service | grep 'resolve address: dpmaster.deathmask.net'"
- )
+ server.wait_for_unit("openarena")
+ server.wait_until_succeeds("ss --numeric --udp --listening | grep -q 27960")
+
+ client1.wait_for_x()
+ client2.wait_for_x()
- # Check it's possible to join the server.
- # Can't use substring match instead of grep because the output is not utf-8
- machine.succeed(
- "echo -n -e '\\xff\\xff\\xff\\xffgetchallenge' | socat - UDP4-DATAGRAM:127.0.0.1:27960 | grep -q challengeResponse"
+ client1.execute("openarena +set r_fullscreen 0 +set name Foo +connect server &")
+ client2.execute("openarena +set r_fullscreen 0 +set name Bar +connect server &")
+
+ server.wait_until_succeeds(
+ "journalctl -u openarena -e | grep -q 'Foo.*entered the game'"
+ )
+ server.wait_until_succeeds(
+ "journalctl -u openarena -e | grep -q 'Bar.*entered the game'"
)
+
+ server.sleep(10) # wait for a while to get a nice screenshot
+
+ client1.screenshot("screen_client1_1")
+ client2.screenshot("screen_client2_1")
+
+ client1.block()
+
+ server.sleep(10)
+
+ client1.screenshot("screen_client1_2")
+ client2.screenshot("screen_client2_2")
+
+ client1.unblock()
+
+ server.sleep(10)
+
+ client1.screenshot("screen_client1_3")
+ client2.screenshot("screen_client2_3")
'';
+
})
diff --git a/nixpkgs/nixos/tests/opensmtpd.nix b/nixpkgs/nixos/tests/opensmtpd.nix
index e6f52db1d98..17c1a569ba0 100644
--- a/nixpkgs/nixos/tests/opensmtpd.nix
+++ b/nixpkgs/nixos/tests/opensmtpd.nix
@@ -121,5 +121,5 @@ import ./make-test-python.nix {
client.succeed("check-mail-landed >&2")
'';
- meta.timeout = 30;
+ meta.timeout = 1800;
}
diff --git a/nixpkgs/nixos/tests/openstack-image.nix b/nixpkgs/nixos/tests/openstack-image.nix
index 8a21dd1b599..97c9137fe1d 100644
--- a/nixpkgs/nixos/tests/openstack-image.nix
+++ b/nixpkgs/nixos/tests/openstack-image.nix
@@ -16,6 +16,12 @@ let
../maintainers/scripts/openstack/openstack-image.nix
../modules/testing/test-instrumentation.nix
../modules/profiles/qemu-guest.nix
+ {
+ # Needed by nixos-rebuild due to lack of network access.
+ system.extraDependencies = with pkgs; [
+ stdenv
+ ];
+ }
];
}).config.system.build.openstackImage + "/nixos.qcow2";
diff --git a/nixpkgs/nixos/tests/orangefs.nix b/nixpkgs/nixos/tests/orangefs.nix
index 46d7a6a72f8..24b7737058c 100644
--- a/nixpkgs/nixos/tests/orangefs.nix
+++ b/nixpkgs/nixos/tests/orangefs.nix
@@ -10,11 +10,11 @@ let
virtualisation.emptyDiskImages = [ 4096 ];
fileSystems = pkgs.lib.mkVMOverride
- [ { mountPoint = "/data";
- device = "/dev/disk/by-label/data";
- fsType = "ext4";
- }
- ];
+ { "/data" =
+ { device = "/dev/disk/by-label/data";
+ fsType = "ext4";
+ };
+ };
services.orangefs.server = {
enable = true;
diff --git a/nixpkgs/nixos/tests/plotinus.nix b/nixpkgs/nixos/tests/plotinus.nix
index 609afe7b214..39a4234dbf7 100644
--- a/nixpkgs/nixos/tests/plotinus.nix
+++ b/nixpkgs/nixos/tests/plotinus.nix
@@ -1,4 +1,4 @@
-import ./make-test.nix ({ pkgs, ... }: {
+import ./make-test-python.nix ({ pkgs, ... }: {
name = "plotinus";
meta = {
maintainers = pkgs.plotinus.meta.maintainers;
@@ -12,16 +12,17 @@ import ./make-test.nix ({ pkgs, ... }: {
environment.systemPackages = [ pkgs.gnome3.gnome-calculator pkgs.xdotool ];
};
- testScript =
- ''
- $machine->waitForX;
- $machine->succeed("gnome-calculator &");
- $machine->waitForWindow(qr/gnome-calculator/);
- $machine->succeed("xdotool search --sync --onlyvisible --class gnome-calculator windowfocus --sync key ctrl+shift+p");
- $machine->sleep(5); # wait for the popup
- $machine->succeed("xdotool key --delay 100 p r e f e r e n c e s Return");
- $machine->waitForWindow(qr/Preferences/);
- $machine->screenshot("screen");
- '';
-
+ testScript = ''
+ machine.wait_for_x()
+ machine.succeed("gnome-calculator &")
+ machine.wait_for_window("gnome-calculator")
+ machine.succeed(
+ "xdotool search --sync --onlyvisible --class gnome-calculator "
+ + "windowfocus --sync key --clearmodifiers --delay 1 'ctrl+shift+p'"
+ )
+ machine.sleep(5) # wait for the popup
+ machine.succeed("xdotool key --delay 100 p r e f e r e n c e s Return")
+ machine.wait_for_window("Preferences")
+ machine.screenshot("screen")
+ '';
})
diff --git a/nixpkgs/nixos/tests/postgresql-wal-receiver.nix b/nixpkgs/nixos/tests/postgresql-wal-receiver.nix
index 791b041ba95..372dd9d8c1c 100644
--- a/nixpkgs/nixos/tests/postgresql-wal-receiver.nix
+++ b/nixpkgs/nixos/tests/postgresql-wal-receiver.nix
@@ -6,17 +6,24 @@ with import ../lib/testing.nix { inherit system pkgs; };
with pkgs.lib;
let
+ makePostgresqlWalReceiverTest = subTestName: postgresqlPackage: let
+
postgresqlDataDir = "/var/db/postgresql/test";
replicationUser = "wal_receiver_user";
replicationSlot = "wal_receiver_slot";
replicationConn = "postgresql://${replicationUser}@localhost";
baseBackupDir = "/tmp/pg_basebackup";
walBackupDir = "/tmp/pg_wal";
- recoveryConf = pkgs.writeText "recovery.conf" ''
+ atLeast12 = versionAtLeast postgresqlPackage.version "12.0";
+ restoreCommand = ''
restore_command = 'cp ${walBackupDir}/%f %p'
'';
- makePostgresqlWalReceiverTest = subTestName: postgresqlPackage: makeTest {
+ recoveryFile = if atLeast12
+ then pkgs.writeTextDir "recovery.signal" ""
+ else pkgs.writeTextDir "recovery.conf" "${restoreCommand}";
+
+ in makeTest {
name = "postgresql-wal-receiver-${subTestName}";
meta.maintainers = with maintainers; [ pacien ];
@@ -29,6 +36,9 @@ let
wal_level = archive # alias for replica on pg >= 9.6
max_wal_senders = 10
max_replication_slots = 10
+ '' + optionalString atLeast12 ''
+ ${restoreCommand}
+ recovery_end_command = 'touch recovery.done'
'';
authentication = ''
host replication ${replicationUser} all trust
@@ -45,6 +55,9 @@ let
slot = replicationSlot;
directory = walBackupDir;
};
+ # This is only to speedup test, it isn't time racing. Service is set to autorestart always,
+ # default 60sec is fine for real system, but is too much for a test
+ systemd.services.postgresql-wal-receiver-main.serviceConfig.RestartSec = mkForce 5;
};
testScript = ''
@@ -70,7 +83,7 @@ let
# prepare WAL and recovery
$machine->succeed('chmod a+rX -R ${walBackupDir}');
$machine->execute('for part in ${walBackupDir}/*.partial; do mv $part ''${part%%.*}; done'); # make use of partial segments too
- $machine->succeed('cp ${recoveryConf} ${postgresqlDataDir}/recovery.conf && chmod 666 ${postgresqlDataDir}/recovery.conf');
+ $machine->succeed('cp ${recoveryFile}/* ${postgresqlDataDir}/ && chmod 666 ${postgresqlDataDir}/recovery*');
# replay WAL
$machine->systemctl('start postgresql');
diff --git a/nixpkgs/nixos/tests/predictable-interface-names.nix b/nixpkgs/nixos/tests/predictable-interface-names.nix
index 83883477a5c..bab091d57ac 100644
--- a/nixpkgs/nixos/tests/predictable-interface-names.nix
+++ b/nixpkgs/nixos/tests/predictable-interface-names.nix
@@ -17,6 +17,12 @@ in pkgs.lib.listToAttrs (pkgs.lib.crossLists (predictable: withNetworkd: {
networking.useNetworkd = withNetworkd;
networking.dhcpcd.enable = !withNetworkd;
networking.useDHCP = !withNetworkd;
+
+ # Check if predictable interface names are working in stage-1
+ boot.initrd.postDeviceCommands = ''
+ ip link
+ ip link show eth0 ${if predictable then "&&" else "||"} exit 1
+ '';
};
testScript = ''
diff --git a/nixpkgs/nixos/tests/printing.nix b/nixpkgs/nixos/tests/printing.nix
index 4d0df289cf7..355c94a0386 100644
--- a/nixpkgs/nixos/tests/printing.nix
+++ b/nixpkgs/nixos/tests/printing.nix
@@ -1,19 +1,18 @@
# Test printing via CUPS.
-import ./make-test.nix ({pkgs, ... }:
+import ./make-test-python.nix ({pkgs, ... }:
let
printingServer = startWhenNeeded: {
services.printing.enable = true;
services.printing.startWhenNeeded = startWhenNeeded;
services.printing.listenAddresses = [ "*:631" ];
services.printing.defaultShared = true;
- services.printing.extraConf =
- ''
- <Location />
- Order allow,deny
- Allow from all
- </Location>
- '';
+ services.printing.extraConf = ''
+ <Location />
+ Order allow,deny
+ Allow from all
+ </Location>
+ '';
networking.firewall.allowedTCPPorts = [ 631 ];
# Add a HP Deskjet printer connected via USB to the server.
hardware.printers.ensurePrinters = [{
@@ -34,9 +33,7 @@ let
hardware.printers.ensureDefaultPrinter = "DeskjetRemote";
};
-in
-
-{
+in {
name = "printing";
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ domenkozar eelco matthewbauer ];
@@ -50,65 +47,91 @@ in
serviceClient = { ... }: (printingClient false);
};
- testScript =
- ''
- startAll;
-
- # Make sure that cups is up on both sides.
- $serviceServer->waitForUnit("cups.service");
- $serviceClient->waitForUnit("cups.service");
- # wait until cups is fully initialized and ensure-printers has executed with 10s delay
- $serviceClient->sleep(20);
- $socketActivatedClient->waitUntilSucceeds("systemctl status ensure-printers | grep -q -E 'code=exited, status=0/SUCCESS'");
- sub testPrinting {
- my ($client, $server) = (@_);
- my $clientHostname = $client->name();
- my $serverHostname = $server->name();
- $client->succeed("lpstat -r") =~ /scheduler is running/ or die;
- # Test that UNIX socket is used for connections.
- $client->succeed("lpstat -H") =~ "/var/run/cups/cups.sock" or die;
- # Test that HTTP server is available too.
- $client->succeed("curl --fail http://localhost:631/");
- $client->succeed("curl --fail http://$serverHostname:631/");
- $server->fail("curl --fail --connect-timeout 2 http://$clientHostname:631/");
- # Do some status checks.
- $client->succeed("lpstat -a") =~ /DeskjetRemote accepting requests/ or die;
- $client->succeed("lpstat -h $serverHostname:631 -a") =~ /DeskjetLocal accepting requests/ or die;
- $client->succeed("cupsdisable DeskjetRemote");
- $client->succeed("lpq") =~ /DeskjetRemote is not ready.*no entries/s or die;
- $client->succeed("cupsenable DeskjetRemote");
- $client->succeed("lpq") =~ /DeskjetRemote is ready.*no entries/s or die;
- # Test printing various file types.
- foreach my $file ("${pkgs.groff.doc}/share/doc/*/examples/mom/penguin.pdf",
- "${pkgs.groff.doc}/share/doc/*/meref.ps",
- "${pkgs.cups.out}/share/doc/cups/images/cups.png",
- "${pkgs.pcre.doc}/share/doc/pcre/pcre.txt")
- {
- $file =~ /([^\/]*)$/; my $fn = $1;
- subtest "print $fn", sub {
- # Print the file on the client.
- $client->succeed("lp $file");
- $client->waitUntilSucceeds("lpq | grep -q -E 'active.*root.*$fn'");
- # Ensure that a raw PCL file appeared in the server's queue
- # (showing that the right filters have been applied). Of
- # course, since there is no actual USB printer attached, the
- # file will stay in the queue forever.
- $server->waitForFile("/var/spool/cups/d*-001");
- $server->waitUntilSucceeds("lpq -a | grep -q -E '$fn'");
- # Delete the job on the client. It should disappear on the
- # server as well.
- $client->succeed("lprm");
- $client->waitUntilSucceeds("lpq -a | grep -q -E 'no entries'");
- Machine::retry sub {
- return 1 if $server->succeed("lpq -a") =~ /no entries/;
- };
- # The queue is empty already, so this should be safe.
- # Otherwise, pairs of "c*"-"d*-001" files might persist.
- $server->execute("rm /var/spool/cups/*");
- };
- }
- }
- testPrinting($serviceClient, $serviceServer);
- testPrinting($socketActivatedClient, $socketActivatedServer);
+ testScript = ''
+ import os
+ import re
+ import sys
+
+ start_all()
+
+ with subtest("Make sure that cups is up on both sides"):
+ serviceServer.wait_for_unit("cups.service")
+ serviceClient.wait_for_unit("cups.service")
+
+ with subtest(
+ "Wait until cups is fully initialized and ensure-printers has "
+ "executed with 10s delay"
+ ):
+ serviceClient.sleep(20)
+ socketActivatedClient.wait_until_succeeds(
+ "systemctl status ensure-printers | grep -q -E 'code=exited, status=0/SUCCESS'"
+ )
+
+
+ def test_printing(client, server):
+ assert "scheduler is running" in client.succeed("lpstat -r")
+
+ with subtest("UNIX socket is used for connections"):
+ assert "/var/run/cups/cups.sock" in client.succeed("lpstat -H")
+ with subtest("HTTP server is available too"):
+ client.succeed("curl --fail http://localhost:631/")
+ client.succeed(f"curl --fail http://{server.name}:631/")
+ server.fail(f"curl --fail --connect-timeout 2 http://{client.name}:631/")
+
+ with subtest("LP status checks"):
+ assert "DeskjetRemote accepting requests" in client.succeed("lpstat -a")
+ assert "DeskjetLocal accepting requests" in client.succeed(
+ f"lpstat -h {server.name}:631 -a"
+ )
+ client.succeed("cupsdisable DeskjetRemote")
+ out = client.succeed("lpq")
+ print(out)
+ assert re.search(
+ "DeskjetRemote is not ready.*no entries",
+ client.succeed("lpq"),
+ flags=re.DOTALL,
+ )
+ client.succeed("cupsenable DeskjetRemote")
+ assert re.match(
+ "DeskjetRemote is ready.*no entries", client.succeed("lpq"), flags=re.DOTALL
+ )
+
+ # Test printing various file types.
+ for file in [
+ "${pkgs.groff.doc}/share/doc/*/examples/mom/penguin.pdf",
+ "${pkgs.groff.doc}/share/doc/*/meref.ps",
+ "${pkgs.cups.out}/share/doc/cups/images/cups.png",
+ "${pkgs.pcre.doc}/share/doc/pcre/pcre.txt",
+ ]:
+ file_name = os.path.basename(file)
+ with subtest(f"print {file_name}"):
+ # Print the file on the client.
+ print(client.succeed("lpq"))
+ client.succeed(f"lp {file}")
+ client.wait_until_succeeds(
+ f"lpq; lpq | grep -q -E 'active.*root.*{file_name}'"
+ )
+
+ # Ensure that a raw PCL file appeared in the server's queue
+ # (showing that the right filters have been applied). Of
+ # course, since there is no actual USB printer attached, the
+ # file will stay in the queue forever.
+ server.wait_for_file("/var/spool/cups/d*-001")
+ server.wait_until_succeeds(f"lpq -a | grep -q -E '{file_name}'")
+
+ # Delete the job on the client. It should disappear on the
+ # server as well.
+ client.succeed("lprm")
+ client.wait_until_succeeds("lpq -a | grep -q -E 'no entries'")
+
+ retry(lambda _: "no entries" in server.succeed("lpq -a"))
+
+ # The queue is empty already, so this should be safe.
+ # Otherwise, pairs of "c*"-"d*-001" files might persist.
+ server.execute("rm /var/spool/cups/*")
+
+
+ test_printing(serviceClient, serviceServer)
+ test_printing(socketActivatedClient, socketActivatedServer)
'';
})
diff --git a/nixpkgs/nixos/tests/prometheus-exporters.nix b/nixpkgs/nixos/tests/prometheus-exporters.nix
index 563f2472647..4fc3668cfaf 100644
--- a/nixpkgs/nixos/tests/prometheus-exporters.nix
+++ b/nixpkgs/nixos/tests/prometheus-exporters.nix
@@ -224,7 +224,7 @@ let
after = [ "postfix.service" ];
requires = [ "postfix.service" ];
preStart = ''
- mkdir -p 0600 mail-exporter/new
+ mkdir -p -m 0700 mail-exporter/new
'';
serviceConfig = {
ProtectHome = true;
@@ -245,6 +245,46 @@ let
'';
};
+ mikrotik = {
+ exporterConfig = {
+ enable = true;
+ extraFlags = [ "-timeout=1s" ];
+ configuration = {
+ devices = [
+ {
+ name = "router";
+ address = "192.168.42.48";
+ user = "prometheus";
+ password = "shh";
+ }
+ ];
+ features = {
+ bgp = true;
+ dhcp = true;
+ dhcpl = true;
+ dhcpv6 = true;
+ health = true;
+ routes = true;
+ poe = true;
+ pools = true;
+ optics = true;
+ w60g = true;
+ wlansta = true;
+ wlanif = true;
+ monitor = true;
+ ipsec = true;
+ };
+ };
+ };
+ exporterTest = ''
+ wait_for_unit("prometheus-mikrotik-exporter.service")
+ wait_for_open_port(9436)
+ succeed(
+ "curl -sSf http://localhost:9436/metrics | grep -q 'mikrotik_scrape_collector_success{device=\"router\"} 0'"
+ )
+ '';
+ };
+
nextcloud = {
exporterConfig = {
enable = true;
@@ -287,7 +327,7 @@ let
services.nginx = {
enable = true;
statusPage = true;
- virtualHosts."/".extraConfig = "return 204;";
+ virtualHosts."test".extraConfig = "return 204;";
};
};
exporterTest = ''
@@ -363,6 +403,7 @@ let
};
metricProvider = {
services.rspamd.enable = true;
+ virtualisation.memorySize = 1024;
};
exporterTest = ''
wait_for_unit("rspamd.service")
diff --git a/nixpkgs/nixos/tests/restic.nix b/nixpkgs/nixos/tests/restic.nix
new file mode 100644
index 00000000000..67bb7f1933d
--- /dev/null
+++ b/nixpkgs/nixos/tests/restic.nix
@@ -0,0 +1,63 @@
+import ./make-test-python.nix (
+ { pkgs, ... }:
+
+ let
+ password = "some_password";
+ repository = "/tmp/restic-backup";
+ passwordFile = pkgs.writeText "password" "correcthorsebatterystaple";
+ in
+ {
+ name = "restic";
+
+ meta = with pkgs.stdenv.lib.maintainers; {
+ maintainers = [ bbigras ];
+ };
+
+ nodes = {
+ server =
+ { ... }:
+ {
+ 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"
+ ];
+ };
+ };
+ };
+ };
+
+ testScript = ''
+ server.start()
+ server.wait_for_unit("dbus.socket")
+ server.fail(
+ "${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots"
+ )
+ server.succeed(
+ "mkdir -p /opt",
+ "touch /opt/some_file",
+ "timedatectl set-time '2016-12-13 13:45'",
+ "systemctl start restic-backups-remotebackup.service",
+ '${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots -c | grep -e "^1 snapshot"',
+ "timedatectl set-time '2017-12-13 13:45'",
+ "systemctl start restic-backups-remotebackup.service",
+ "timedatectl set-time '2018-12-13 13:45'",
+ "systemctl start restic-backups-remotebackup.service",
+ "timedatectl set-time '2018-12-14 13:45'",
+ "systemctl start restic-backups-remotebackup.service",
+ "timedatectl set-time '2018-12-15 13:45'",
+ "systemctl start restic-backups-remotebackup.service",
+ "timedatectl set-time '2018-12-16 13:45'",
+ "systemctl start restic-backups-remotebackup.service",
+ '${pkgs.restic}/bin/restic -r ${repository} -p ${passwordFile} snapshots -c | grep -e "^4 snapshot"',
+ )
+ '';
+ }
+)
diff --git a/nixpkgs/nixos/tests/rsyslogd.nix b/nixpkgs/nixos/tests/rsyslogd.nix
index f17e61814c5..50523920c60 100644
--- a/nixpkgs/nixos/tests/rsyslogd.nix
+++ b/nixpkgs/nixos/tests/rsyslogd.nix
@@ -3,40 +3,38 @@
pkgs ? import ../.. { inherit system config; }
}:
-with import ../lib/testing.nix { inherit system pkgs; };
+with import ../lib/testing-python.nix { inherit system pkgs; };
with pkgs.lib;
{
test1 = makeTest {
name = "rsyslogd-test1";
- meta.maintainers = [ maintainers.aanderse ];
+ meta.maintainers = [ pkgs.stdenv.lib.maintainers.aanderse ];
- machine =
- { config, pkgs, ... }:
- { services.rsyslogd.enable = true;
- services.journald.forwardToSyslog = false;
- };
+ machine = { config, pkgs, ... }: {
+ services.rsyslogd.enable = true;
+ services.journald.forwardToSyslog = false;
+ };
# ensure rsyslogd isn't receiving messages from journald if explicitly disabled
testScript = ''
- $machine->waitForUnit("default.target");
- $machine->fail("test -f /var/log/messages");
+ machine.wait_for_unit("default.target")
+ machine.fail("test -f /var/log/messages")
'';
};
test2 = makeTest {
name = "rsyslogd-test2";
- meta.maintainers = [ maintainers.aanderse ];
+ meta.maintainers = [ pkgs.stdenv.lib.maintainers.aanderse ];
- machine =
- { config, pkgs, ... }:
- { services.rsyslogd.enable = true;
- };
+ machine = { config, pkgs, ... }: {
+ services.rsyslogd.enable = true;
+ };
# ensure rsyslogd is receiving messages from journald
testScript = ''
- $machine->waitForUnit("default.target");
- $machine->succeed("test -f /var/log/messages");
+ machine.wait_for_unit("default.target")
+ machine.succeed("test -f /var/log/messages")
'';
};
}
diff --git a/nixpkgs/nixos/tests/run-in-machine.nix b/nixpkgs/nixos/tests/run-in-machine.nix
index 339a4b9a740..67840f3e9fe 100644
--- a/nixpkgs/nixos/tests/run-in-machine.nix
+++ b/nixpkgs/nixos/tests/run-in-machine.nix
@@ -3,7 +3,7 @@
pkgs ? import ../.. { inherit system config; }
}:
-with import ../lib/testing.nix { inherit system pkgs; };
+with import ../lib/testing-python.nix { inherit system pkgs; };
let
output = runInMachine {
diff --git a/nixpkgs/nixos/tests/sanoid.nix b/nixpkgs/nixos/tests/sanoid.nix
new file mode 100644
index 00000000000..284b38932cc
--- /dev/null
+++ b/nixpkgs/nixos/tests/sanoid.nix
@@ -0,0 +1,90 @@
+import ./make-test-python.nix ({ pkgs, ... }: let
+ inherit (import ./ssh-keys.nix pkgs)
+ snakeOilPrivateKey snakeOilPublicKey;
+
+ commonConfig = { pkgs, ... }: {
+ virtualisation.emptyDiskImages = [ 2048 ];
+ boot.supportedFilesystems = [ "zfs" ];
+ environment.systemPackages = [ pkgs.parted ];
+ };
+in {
+ name = "sanoid";
+ meta = with pkgs.stdenv.lib.maintainers; {
+ maintainers = [ lopsided98 ];
+ };
+
+ nodes = {
+ source = { ... }: {
+ imports = [ commonConfig ];
+ networking.hostId = "daa82e91";
+
+ programs.ssh.extraConfig = ''
+ UserKnownHostsFile=/dev/null
+ StrictHostKeyChecking=no
+ '';
+
+ services.sanoid = {
+ enable = true;
+ templates.test = {
+ hourly = 12;
+ daily = 1;
+ monthly = 1;
+ yearly = 1;
+
+ autosnap = true;
+ };
+ datasets."pool/test".useTemplate = [ "test" ];
+ };
+
+ services.syncoid = {
+ enable = true;
+ sshKey = "/root/.ssh/id_ecdsa";
+ commonArgs = [ "--no-sync-snap" ];
+ commands."pool/test".target = "root@target:pool/test";
+ };
+ };
+ target = { ... }: {
+ imports = [ commonConfig ];
+ networking.hostId = "dcf39d36";
+
+ services.openssh.enable = true;
+ users.users.root.openssh.authorizedKeys.keys = [ snakeOilPublicKey ];
+ };
+ };
+
+ testScript = ''
+ source.succeed(
+ "mkdir /tmp/mnt",
+ "parted --script /dev/vdb -- mklabel msdos mkpart primary 1024M -1s",
+ "udevadm settle",
+ "zpool create pool /dev/vdb1",
+ "zfs create -o mountpoint=legacy pool/test",
+ "mount -t zfs pool/test /tmp/mnt",
+ "udevadm settle",
+ )
+ target.succeed(
+ "parted --script /dev/vdb -- mklabel msdos mkpart primary 1024M -1s",
+ "udevadm settle",
+ "zpool create pool /dev/vdb1",
+ "udevadm settle",
+ )
+
+ source.succeed("mkdir -m 700 /root/.ssh")
+ source.succeed(
+ "cat '${snakeOilPrivateKey}' > /root/.ssh/id_ecdsa"
+ )
+ source.succeed("chmod 600 /root/.ssh/id_ecdsa")
+
+ source.succeed("touch /tmp/mnt/test.txt")
+ source.systemctl("start --wait sanoid.service")
+
+ target.wait_for_open_port(22)
+ source.systemctl("start --wait syncoid.service")
+ target.succeed(
+ "mkdir /tmp/mnt",
+ "zfs set mountpoint=legacy pool/test",
+ "mount -t zfs pool/test /tmp/mnt",
+ )
+ target.succeed("cat /tmp/mnt/test.txt")
+ '';
+})
diff --git a/nixpkgs/nixos/tests/service-runner.nix b/nixpkgs/nixos/tests/service-runner.nix
new file mode 100644
index 00000000000..adb3fcd36d7
--- /dev/null
+++ b/nixpkgs/nixos/tests/service-runner.nix
@@ -0,0 +1,36 @@
+import ./make-test-python.nix ({ pkgs, ... }: {
+ name = "service-runner";
+ meta = with pkgs.stdenv.lib.maintainers; {
+ maintainers = [ roberth ];
+ };
+
+ nodes = {
+ machine = { pkgs, lib, ... }: {
+ services.nginx.enable = true;
+ services.nginx.virtualHosts.machine.root = pkgs.runCommand "webroot" {} ''
+ mkdir $out
+ echo 'yay' >$out/index.html
+ '';
+ systemd.services.nginx.enable = false;
+ };
+
+ };
+
+ testScript = { nodes, ... }: ''
+ url = "http://localhost/index.html"
+
+ with subtest("check systemd.services.nginx.runner"):
+ machine.fail(f"curl {url}")
+ machine.succeed(
+ """
+ mkdir -p /run/nginx /var/spool/nginx/logs
+ ${nodes.machine.config.systemd.services.nginx.runner} &
+ echo $!>my-nginx.pid
+ """
+ )
+ machine.wait_for_open_port(80)
+ machine.succeed(f"curl {url}")
+ machine.succeed("kill -INT $(cat my-nginx.pid)")
+ machine.wait_for_closed_port(80)
+ '';
+})
diff --git a/nixpkgs/nixos/tests/signal-desktop.nix b/nixpkgs/nixos/tests/signal-desktop.nix
index ae141fe116d..e4b830e9e23 100644
--- a/nixpkgs/nixos/tests/signal-desktop.nix
+++ b/nixpkgs/nixos/tests/signal-desktop.nix
@@ -17,6 +17,7 @@ import ./make-test-python.nix ({ pkgs, ...} :
services.xserver.enable = true;
test-support.displayManager.auto.user = "alice";
environment.systemPackages = [ pkgs.signal-desktop ];
+ virtualisation.memorySize = 1024;
};
enableOCR = true;
diff --git a/nixpkgs/nixos/tests/solr.nix b/nixpkgs/nixos/tests/solr.nix
index 23e1a960fb3..dc5770e16bc 100644
--- a/nixpkgs/nixos/tests/solr.nix
+++ b/nixpkgs/nixos/tests/solr.nix
@@ -1,4 +1,4 @@
-import ./make-test.nix ({ pkgs, ... }:
+import ./make-test-python.nix ({ pkgs, ... }:
{
name = "solr";
@@ -21,28 +21,36 @@ import ./make-test.nix ({ pkgs, ... }:
};
testScript = ''
- startAll;
+ start_all()
- $machine->waitForUnit('solr.service');
- $machine->waitForOpenPort('8983');
- $machine->succeed('curl --fail http://localhost:8983/solr/');
+ machine.wait_for_unit("solr.service")
+ machine.wait_for_open_port(8983)
+ machine.succeed("curl --fail http://localhost:8983/solr/")
# adapted from pkgs.solr/examples/films/README.txt
- $machine->succeed('sudo -u solr solr create -c films');
- $machine->succeed(q(curl http://localhost:8983/solr/films/schema -X POST -H 'Content-type:application/json' --data-binary '{
- "add-field" : {
- "name":"name",
- "type":"text_general",
- "multiValued":false,
- "stored":true
- },
- "add-field" : {
- "name":"initial_release_date",
- "type":"pdate",
- "stored":true
- }
- }')) =~ /"status":0/ or die;
- $machine->succeed('sudo -u solr post -c films ${pkgs.solr}/example/films/films.json');
- $machine->succeed('curl http://localhost:8983/solr/films/query?q=name:batman') =~ /"name":"Batman Begins"/ or die;
+ machine.succeed("sudo -u solr solr create -c films")
+ assert '"status":0' in machine.succeed(
+ """
+ curl http://localhost:8983/solr/films/schema -X POST -H 'Content-type:application/json' --data-binary '{
+ "add-field" : {
+ "name":"name",
+ "type":"text_general",
+ "multiValued":false,
+ "stored":true
+ },
+ "add-field" : {
+ "name":"initial_release_date",
+ "type":"pdate",
+ "stored":true
+ }
+ }'
+ """
+ )
+ machine.succeed(
+ "sudo -u solr post -c films ${pkgs.solr}/example/films/films.json"
+ )
+ assert '"name":"Batman Begins"' in machine.succeed(
+ "curl http://localhost:8983/solr/films/query?q=name:batman"
+ )
'';
})
diff --git a/nixpkgs/nixos/tests/sympa.nix b/nixpkgs/nixos/tests/sympa.nix
new file mode 100644
index 00000000000..280691f7cb4
--- /dev/null
+++ b/nixpkgs/nixos/tests/sympa.nix
@@ -0,0 +1,36 @@
+import ./make-test-python.nix ({ pkgs, lib, ... }: {
+ name = "sympa";
+ meta.maintainers = with lib.maintainers; [ mmilata ];
+
+ machine =
+ { ... }:
+ {
+ virtualisation.memorySize = 1024;
+
+ services.sympa = {
+ enable = true;
+ domains = {
+ "lists.example.org" = {
+ webHost = "localhost";
+ };
+ };
+ listMasters = [ "joe@example.org" ];
+ web.enable = true;
+ web.https = false;
+ database = {
+ type = "PostgreSQL";
+ createLocally = true;
+ };
+ };
+ };
+
+ testScript = ''
+ start_all()
+
+ machine.wait_for_unit("sympa.service")
+ machine.wait_for_unit("wwsympa.service")
+ assert "Mailing lists service" in machine.succeed(
+ "curl --insecure -L http://localhost/"
+ )
+ '';
+})
diff --git a/nixpkgs/nixos/tests/systemd-networkd-vrf.nix b/nixpkgs/nixos/tests/systemd-networkd-vrf.nix
new file mode 100644
index 00000000000..af7813a2e60
--- /dev/null
+++ b/nixpkgs/nixos/tests/systemd-networkd-vrf.nix
@@ -0,0 +1,221 @@
+import ./make-test-python.nix ({ pkgs, lib, ... }: let
+ inherit (import ./ssh-keys.nix pkgs) snakeOilPrivateKey snakeOilPublicKey;
+in {
+ name = "systemd-networkd-vrf";
+ meta.maintainers = with lib.maintainers; [ ma27 ];
+
+ nodes = {
+ client = { pkgs, ... }: {
+ virtualisation.vlans = [ 1 2 ];
+
+ networking = {
+ useDHCP = false;
+ useNetworkd = true;
+ firewall.checkReversePath = "loose";
+ };
+
+ systemd.network = {
+ enable = true;
+
+ netdevs."10-vrf1" = {
+ netdevConfig = {
+ Kind = "vrf";
+ Name = "vrf1";
+ MTUBytes = "1300";
+ };
+ vrfConfig.Table = 23;
+ };
+ netdevs."10-vrf2" = {
+ netdevConfig = {
+ Kind = "vrf";
+ Name = "vrf2";
+ MTUBytes = "1300";
+ };
+ vrfConfig.Table = 42;
+ };
+
+ networks."10-vrf1" = {
+ matchConfig.Name = "vrf1";
+ networkConfig.IPForward = "yes";
+ routes = [
+ { routeConfig = { Destination = "192.168.1.2"; Metric = "100"; }; }
+ ];
+ };
+ networks."10-vrf2" = {
+ matchConfig.Name = "vrf2";
+ networkConfig.IPForward = "yes";
+ routes = [
+ { routeConfig = { Destination = "192.168.2.3"; Metric = "100"; }; }
+ ];
+ };
+
+ networks."10-eth1" = {
+ matchConfig.Name = "eth1";
+ linkConfig.RequiredForOnline = "no";
+ networkConfig = {
+ VRF = "vrf1";
+ Address = "192.168.1.1";
+ IPForward = "yes";
+ };
+ };
+ networks."10-eth2" = {
+ matchConfig.Name = "eth2";
+ linkConfig.RequiredForOnline = "no";
+ networkConfig = {
+ VRF = "vrf2";
+ Address = "192.168.2.1";
+ IPForward = "yes";
+ };
+ };
+ };
+ };
+
+ node1 = { pkgs, ... }: {
+ virtualisation.vlans = [ 1 ];
+ networking = {
+ useDHCP = false;
+ useNetworkd = true;
+ };
+
+ services.openssh.enable = true;
+ users.users.root.openssh.authorizedKeys.keys = [ snakeOilPublicKey ];
+
+ systemd.network = {
+ enable = true;
+
+ networks."10-eth1" = {
+ matchConfig.Name = "eth1";
+ linkConfig.RequiredForOnline = "no";
+ networkConfig = {
+ Address = "192.168.1.2";
+ IPForward = "yes";
+ };
+ };
+ };
+ };
+
+ node2 = { pkgs, ... }: {
+ virtualisation.vlans = [ 2 ];
+ networking = {
+ useDHCP = false;
+ useNetworkd = true;
+ };
+
+ systemd.network = {
+ enable = true;
+
+ networks."10-eth2" = {
+ matchConfig.Name = "eth2";
+ linkConfig.RequiredForOnline = "no";
+ networkConfig = {
+ Address = "192.168.2.3";
+ IPForward = "yes";
+ };
+ };
+ };
+ };
+
+ node3 = { pkgs, ... }: {
+ virtualisation.vlans = [ 2 ];
+ networking = {
+ useDHCP = false;
+ useNetworkd = true;
+ };
+
+ systemd.network = {
+ enable = true;
+
+ networks."10-eth2" = {
+ matchConfig.Name = "eth2";
+ linkConfig.RequiredForOnline = "no";
+ networkConfig = {
+ Address = "192.168.2.4";
+ IPForward = "yes";
+ };
+ };
+ };
+ };
+ };
+
+ testScript = ''
+ def compare_tables(expected, actual):
+ assert (
+ expected == actual
+ ), """
+ Routing tables don't match!
+ Expected:
+ {}
+ Actual:
+ {}
+ """.format(
+ expected, actual
+ )
+
+
+ start_all()
+
+ client.wait_for_unit("network.target")
+ node1.wait_for_unit("network.target")
+ node2.wait_for_unit("network.target")
+ node3.wait_for_unit("network.target")
+
+ client_ipv4_table = """
+ 192.168.1.2 dev vrf1 proto static metric 100
+ 192.168.2.3 dev vrf2 proto static metric 100
+ """.strip()
+ vrf1_table = """
+ broadcast 192.168.1.0 dev eth1 proto kernel scope link src 192.168.1.1
+ 192.168.1.0/24 dev eth1 proto kernel scope link src 192.168.1.1
+ local 192.168.1.1 dev eth1 proto kernel scope host src 192.168.1.1
+ broadcast 192.168.1.255 dev eth1 proto kernel scope link src 192.168.1.1
+ """.strip()
+ vrf2_table = """
+ broadcast 192.168.2.0 dev eth2 proto kernel scope link src 192.168.2.1
+ 192.168.2.0/24 dev eth2 proto kernel scope link src 192.168.2.1
+ local 192.168.2.1 dev eth2 proto kernel scope host src 192.168.2.1
+ broadcast 192.168.2.255 dev eth2 proto kernel scope link src 192.168.2.1
+ """.strip()
+
+ # Check that networkd properly configures the main routing table
+ # and the routing tables for the VRF.
+ with subtest("check vrf routing tables"):
+ compare_tables(
+ client_ipv4_table, client.succeed("ip -4 route list | head -n2").strip()
+ )
+ compare_tables(
+ vrf1_table, client.succeed("ip -4 route list table 23 | head -n4").strip()
+ )
+ compare_tables(
+ vrf2_table, client.succeed("ip -4 route list table 42 | head -n4").strip()
+ )
+
+ # Ensure that other nodes are reachable via ICMP through the VRF.
+ with subtest("icmp through vrf works"):
+ 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"
+ # )
+
+ # Only configured routes through the VRF from the main routing table should
+ # work. Additional IPs are only reachable when binding to the vrf interface.
+ with subtest("only routes from main routing table work by default"):
+ client.fail("ping -c5 192.168.2.4")
+ client.succeed("ping -I vrf2 -c5 192.168.2.4")
+
+ client.shutdown()
+ node1.shutdown()
+ node2.shutdown()
+ node3.shutdown()
+ '';
+})
diff --git a/nixpkgs/nixos/tests/systemd-networkd-wireguard.nix b/nixpkgs/nixos/tests/systemd-networkd.nix
index be5c0da981d..319e5e94ece 100644
--- a/nixpkgs/nixos/tests/systemd-networkd-wireguard.nix
+++ b/nixpkgs/nixos/tests/systemd-networkd.nix
@@ -41,15 +41,25 @@ let generateNodeConf = { lib, pkgs, config, privk, pubk, peerId, nodeId, ...}: {
{ routeConfig = { Gateway = "10.0.0.${nodeId}"; Destination = "10.0.0.0/24"; }; }
];
};
- "90-eth1" = {
+ "30-eth1" = {
matchConfig = { Name = "eth1"; };
- address = [ "192.168.1.${nodeId}/24" ];
+ address = [
+ "192.168.1.${nodeId}/24"
+ "fe80::${nodeId}/64"
+ ];
+ routingPolicyRules = [
+ { routingPolicyRuleConfig = { Table = 10; IncomingInterface = "eth1"; Family = "both"; };}
+ { routingPolicyRuleConfig = { Table = 20; OutgoingInterface = "eth1"; };}
+ { routingPolicyRuleConfig = { Table = 30; From = "192.168.1.1"; To = "192.168.1.2"; SourcePort = 666 ; DestinationPort = 667; };}
+ { routingPolicyRuleConfig = { Table = 40; IPProtocol = "tcp"; InvertRule = true; };}
+ { routingPolicyRuleConfig = { Table = 50; IncomingInterface = "eth1"; Family = "ipv4"; };}
+ ];
};
};
};
};
in import ./make-test-python.nix ({pkgs, ... }: {
- name = "networkd-wireguard";
+ name = "networkd";
meta = with pkgs.stdenv.lib.maintainers; {
maintainers = [ ninjatrappeur ];
};
@@ -76,9 +86,28 @@ testScript = ''
start_all()
node1.wait_for_unit("systemd-networkd-wait-online.service")
node2.wait_for_unit("systemd-networkd-wait-online.service")
+
+ # ================================
+ # Wireguard
+ # ================================
node1.succeed("ping -c 5 10.0.0.2")
node2.succeed("ping -c 5 10.0.0.1")
# Is the fwmark set?
node2.succeed("wg | grep -q 42")
+
+ # ================================
+ # Routing Policies
+ # ================================
+ # Testing all the routingPolicyRuleConfig members:
+ # Table + IncomingInterface
+ node1.succeed("sudo ip rule | grep 'from all iif eth1 lookup 10'")
+ # OutgoingInterface
+ node1.succeed("sudo ip rule | grep 'from all oif eth1 lookup 20'")
+ # From + To + SourcePort + DestinationPort
+ node1.succeed(
+ "sudo ip rule | grep 'from 192.168.1.1 to 192.168.1.2 sport 666 dport 667 lookup 30'"
+ )
+ # IPProtocol + InvertRule
+ node1.succeed("sudo ip rule | grep 'not from all ipproto tcp lookup 40'")
'';
})
diff --git a/nixpkgs/nixos/tests/tinydns.nix b/nixpkgs/nixos/tests/tinydns.nix
index c7740d5ade3..b80e3451700 100644
--- a/nixpkgs/nixos/tests/tinydns.nix
+++ b/nixpkgs/nixos/tests/tinydns.nix
@@ -21,6 +21,6 @@ import ./make-test-python.nix ({ lib, ...} : {
testScript = ''
nameserver.start()
nameserver.wait_for_unit("tinydns.service")
- nameserver.succeed("host bla.foo.bar | grep '1\.2\.3\.4'")
+ nameserver.succeed("host bla.foo.bar 192.168.1.1 | grep '1\.2\.3\.4'")
'';
})
diff --git a/nixpkgs/nixos/tests/zfs.nix b/nixpkgs/nixos/tests/zfs.nix
index 8f844aca416..7ba60ee9806 100644
--- a/nixpkgs/nixos/tests/zfs.nix
+++ b/nixpkgs/nixos/tests/zfs.nix
@@ -3,12 +3,10 @@
pkgs ? import ../.. { inherit system config; }
}:
-with import ../lib/testing.nix { inherit system pkgs; };
+with import ../lib/testing-python.nix { inherit system pkgs; };
let
- makeTest = import ./make-test-python.nix;
-
makeZfsTest = name:
{ kernelPackage ? pkgs.linuxPackages_latest
, enableUnstable ? false
@@ -20,41 +18,33 @@ let
maintainers = [ adisbladis ];
};
- machine = { pkgs, ... }:
- {
- virtualisation.emptyDiskImages = [ 4096 ];
- networking.hostId = "deadbeef";
- boot.kernelPackages = kernelPackage;
- boot.supportedFilesystems = [ "zfs" ];
- boot.zfs.enableUnstable = enableUnstable;
+ machine = { pkgs, ... }: {
+ virtualisation.emptyDiskImages = [ 4096 ];
+ networking.hostId = "deadbeef";
+ boot.kernelPackages = kernelPackage;
+ boot.supportedFilesystems = [ "zfs" ];
+ boot.zfs.enableUnstable = enableUnstable;
- environment.systemPackages = with pkgs; [
- parted
- ];
- };
+ environment.systemPackages = [ pkgs.parted ];
+ };
testScript = ''
- machine.succeed("modprobe zfs")
- machine.succeed("zpool status")
-
- machine.succeed("ls /dev")
-
machine.succeed(
- "mkdir /tmp/mnt",
-
- "udevadm settle",
- "parted --script /dev/vdb mklabel msdos",
- "parted --script /dev/vdb -- mkpart primary 1024M -1s",
- "udevadm settle",
-
- "zpool create rpool /dev/vdb1",
- "zfs create -o mountpoint=legacy rpool/root",
- "mount -t zfs rpool/root /tmp/mnt",
- "udevadm settle",
-
- "umount /tmp/mnt",
- "zpool destroy rpool",
- "udevadm settle"
+ "modprobe zfs",
+ "zpool status",
+ "ls /dev",
+ "mkdir /tmp/mnt",
+ "udevadm settle",
+ "parted --script /dev/vdb mklabel msdos",
+ "parted --script /dev/vdb -- mkpart primary 1024M -1s",
+ "udevadm settle",
+ "zpool create rpool /dev/vdb1",
+ "zfs create -o mountpoint=legacy rpool/root",
+ "mount -t zfs rpool/root /tmp/mnt",
+ "udevadm settle",
+ "umount /tmp/mnt",
+ "zpool destroy rpool",
+ "udevadm settle",
)
'' + extraTest;
@@ -69,18 +59,17 @@ in {
enableUnstable = true;
extraTest = ''
machine.succeed(
- "echo password | zpool create -o altroot=\"/tmp/mnt\" -O encryption=aes-256-gcm -O keyformat=passphrase rpool /dev/vdb1",
- "zfs create -o mountpoint=legacy rpool/root",
- "mount -t zfs rpool/root /tmp/mnt",
- "udevadm settle",
-
- "umount /tmp/mnt",
- "zpool destroy rpool",
- "udevadm settle"
+ 'echo password | zpool create -o altroot="/tmp/mnt" '
+ + "-O encryption=aes-256-gcm -O keyformat=passphrase rpool /dev/vdb1",
+ "zfs create -o mountpoint=legacy rpool/root",
+ "mount -t zfs rpool/root /tmp/mnt",
+ "udevadm settle",
+ "umount /tmp/mnt",
+ "zpool destroy rpool",
+ "udevadm settle",
)
'';
};
installer = (import ./installer.nix { }).zfsroot;
-
}