diff options
Diffstat (limited to 'nixos')
68 files changed, 1227 insertions, 334 deletions
diff --git a/nixos/doc/manual/administration/declarative-containers.section.md b/nixos/doc/manual/administration/declarative-containers.section.md index 0d9d4017ed81b..00fd244bb91fb 100644 --- a/nixos/doc/manual/administration/declarative-containers.section.md +++ b/nixos/doc/manual/administration/declarative-containers.section.md @@ -40,7 +40,7 @@ section for details on container networking.) To disable the container, just remove it from `configuration.nix` and run `nixos-rebuild switch`. Note that this will not delete the root directory of the -container in `/var/lib/containers`. Containers can be destroyed using +container in `/var/lib/nixos-containers`. Containers can be destroyed using the imperative method: `nixos-container destroy foo`. Declarative containers can be started and stopped using the diff --git a/nixos/doc/manual/administration/imperative-containers.section.md b/nixos/doc/manual/administration/imperative-containers.section.md index 05196bf5d819e..f45991780c4b9 100644 --- a/nixos/doc/manual/administration/imperative-containers.section.md +++ b/nixos/doc/manual/administration/imperative-containers.section.md @@ -10,8 +10,8 @@ You create a container with identifier `foo` as follows: # nixos-container create foo ``` -This creates the container's root directory in `/var/lib/containers/foo` -and a small configuration file in `/etc/containers/foo.conf`. It also +This creates the container's root directory in `/var/lib/nixos-containers/foo` +and a small configuration file in `/etc/nixos-containers/foo.conf`. It also builds the container's initial system configuration and stores it in `/nix/var/nix/profiles/per-container/foo/system`. You can modify the initial configuration of the container on the command line. For diff --git a/nixos/doc/manual/from_md/administration/declarative-containers.section.xml b/nixos/doc/manual/from_md/administration/declarative-containers.section.xml index 7b35520d567bf..b8179dca1f8bd 100644 --- a/nixos/doc/manual/from_md/administration/declarative-containers.section.xml +++ b/nixos/doc/manual/from_md/administration/declarative-containers.section.xml @@ -48,8 +48,8 @@ containers.database = { <literal>configuration.nix</literal> and run <literal>nixos-rebuild switch</literal>. Note that this will not delete the root directory of the container in - <literal>/var/lib/containers</literal>. Containers can be destroyed - using the imperative method: + <literal>/var/lib/nixos-containers</literal>. Containers can be + destroyed using the imperative method: <literal>nixos-container destroy foo</literal>. </para> <para> diff --git a/nixos/doc/manual/from_md/administration/imperative-containers.section.xml b/nixos/doc/manual/from_md/administration/imperative-containers.section.xml index 59ecfdee5af08..865fc46893981 100644 --- a/nixos/doc/manual/from_md/administration/imperative-containers.section.xml +++ b/nixos/doc/manual/from_md/administration/imperative-containers.section.xml @@ -14,8 +14,9 @@ </programlisting> <para> This creates the container’s root directory in - <literal>/var/lib/containers/foo</literal> and a small configuration - file in <literal>/etc/containers/foo.conf</literal>. It also builds + <literal>/var/lib/nixos-containers/foo</literal> and a small + configuration file in + <literal>/etc/nixos-containers/foo.conf</literal>. It also builds the container’s initial system configuration and stores it in <literal>/nix/var/nix/profiles/per-container/foo/system</literal>. You can modify the initial configuration of the container on the diff --git a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml index 05b3822cab713..10608685c4718 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml @@ -75,6 +75,22 @@ </listitem> <listitem> <para> + Pulseaudio has been upgraded to version 15.0 and now + optionally + <link xlink:href="https://www.freedesktop.org/wiki/Software/PulseAudio/Notes/15.0/#supportforldacandaptxbluetoothcodecsplussbcxqsbcwithhigher-qualityparameters">supports + additional Bluetooth audio codecs</link> like aptX or LDAC, + with codec switching support being available in + <literal>pavucontrol</literal>. This feature is disabled by + default but can be enabled by using + <literal>hardware.pulseaudio.package = pkgs.pulseaudioFull;</literal>. + Existing 3rd party modules that provided similar + functionality, like <literal>pulseaudio-modules-bt</literal> + or <literal>pulseaudio-hsphfpd</literal> are deprecated and + have been removed. + </para> + </listitem> + <listitem> + <para> The new <link xlink:href="https://nixos.org/manual/nixpkgs/stable/#sec-postgresqlTestHook"><literal>postgresqlTestHook</literal></link> runs a PostgreSQL server for the duration of package checks. @@ -473,6 +489,28 @@ </listitem> <listitem> <para> + The configuration and state directories used by + <literal>nixos-containers</literal> have been moved from + <literal>/etc/containers</literal> and + <literal>/var/lib/containers</literal> to + <literal>/etc/nixos-containers</literal> and + <literal>/var/lib/nixos-containers</literal>. + </para> + <para> + If you are changing <literal>system.stateVersion</literal> to + <literal>"22.05"</literal> manually on an existing + system you are responsible for migrating these directories + yourself. + </para> + <para> + This is to improve compatibility with + <literal>libcontainer</literal> based software such as Podman + and Skopeo which assumes they have ownership over + <literal>/etc/containers</literal>. + </para> + </listitem> + <listitem> + <para> <literal>security.klogd</literal> was removed. Logging of kernel messages is handled by systemd since Linux 3.5. </para> @@ -1266,7 +1304,7 @@ <literal>systemd-shutdown</literal> is now properly linked on shutdown to unmount all filesystems and device mapper devices cleanly. This can be disabled using - <literal>boot.systemd.shutdown.enable</literal>. + <literal>systemd.shutdownRamfs.enable</literal>. </para> </listitem> <listitem> @@ -1334,6 +1372,16 @@ </listitem> <listitem> <para> + <literal>services.zookeeper</literal> has a new option + <literal>jre</literal> for specifying the JRE to start + zookeeper with. It defaults to the JRE that + <literal>pkgs.zookeeper</literal> was wrapped with, instead of + <literal>pkgs.jre</literal>. This changes the JRE to + <literal>pkgs.jdk11_headless</literal> by default. + </para> + </listitem> + <listitem> + <para> <literal>pkgs.pgadmin</literal> now refers to <literal>pkgs.pgadmin4</literal>. <literal>pgadmin3</literal> has been removed. diff --git a/nixos/doc/manual/release-notes/rl-2205.section.md b/nixos/doc/manual/release-notes/rl-2205.section.md index 16c59ce3dddb1..3b118d4e03d2c 100644 --- a/nixos/doc/manual/release-notes/rl-2205.section.md +++ b/nixos/doc/manual/release-notes/rl-2205.section.md @@ -27,6 +27,9 @@ In addition to numerous new and upgraded packages, this release has the followin - Systemd has been upgraded to the version 250. +- Pulseaudio has been upgraded to version 15.0 and now optionally [supports additional Bluetooth audio codecs](https://www.freedesktop.org/wiki/Software/PulseAudio/Notes/15.0/#supportforldacandaptxbluetoothcodecsplussbcxqsbcwithhigher-qualityparameters) like aptX or LDAC, with codec switching support being available in `pavucontrol`. This feature is disabled by default but can be enabled by using `hardware.pulseaudio.package = pkgs.pulseaudioFull;`. + Existing 3rd party modules that provided similar functionality, like `pulseaudio-modules-bt` or `pulseaudio-hsphfpd` are deprecated and have been removed. + - The new [`postgresqlTestHook`](https://nixos.org/manual/nixpkgs/stable/#sec-postgresqlTestHook) runs a PostgreSQL server for the duration of package checks. - [`kops`](https://kops.sigs.k8s.io) defaults to 1.22.4, which will enable [Instance Metadata Service Version 2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html) and require tokens on new clusters with Kubernetes 1.22. This will increase security by default, but may break some types of workloads. See the [release notes](https://kops.sigs.k8s.io/releases/1.22-notes/) for details. @@ -151,6 +154,16 @@ In addition to numerous new and upgraded packages, this release has the followin org-contrib, refer to the ones in `pkgs.emacsPackages.elpaPackages` and `pkgs.emacsPackages.nongnuPackages` where the new versions will release. +- The configuration and state directories used by `nixos-containers` have been + moved from `/etc/containers` and `/var/lib/containers` to + `/etc/nixos-containers` and `/var/lib/nixos-containers`. + + If you are changing `system.stateVersion` to `"22.05"` manually on an existing + system you are responsible for migrating these directories yourself. + + This is to improve compatibility with `libcontainer` based software such as Podman and Skopeo + which assumes they have ownership over `/etc/containers`. + - `security.klogd` was removed. Logging of kernel messages is handled by systemd since Linux 3.5. @@ -500,7 +513,7 @@ In addition to numerous new and upgraded packages, this release has the followin - `systemd-nspawn@.service` settings have been reverted to the default systemd behaviour. User namespaces are now activated by default. If you want to keep running nspawn containers without user namespaces you need to set `systemd.nspawn.<name>.execConfig.PrivateUsers = false` -- `systemd-shutdown` is now properly linked on shutdown to unmount all filesystems and device mapper devices cleanly. This can be disabled using `boot.systemd.shutdown.enable`. +- `systemd-shutdown` is now properly linked on shutdown to unmount all filesystems and device mapper devices cleanly. This can be disabled using `systemd.shutdownRamfs.enable`. - The Tor SOCKS proxy is now actually disabled if `services.tor.client.enable` is set to `false` (the default). If you are using this functionality but didn't change the setting or set it to `false`, you now need to set it to `true`. @@ -528,6 +541,10 @@ In addition to numerous new and upgraded packages, this release has the followin you should change the package you refer to. If you don't need them update your commands from `otelcontribcol` to `otelcorecol` and enjoy a 7x smaller binary. +- `services.zookeeper` has a new option `jre` for specifying the JRE to start + zookeeper with. It defaults to the JRE that `pkgs.zookeeper` was wrapped with, + instead of `pkgs.jre`. This changes the JRE to `pkgs.jdk11_headless` by default. + - `pkgs.pgadmin` now refers to `pkgs.pgadmin4`. `pgadmin3` has been removed. - `pkgs.noto-fonts-cjk` is now deprecated in favor of `pkgs.noto-fonts-cjk-sans` diff --git a/nixos/lib/systemd-types.nix b/nixos/lib/systemd-types.nix index 71962fab2e177..961b6d7f98514 100644 --- a/nixos/lib/systemd-types.nix +++ b/nixos/lib/systemd-types.nix @@ -1,4 +1,4 @@ -{ lib, systemdUtils }: +{ lib, systemdUtils, pkgs }: with systemdUtils.lib; with systemdUtils.unitOptions; @@ -34,4 +34,36 @@ rec { automounts = with types; listOf (submodule [ stage2AutomountOptions unitConfig automountConfig ]); initrdAutomounts = with types; attrsOf (submodule [ stage1AutomountOptions unitConfig automountConfig ]); + + initrdContents = types.attrsOf (types.submodule ({ config, options, name, ... }: { + options = { + enable = mkEnableOption "copying of this file and symlinking it" // { default = true; }; + + target = mkOption { + type = types.path; + description = '' + Path of the symlink. + ''; + default = name; + }; + + text = mkOption { + default = null; + type = types.nullOr types.lines; + description = "Text of the file."; + }; + + source = mkOption { + type = types.path; + description = "Path of the source file."; + }; + }; + + config = { + source = mkIf (config.text != null) ( + let name' = "initrd-" + baseNameOf name; + in mkDerivedConfig options.text (pkgs.writeText name') + ); + }; + })); } diff --git a/nixos/lib/utils.nix b/nixos/lib/utils.nix index 497d98aa4d195..d7671a374999a 100644 --- a/nixos/lib/utils.nix +++ b/nixos/lib/utils.nix @@ -213,6 +213,6 @@ rec { systemdUtils = { lib = import ./systemd-lib.nix { inherit lib config pkgs; }; unitOptions = import ./systemd-unit-options.nix { inherit lib systemdUtils; }; - types = import ./systemd-types.nix { inherit lib systemdUtils; }; + types = import ./systemd-types.nix { inherit lib systemdUtils pkgs; }; }; } diff --git a/nixos/modules/config/console.nix b/nixos/modules/config/console.nix index 5b07901f99011..b60fc55851daf 100644 --- a/nixos/modules/config/console.nix +++ b/nixos/modules/config/console.nix @@ -149,8 +149,11 @@ in ''); boot.initrd.systemd.contents = { - "/etc/kbd".source = "${consoleEnv config.boot.initrd.systemd.package.kbd}/share"; "/etc/vconsole.conf".source = vconsoleConf; + # Add everything if we want full console setup... + "/etc/kbd" = lib.mkIf cfg.earlySetup { source = "${consoleEnv config.boot.initrd.systemd.package.kbd}/share"; }; + # ...but only the keymaps if we don't + "/etc/kbd/keymaps" = lib.mkIf (!cfg.earlySetup) { source = "${consoleEnv config.boot.initrd.systemd.package.kbd}/share/keymaps"; }; }; boot.initrd.systemd.storePaths = [ "${config.boot.initrd.systemd.package}/lib/systemd/systemd-vconsole-setup" @@ -180,7 +183,7 @@ in ]; }) - (mkIf cfg.earlySetup { + (mkIf (cfg.earlySetup && !config.boot.initrd.systemd.enable) { boot.initrd.extraUtilsCommands = '' mkdir -p $out/share/consolefonts ${if substring 0 1 cfg.font == "/" then '' @@ -194,10 +197,6 @@ in cp -L $font $out/share/consolefonts/font.psf fi ''; - assertions = [{ - assertion = !config.boot.initrd.systemd.enable; - message = "console.earlySetup is implied by systemd stage 1"; - }]; }) ])) ]; diff --git a/nixos/modules/hardware/all-firmware.nix b/nixos/modules/hardware/all-firmware.nix index 5b60b17312f9e..176056d0a917a 100644 --- a/nixos/modules/hardware/all-firmware.nix +++ b/nixos/modules/hardware/all-firmware.nix @@ -27,7 +27,8 @@ in { }; hardware.enableRedistributableFirmware = mkOption { - default = false; + default = config.hardware.enableAllFirmware; + defaultText = lib.literalExpression "config.hardware.enableAllFirmware"; type = types.bool; description = '' Turn on this option if you want to enable all the firmware with a license allowing redistribution. @@ -84,7 +85,10 @@ in { b43Firmware_6_30_163_46 b43FirmwareCutter xow_dongle-firmware - ] ++ optional pkgs.stdenv.hostPlatform.isx86 facetimehd-firmware; + ] ++ optionals pkgs.stdenv.hostPlatform.isx86 [ + facetimehd-calibration + facetimehd-firmware + ]; }) (mkIf cfg.wirelessRegulatoryDatabase { hardware.firmware = [ pkgs.wireless-regdb ]; diff --git a/nixos/modules/hardware/raid/hpsa.nix b/nixos/modules/hardware/raid/hpsa.nix index c4977e3fd70aa..fa6f0b8fc84a3 100644 --- a/nixos/modules/hardware/raid/hpsa.nix +++ b/nixos/modules/hardware/raid/hpsa.nix @@ -8,7 +8,10 @@ let version = "2.40-13.0"; src = pkgs.fetchurl { - url = "https://downloads.linux.hpe.com/SDR/downloads/MCP/Ubuntu/pool/non-free/${pname}-${version}_amd64.deb"; + urls = [ + "https://downloads.linux.hpe.com/SDR/downloads/MCP/Ubuntu/pool/non-free/${pname}-${version}_amd64.deb" + "http://apt.netangels.net/pool/main/h/hpssacli/${pname}-${version}_amd64.deb" + ]; sha256 = "11w7fwk93lmfw0yya4jpjwdmgjimqxx6412sqa166g1pz4jil4sw"; }; diff --git a/nixos/modules/hardware/video/nvidia.nix b/nixos/modules/hardware/video/nvidia.nix index 6899eb4e196aa..210d45ac84153 100644 --- a/nixos/modules/hardware/video/nvidia.nix +++ b/nixos/modules/hardware/video/nvidia.nix @@ -361,11 +361,12 @@ in services.udev.extraRules = '' # Create /dev/nvidia-uvm when the nvidia-uvm module is loaded. - KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidiactl c $$(grep nvidia-frontend /proc/devices | cut -d \ -f 1) 255'" - KERNEL=="nvidia_modeset", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-modeset c $$(grep nvidia-frontend /proc/devices | cut -d \ -f 1) 254'" - KERNEL=="card*", SUBSYSTEM=="drm", DRIVERS=="nvidia", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia%n c $$(grep nvidia-frontend /proc/devices | cut -d \ -f 1) %n'" + KERNEL=="nvidia", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidiactl c 195 255'" + KERNEL=="nvidia_modeset", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-modeset c 195 254'" + KERNEL=="card*", SUBSYSTEM=="drm", DRIVERS=="nvidia", PROGRAM="${pkgs.gnugrep}/bin/grep 'Device Minor:' /proc/driver/nvidia/gpus/%b/information", \ + RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia%c{3} c 195 %c{3}" KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm c $$(grep nvidia-uvm /proc/devices | cut -d \ -f 1) 0'" - KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm-tools c $$(grep nvidia-uvm /proc/devices | cut -d \ -f 1) 0'" + KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm-tools c $$(grep nvidia-uvm /proc/devices | cut -d \ -f 1) 1'" '' + optionalString cfg.powerManagement.finegrained '' # Remove NVIDIA USB xHCI Host Controller devices, if present ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c0330", ATTR{remove}="1" diff --git a/nixos/modules/hardware/video/webcam/facetimehd.nix b/nixos/modules/hardware/video/webcam/facetimehd.nix index b13f103350e9d..c48eac5e9c116 100644 --- a/nixos/modules/hardware/video/webcam/facetimehd.nix +++ b/nixos/modules/hardware/video/webcam/facetimehd.nix @@ -14,6 +14,18 @@ in options.hardware.facetimehd.enable = mkEnableOption "facetimehd kernel module"; + options.hardware.facetimehd.withCalibration = mkOption { + default = false; + example = true; + type = types.bool; + description = '' + Whether to include sensor calibration files for facetimehd. + This makes colors look much better but is experimental, see + <link xlink:href="https://github.com/patjak/facetimehd/wiki/Extracting-the-sensor-calibration-files"/> + for details. + ''; + }; + config = mkIf cfg.enable { boot.kernelModules = [ "facetimehd" ]; @@ -22,7 +34,8 @@ in boot.extraModulePackages = [ kernelPackages.facetimehd ]; - hardware.firmware = [ pkgs.facetimehd-firmware ]; + hardware.firmware = [ pkgs.facetimehd-firmware ] + ++ optional cfg.withCalibration pkgs.facetimehd-calibration; # unload module during suspend/hibernate as it crashes the whole system powerManagement.powerDownCommands = '' diff --git a/nixos/modules/installer/cd-dvd/channel.nix b/nixos/modules/installer/cd-dvd/channel.nix index 92164d65e5335..2f91cd39881d8 100644 --- a/nixos/modules/installer/cd-dvd/channel.nix +++ b/nixos/modules/installer/cd-dvd/channel.nix @@ -39,7 +39,8 @@ in echo "unpacking the NixOS/Nixpkgs sources..." mkdir -p /nix/var/nix/profiles/per-user/root ${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/per-user/root/channels \ - -i ${channelSources} --quiet --option build-use-substitutes false + -i ${channelSources} --quiet --option build-use-substitutes false \ + ${optionalString config.boot.initrd.systemd.enable "--option sandbox false"} # There's an issue with pivot_root mkdir -m 0700 -p /root/.nix-defexpr ln -s /nix/var/nix/profiles/per-user/root/channels /root/.nix-defexpr/channels mkdir -m 0755 -p /var/lib/nixos diff --git a/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix b/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix index 458e313a3f751..329bd329dc15f 100644 --- a/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix +++ b/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix @@ -87,19 +87,19 @@ in boot.initrd.availableKernelModules = [ "mvsdio" "reiserfs" "ext3" "ums-cypress" "rtc_mv" "ext4" ]; - boot.postBootCommands = + boot.postBootCommands = lib.mkIf (!boot.initrd.systemd.enable) '' mkdir -p /mnt cp ${dummyConfiguration} /etc/nixos/configuration.nix ''; - boot.initrd.extraUtilsCommands = + boot.initrd.extraUtilsCommands = lib.mkIf (!boot.initrd.systemd.enable) '' copy_bin_and_libs ${pkgs.util-linux}/sbin/hwclock ''; - boot.initrd.postDeviceCommands = + boot.initrd.postDeviceCommands = lib.mkIf (!boot.initrd.systemd.enable) '' hwclock -s ''; diff --git a/nixos/modules/installer/kexec/kexec-boot.nix b/nixos/modules/installer/kexec/kexec-boot.nix index 95ab774468c19..2d062214efc21 100644 --- a/nixos/modules/installer/kexec/kexec-boot.nix +++ b/nixos/modules/installer/kexec/kexec-boot.nix @@ -40,7 +40,7 @@ } { name = "bzImage"; - path = "${config.system.build.kernel}/bzImage"; + path = "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}"; } { name = "kexec-boot"; diff --git a/nixos/modules/installer/sd-card/sd-image-aarch64.nix b/nixos/modules/installer/sd-card/sd-image-aarch64.nix index 321793882f4cb..cf01005fdc8a9 100644 --- a/nixos/modules/installer/sd-card/sd-image-aarch64.nix +++ b/nixos/modules/installer/sd-card/sd-image-aarch64.nix @@ -39,6 +39,12 @@ # Supported in newer board revisions arm_boost=1 + [cm4] + # Enable host mode on the 2711 built-in XHCI USB controller. + # This line should be removed if the legacy DWC2 controller is required + # (e.g. for USB device mode) or if USB support is not required. + otg_mode=1 + [all] # Boot in 64-bit mode. arm_64bit=1 @@ -65,6 +71,9 @@ cp ${pkgs.ubootRaspberryPi4_64bit}/u-boot.bin firmware/u-boot-rpi4.bin cp ${pkgs.raspberrypi-armstubs}/armstub8-gic.bin firmware/armstub8-gic.bin cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2711-rpi-4-b.dtb firmware/ + cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2711-rpi-400.dtb firmware/ + cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2711-rpi-cm4.dtb firmware/ + cp ${pkgs.raspberrypifw}/share/raspberrypi/boot/bcm2711-rpi-cm4s.dtb firmware/ ''; populateRootCommands = '' mkdir -p ./files/boot diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index dcd9bb8aff1d0..d1cda0d84e96b 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -172,6 +172,7 @@ ./programs/java.nix ./programs/k40-whisperer.nix ./programs/kclock.nix + ./programs/k3b.nix ./programs/kdeconnect.nix ./programs/kbdlight.nix ./programs/less.nix @@ -662,6 +663,7 @@ ./services/monitoring/longview.nix ./services/monitoring/mackerel-agent.nix ./services/monitoring/metricbeat.nix + ./services/monitoring/mimir.nix ./services/monitoring/monit.nix ./services/monitoring/munin.nix ./services/monitoring/nagios.nix @@ -735,6 +737,7 @@ ./services/networking/blocky.nix ./services/networking/charybdis.nix ./services/networking/cjdns.nix + ./services/networking/cloudflare-dyndns.nix ./services/networking/cntlm.nix ./services/networking/connman.nix ./services/networking/consul.nix @@ -1182,13 +1185,14 @@ ./system/boot/stage-2.nix ./system/boot/systemd.nix ./system/boot/systemd/coredump.nix + ./system/boot/systemd/initrd-secrets.nix + ./system/boot/systemd/initrd.nix ./system/boot/systemd/journald.nix ./system/boot/systemd/logind.nix ./system/boot/systemd/nspawn.nix ./system/boot/systemd/shutdown.nix ./system/boot/systemd/tmpfiles.nix ./system/boot/systemd/user.nix - ./system/boot/systemd/initrd.nix ./system/boot/timesyncd.nix ./system/boot/tmp.nix ./system/etc/etc-activation.nix diff --git a/nixos/modules/profiles/all-hardware.nix b/nixos/modules/profiles/all-hardware.nix index 25f68123a1da9..8347453d403b4 100644 --- a/nixos/modules/profiles/all-hardware.nix +++ b/nixos/modules/profiles/all-hardware.nix @@ -40,6 +40,9 @@ in # SD cards. "sdhci_pci" + # NVMe drives + "nvme" + # Firewire support. Not tested. "ohci1394" "sbp2" diff --git a/nixos/modules/profiles/installation-device.nix b/nixos/modules/profiles/installation-device.nix index 3c503fba2a390..a8601a9e2c067 100644 --- a/nixos/modules/profiles/installation-device.nix +++ b/nixos/modules/profiles/installation-device.nix @@ -99,6 +99,10 @@ with lib; stdenvNoCC # for runCommand busybox jq # for closureInfo + # For boot.initrd.systemd + makeInitrdNGTool + systemdStage1 + systemdStage1Network ]; # Show all debug messages from the kernel but don't log refused packets diff --git a/nixos/modules/profiles/qemu-guest.nix b/nixos/modules/profiles/qemu-guest.nix index d4335edfcf2d3..8b3df97ae0db9 100644 --- a/nixos/modules/profiles/qemu-guest.nix +++ b/nixos/modules/profiles/qemu-guest.nix @@ -1,13 +1,13 @@ # Common configuration for virtual machines running under QEMU (using # virtio). -{ ... }: +{ config, lib, ... }: { boot.initrd.availableKernelModules = [ "virtio_net" "virtio_pci" "virtio_mmio" "virtio_blk" "virtio_scsi" "9p" "9pnet_virtio" ]; boot.initrd.kernelModules = [ "virtio_balloon" "virtio_console" "virtio_rng" ]; - boot.initrd.postDeviceCommands = + boot.initrd.postDeviceCommands = lib.mkIf (!config.boot.initrd.systemd.enable) '' # Set the system time from the hardware clock to work around a # bug in qemu-kvm > 1.5.2 (where the VM clock is initialised diff --git a/nixos/modules/programs/k3b.nix b/nixos/modules/programs/k3b.nix new file mode 100644 index 0000000000000..68a4d08f349c2 --- /dev/null +++ b/nixos/modules/programs/k3b.nix @@ -0,0 +1,52 @@ +{ config, pkgs, lib, ... }: + +with lib; + +{ + # interface + options.programs.k3b = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable k3b, the KDE disk burning application. + + Additionally to installing <package>k3b</package> enabling this will + add <literal>setuid</literal> wrappers in <literal>/run/wrappers/bin</literal> + for both <package>cdrdao</package> and <package>cdrecord</package>. On first + run you must manually configure the path of <package>cdrdae</package> and + <package>cdrecord</package> to correspond to the appropriate paths under + <literal>/run/wrappers/bin</literal> in the "Setup External Programs" menu. + ''; + }; + }; + + # implementation + config = mkIf config.programs.k3b.enable { + + environment.systemPackages = with pkgs; [ + k3b + dvdplusrwtools + cdrdao + cdrkit + ]; + + security.wrappers = { + cdrdao = { + setuid = true; + owner = "root"; + group = "cdrom"; + permissions = "u+wrx,g+x"; + source = "${pkgs.cdrdao}/bin/cdrdao"; + }; + cdrecord = { + setuid = true; + owner = "root"; + group = "cdrom"; + permissions = "u+wrx,g+x"; + source = "${pkgs.cdrkit}/bin/cdrecord"; + }; + }; + + }; +} diff --git a/nixos/modules/services/continuous-integration/gitlab-runner.nix b/nixos/modules/services/continuous-integration/gitlab-runner.nix index dc58c63452392..85ac0fb2a8907 100644 --- a/nixos/modules/services/continuous-integration/gitlab-runner.nix +++ b/nixos/modules/services/continuous-integration/gitlab-runner.nix @@ -36,12 +36,12 @@ let # register new services ${concatStringsSep "\n" (mapAttrsToList (name: service: '' - if echo "$NEW_SERVICES" | grep -xq ${name}; then + if echo "$NEW_SERVICES" | grep -xq "${name}"; then bash -c ${escapeShellArg (concatStringsSep " \\\n " ([ "set -a && source ${service.registrationConfigFile} &&" "gitlab-runner register" "--non-interactive" - "--name ${name}" + (if service.description != null then "--description \"${service.description}\"" else "--name '${name}'") "--executor ${service.executor}" "--limit ${toString service.limit}" "--request-concurrency ${toString service.requestConcurrency}" @@ -365,6 +365,13 @@ in with <literal>RUNNER_ENV</literal> variable set. ''; }; + description = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Name/description of the runner. + ''; + }; executor = mkOption { type = types.str; default = "docker"; diff --git a/nixos/modules/services/databases/couchdb.nix b/nixos/modules/services/databases/couchdb.nix index 742e605d224db..39d1ead28fc0c 100644 --- a/nixos/modules/services/databases/couchdb.nix +++ b/nixos/modules/services/databases/couchdb.nix @@ -193,6 +193,11 @@ in { preStart = '' touch ${cfg.configFile} + if ! test -e ${cfg.databaseDir}/.erlang.cookie; then + touch ${cfg.databaseDir}/.erlang.cookie + chmod 600 ${cfg.databaseDir}/.erlang.cookie + dd if=/dev/random bs=16 count=1 | base64 > ${cfg.databaseDir}/.erlang.cookie + fi ''; environment = { @@ -204,6 +209,7 @@ in { ERL_FLAGS= ''-couch_ini ${cfg.package}/etc/default.ini ${configFile} ${pkgs.writeText "couchdb-extra.ini" cfg.extraConfig} ${cfg.configFile}''; # 5. the vm.args file COUCHDB_ARGS_FILE=''${cfg.argsFile}''; + HOME =''${cfg.databaseDir}''; }; serviceConfig = { diff --git a/nixos/modules/services/misc/sourcehut/default.nix b/nixos/modules/services/misc/sourcehut/default.nix index 21551d7d5f033..5a6d011a729a3 100644 --- a/nixos/modules/services/misc/sourcehut/default.nix +++ b/nixos/modules/services/misc/sourcehut/default.nix @@ -1018,7 +1018,7 @@ in inherit configIniOfService; mainService = mkMerge [ baseService { serviceConfig.StateDirectory = [ "sourcehut/gitsrht" "sourcehut/gitsrht/repos" ]; - preStart = mkIf (!versionAtLeast config.system.stateVersion "22.05") (mkBefore '' + preStart = mkIf (versionOlder config.system.stateVersion "22.05") (mkBefore '' # Fix Git hooks of repositories pre-dating https://github.com/NixOS/nixpkgs/pull/133984 ( set +f diff --git a/nixos/modules/services/misc/zookeeper.nix b/nixos/modules/services/misc/zookeeper.nix index 3809a93a61e18..fefbf9a86de49 100644 --- a/nixos/modules/services/misc/zookeeper.nix +++ b/nixos/modules/services/misc/zookeeper.nix @@ -114,6 +114,13 @@ in { type = types.package; }; + jre = mkOption { + description = "The JRE with which to run Zookeeper"; + default = cfg.package.jre; + defaultText = literalExpression "pkgs.zookeeper.jre"; + example = literalExpression "pkgs.jre"; + type = types.package; + }; }; @@ -131,7 +138,7 @@ in { after = [ "network.target" ]; serviceConfig = { ExecStart = '' - ${pkgs.jre}/bin/java \ + ${cfg.jre}/bin/java \ -cp "${cfg.package}/lib/*:${configDir}" \ ${escapeShellArgs cfg.extraCmdLineOptions} \ -Dzookeeper.datadir.autocreate=false \ diff --git a/nixos/modules/services/monitoring/mimir.nix b/nixos/modules/services/monitoring/mimir.nix new file mode 100644 index 0000000000000..df853f037ee6a --- /dev/null +++ b/nixos/modules/services/monitoring/mimir.nix @@ -0,0 +1,63 @@ +{ config, lib, pkgs, ... }: + +let + inherit (lib) escapeShellArgs mkEnableOption mkIf mkOption types; + + cfg = config.services.mimir; + + settingsFormat = pkgs.formats.yaml {}; +in { + options.services.mimir = { + enable = mkEnableOption "mimir"; + + configuration = mkOption { + type = (pkgs.formats.json {}).type; + default = {}; + description = '' + Specify the configuration for Mimir in Nix. + ''; + }; + + configFile = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + Specify a configuration file that Mimir should use. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [{ + assertion = ( + (cfg.configuration == {} -> cfg.configFile != null) && + (cfg.configFile != null -> cfg.configuration == {}) + ); + message = '' + Please specify either + 'services.mimir.configuration' or + 'services.mimir.configFile'. + ''; + }]; + + systemd.services.mimir = { + description = "mimir Service Daemon"; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = let + conf = if cfg.configFile == null + then settingsFormat.generate "config.yaml" cfg.configuration + else cfg.configFile; + in + { + ExecStart = "${pkgs.grafana-mimir}/bin/mimir --config.file=${conf}"; + DynamicUser = true; + Restart = "always"; + ProtectSystem = "full"; + DevicePolicy = "closed"; + NoNewPrivileges = true; + StateDirectory = "mimir"; + }; + }; + }; +} diff --git a/nixos/modules/services/networking/asterisk.nix b/nixos/modules/services/networking/asterisk.nix index af091d55c01b8..297d0b3b2d02b 100644 --- a/nixos/modules/services/networking/asterisk.nix +++ b/nixos/modules/services/networking/asterisk.nix @@ -14,28 +14,9 @@ let # Add filecontents from files of useTheseDefaultConfFiles to confFiles, do not override defaultConfFiles = subtractLists (attrNames cfg.confFiles) cfg.useTheseDefaultConfFiles; - allConfFiles = - cfg.confFiles // - builtins.listToAttrs (map (x: { name = x; - value = builtins.readFile (cfg.package + "/etc/asterisk/" + x); }) - defaultConfFiles); - - asteriskEtc = pkgs.stdenv.mkDerivation - ((mapAttrs' (name: value: nameValuePair - # Fudge the names to make bash happy - ((replaceChars ["."] ["_"] name) + "_") - (value) - ) allConfFiles) // - { - confFilesString = concatStringsSep " " ( - attrNames allConfFiles - ); - - name = "asterisk-etc"; - + allConfFiles = { # Default asterisk.conf file - # (Notice that astetcdir will be set to the path of this derivation) - asteriskConf = '' + "asterisk.conf".text = '' [directories] astetcdir => /etc/asterisk astmoddir => ${cfg.package}/lib/asterisk/modules @@ -48,43 +29,28 @@ let astrundir => /run/asterisk astlogdir => /var/log/asterisk astsbindir => ${cfg.package}/sbin + ${cfg.extraConfig} ''; - extraConf = cfg.extraConfig; # Loading all modules by default is considered sensible by the authors of # "Asterisk: The Definitive Guide". Secure sites will likely want to # specify their own "modules.conf" in the confFiles option. - modulesConf = '' + "modules.conf".text = '' [modules] autoload=yes ''; # Use syslog for logging so logs can be viewed with journalctl - loggerConf = '' + "logger.conf".text = '' [general] [logfiles] syslog.local0 => notice,warning,error ''; + } // + mapAttrs (name: text: { inherit text; }) cfg.confFiles // + listToAttrs (map (x: nameValuePair x { source = cfg.package + "/etc/asterisk/" + x; }) defaultConfFiles); - buildCommand = '' - mkdir -p "$out" - - # Create asterisk.conf, pointing astetcdir to the path of this derivation - echo "$asteriskConf" | sed "s|@out@|$out|g" > "$out"/asterisk.conf - echo "$extraConf" >> "$out"/asterisk.conf - - echo "$modulesConf" > "$out"/modules.conf - - echo "$loggerConf" > "$out"/logger.conf - - # Config files specified in confFiles option override all other files - for i in $confFilesString; do - conf=$(echo "$i"_ | sed 's/\./_/g') - echo "''${!conf}" > "$out"/"$i" - done - ''; - }); in { @@ -209,7 +175,9 @@ in config = mkIf cfg.enable { environment.systemPackages = [ cfg.package ]; - environment.etc.asterisk.source = asteriskEtc; + environment.etc = mapAttrs' (name: value: + nameValuePair "asterisk/${name}" value + ) allConfFiles; users.users.asterisk = { name = asteriskUser; diff --git a/nixos/modules/services/networking/cloudflare-dyndns.nix b/nixos/modules/services/networking/cloudflare-dyndns.nix new file mode 100644 index 0000000000000..ab5b1a08539a5 --- /dev/null +++ b/nixos/modules/services/networking/cloudflare-dyndns.nix @@ -0,0 +1,93 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.services.cloudflare-dyndns; +in +{ + options = { + services.cloudflare-dyndns = { + enable = mkEnableOption "Cloudflare Dynamic DNS Client"; + + apiTokenFile = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The path to a file containing the CloudFlare API token. + + The file must have the form `CLOUDFLARE_API_TOKEN=...` + ''; + }; + + domains = mkOption { + type = types.listOf types.str; + default = [ ]; + description = '' + List of domain names to update records for. + ''; + }; + + proxied = mkOption { + type = types.bool; + default = false; + description = '' + Whether this is a DNS-only record, or also being proxied through CloudFlare. + ''; + }; + + ipv4 = mkOption { + type = types.bool; + default = true; + description = '' + Whether to enable setting IPv4 A records. + ''; + }; + + ipv6 = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable setting IPv6 AAAA records. + ''; + }; + + deleteMissing = mkOption { + type = types.bool; + default = false; + description = '' + Whether to delete the record when no IP address is found. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + systemd.services.cloudflare-dyndns = { + description = "CloudFlare Dynamic DNS Client"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + startAt = "*:0/5"; + + environment = { + CLOUDFLARE_DOMAINS = toString cfg.domains; + }; + + serviceConfig = { + Type = "simple"; + DynamicUser = true; + StateDirectory = "cloudflare-dyndns"; + EnvironmentFile = cfg.apiTokenFile; + ExecStart = + let + args = [ "--cache-file /var/lib/cloudflare-dyndns/ip.cache" ] + ++ (if cfg.ipv4 then [ "-4" ] else [ "-no-4" ]) + ++ (if cfg.ipv6 then [ "-6" ] else [ "-no-6" ]) + ++ optional cfg.deleteMissing "--delete-missing" + ++ optional cfg.proxied "--proxied"; + in + "${pkgs.cloudflare-dyndns}/bin/cloudflare-dyndns ${toString args}"; + }; + }; + }; +} diff --git a/nixos/modules/services/networking/supplicant.nix b/nixos/modules/services/networking/supplicant.nix index eb24130e519a7..8df450a11c633 100644 --- a/nixos/modules/services/networking/supplicant.nix +++ b/nixos/modules/services/networking/supplicant.nix @@ -43,7 +43,7 @@ let path = [ pkgs.coreutils ]; preStart = '' - ${optionalString (suppl.configFile.path!=null) '' + ${optionalString (suppl.configFile.path!=null && suppl.configFile.writable) '' (umask 077 && touch -a "${suppl.configFile.path}") ''} ${optionalString suppl.userControlled.enable '' diff --git a/nixos/modules/services/system/nscd.nix b/nixos/modules/services/system/nscd.nix index 0caebc8ce90a4..002c409278066 100644 --- a/nixos/modules/services/system/nscd.nix +++ b/nixos/modules/services/system/nscd.nix @@ -38,7 +38,7 @@ in default = if pkgs.stdenv.hostPlatform.libc == "glibc" then pkgs.stdenv.cc.libc.bin else pkgs.glibc.bin; - defaultText = literalExample '' + defaultText = lib.literalExpression '' if pkgs.stdenv.hostPlatform.libc == "glibc" then pkgs.stdenv.cc.libc.bin else pkgs.glibc.bin; diff --git a/nixos/modules/services/web-apps/galene.nix b/nixos/modules/services/web-apps/galene.nix index 1d0a620585b0b..38c3392014f5c 100644 --- a/nixos/modules/services/web-apps/galene.nix +++ b/nixos/modules/services/web-apps/galene.nix @@ -164,6 +164,35 @@ in optional (cfg.dataDir == defaultdataDir) "galene/data" ++ optional (cfg.groupsDir == defaultgroupsDir) "galene/groups" ++ optional (cfg.recordingsDir == defaultrecordingsDir) "galene/recordings"; + + # Hardening + CapabilityBoundingSet = [ "" ]; + DeviceAllow = [ "" ]; + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateTmp = true; + PrivateUsers = true; + ProcSubset = "pid"; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + ProtectSystem = "strict"; + ReadWritePaths = cfg.recordingsDir; + RemoveIPC = true; + RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + SystemCallFilter = [ "@system-service" "~@privileged" "~@resources" ]; + UMask = "0077"; } ]; }; diff --git a/nixos/modules/services/x11/desktop-managers/enlightenment.nix b/nixos/modules/services/x11/desktop-managers/enlightenment.nix index d1513a596b9fa..991616bd192d5 100644 --- a/nixos/modules/services/x11/desktop-managers/enlightenment.nix +++ b/nixos/modules/services/x11/desktop-managers/enlightenment.nix @@ -16,6 +16,10 @@ let in { + meta = { + maintainers = teams.enlightenment.members; + }; + imports = [ (mkRenamedOptionModule [ "services" "xserver" "desktopManager" "e19" "enable" ] [ "services" "xserver" "desktopManager" "enlightenment" "enable" ]) ]; @@ -92,6 +96,7 @@ in services.udisks2.enable = true; services.upower.enable = config.powerManagement.enable; + services.xserver.libinput.enable = mkDefault true; services.dbus.packages = [ e.efl ]; diff --git a/nixos/modules/services/x11/desktop-managers/lumina.nix b/nixos/modules/services/x11/desktop-managers/lumina.nix index 419f5055d8be9..faa83b8bc54a5 100644 --- a/nixos/modules/services/x11/desktop-managers/lumina.nix +++ b/nixos/modules/services/x11/desktop-managers/lumina.nix @@ -10,6 +10,10 @@ let in { + meta = { + maintainers = teams.lumina.members; + }; + options = { services.xserver.desktopManager.lumina.enable = mkOption { diff --git a/nixos/modules/services/x11/desktop-managers/lxqt.nix b/nixos/modules/services/x11/desktop-managers/lxqt.nix index 1bc6c906c4790..46f35f11b4a59 100644 --- a/nixos/modules/services/x11/desktop-managers/lxqt.nix +++ b/nixos/modules/services/x11/desktop-managers/lxqt.nix @@ -9,6 +9,10 @@ let in { + meta = { + maintainers = teams.lxqt.members; + }; + options = { services.xserver.desktopManager.lxqt.enable = mkOption { @@ -62,6 +66,11 @@ in services.gvfs.enable = true; services.upower.enable = config.powerManagement.enable; + + services.xserver.libinput.enable = mkDefault true; + + xdg.portal.enable = true; + xdg.portal.extraPortals = [ pkgs.lxqt.xdg-desktop-portal-lxqt ]; }; } diff --git a/nixos/modules/services/x11/desktop-managers/mate.nix b/nixos/modules/services/x11/desktop-managers/mate.nix index 9ab4c6e7e9841..b63510475ec5f 100644 --- a/nixos/modules/services/x11/desktop-managers/mate.nix +++ b/nixos/modules/services/x11/desktop-managers/mate.nix @@ -73,6 +73,7 @@ in services.udev.packages = [ pkgs.mate.mate-settings-daemon ]; services.gvfs.enable = true; services.upower.enable = config.powerManagement.enable; + services.xserver.libinput.enable = mkDefault true; security.pam.services.mate-screensaver.unixAuth = true; diff --git a/nixos/modules/services/x11/desktop-managers/pantheon.xml b/nixos/modules/services/x11/desktop-managers/pantheon.xml index 202909d398f08..6226f8f6a272f 100644 --- a/nixos/modules/services/x11/desktop-managers/pantheon.xml +++ b/nixos/modules/services/x11/desktop-managers/pantheon.xml @@ -3,7 +3,7 @@ xml:id="chap-pantheon"> <title>Pantheon Desktop</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. + Pantheon is the desktop environment created for the elementary OS distribution. It is written from scratch in Vala, utilizing GNOME technologies with GTK and Granite. </para> <section xml:id="sec-pantheon-enable"> <title>Enabling Pantheon</title> @@ -89,9 +89,9 @@ switchboard-with-plugs.override { </para> </listitem> </varlistentry> - <varlistentry xml:id="sec-pantheon-faq-gnome3-and-pantheon"> + <varlistentry xml:id="sec-pantheon-faq-gnome-and-pantheon"> <term> - I cannot enable both GNOME 3 and Pantheon. + I cannot enable both GNOME and Pantheon. </term> <listitem> <para> diff --git a/nixos/modules/system/boot/luksroot.nix b/nixos/modules/system/boot/luksroot.nix index 57fc02a2e3227..4103a7af57cdf 100644 --- a/nixos/modules/system/boot/luksroot.nix +++ b/nixos/modules/system/boot/luksroot.nix @@ -992,6 +992,7 @@ in ]; storePaths = [ "${config.boot.initrd.systemd.package}/lib/systemd/systemd-cryptsetup" + "${config.boot.initrd.systemd.package}/lib/systemd/system-generators/systemd-cryptsetup-generator" ]; }; diff --git a/nixos/modules/system/boot/systemd/initrd-secrets.nix b/nixos/modules/system/boot/systemd/initrd-secrets.nix new file mode 100644 index 0000000000000..bc65880719d7a --- /dev/null +++ b/nixos/modules/system/boot/systemd/initrd-secrets.nix @@ -0,0 +1,36 @@ +{ config, pkgs, lib, ... }: + +{ + config = lib.mkIf (config.boot.initrd.enable && config.boot.initrd.systemd.enable) { + # Copy secrets into the initrd if they cannot be appended + boot.initrd.systemd.contents = lib.mkIf (!config.boot.loader.supportsInitrdSecrets) + (lib.mapAttrs' (dest: source: lib.nameValuePair "/.initrd-secrets/${dest}" { source = if source == null then dest else source; }) config.boot.initrd.secrets); + + # Copy secrets to their respective locations + boot.initrd.systemd.services.initrd-nixos-copy-secrets = lib.mkIf (config.boot.initrd.secrets != {}) { + description = "Copy secrets into place"; + # Run as early as possible + wantedBy = [ "sysinit.target" ]; + before = [ "cryptsetup-pre.target" ]; + unitConfig.DefaultDependencies = false; + + # We write the secrets to /.initrd-secrets and move them because this allows + # secrets to be written to /run. If we put the secret directly to /run and + # drop this service, we'd mount the /run tmpfs over the secret, making it + # invisible in stage 2. + script = '' + for secret in $(cd /.initrd-secrets; find . -type f); do + mkdir -p "$(dirname "/$secret")" + cp "/.initrd-secrets/$secret" "/$secret" + done + ''; + + unitConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + }; + # The script needs this + boot.initrd.systemd.extraBin.find = "${pkgs.findutils}/bin/find"; + }; +} diff --git a/nixos/modules/system/boot/systemd/initrd.nix b/nixos/modules/system/boot/systemd/initrd.nix index 6c1b42da1c41f..cdec7f532917d 100644 --- a/nixos/modules/system/boot/systemd/initrd.nix +++ b/nixos/modules/system/boot/systemd/initrd.nix @@ -65,7 +65,6 @@ let "systemd-kexec.service" "systemd-modules-load.service" "systemd-poweroff.service" - "systemd-random-seed.service" "systemd-reboot.service" "systemd-sysctl.service" "systemd-tmpfiles-setup-dev.service" @@ -106,6 +105,9 @@ let opts = options ++ optional autoFormat "x-systemd.makefs" ++ optional autoResize "x-systemd.growfs"; in "${device} /sysroot${mountPoint} ${fsType} ${lib.concatStringsSep "," opts}") fileSystems); + needMakefs = lib.any (fs: fs.autoFormat) fileSystems; + needGrowfs = lib.any (fs: fs.autoResize) fileSystems; + kernel-name = config.boot.kernelPackages.kernel.name or "kernel"; modulesTree = config.system.modulesTree.override { name = kernel-name + "-modules"; }; firmware = config.hardware.firmware; @@ -156,44 +158,14 @@ in { ''; visible = false; default = {}; - type = types.attrsOf (types.submodule ({ config, options, name, ... }: { - options = { - enable = mkEnableOption "copying of this file to initrd and symlinking it" // { default = true; }; - - target = mkOption { - type = types.path; - description = '' - Path of the symlink. - ''; - default = name; - }; - - text = mkOption { - default = null; - type = types.nullOr types.lines; - description = "Text of the file."; - }; - - source = mkOption { - type = types.path; - description = "Path of the source file."; - }; - }; - - config = { - source = mkIf (config.text != null) ( - let name' = "initrd-" + baseNameOf name; - in mkDerivedConfig options.text (pkgs.writeText name') - ); - }; - })); + type = utils.systemdUtils.types.initrdContents; }; storePaths = mkOption { description = '' Store paths to copy into the initrd as well. ''; - type = types.listOf types.singleLineStr; + type = with types; listOf (oneOf [ singleLineStr package ]); default = []; }; @@ -370,6 +342,7 @@ in { "/etc/fstab".source = fstab; "/lib/modules".source = "${modulesClosure}/lib/modules"; + "/lib/firmware".source = "${modulesClosure}/lib/firmware"; "/etc/modules-load.d/nixos.conf".text = concatStringsSep "\n" config.boot.initrd.kernelModules; @@ -391,19 +364,22 @@ in { storePaths = [ # systemd tooling "${cfg.package}/lib/systemd/systemd-fsck" - "${cfg.package}/lib/systemd/systemd-growfs" + (lib.mkIf needGrowfs "${cfg.package}/lib/systemd/systemd-growfs") "${cfg.package}/lib/systemd/systemd-hibernate-resume" "${cfg.package}/lib/systemd/systemd-journald" - "${cfg.package}/lib/systemd/systemd-makefs" + (lib.mkIf needMakefs "${cfg.package}/lib/systemd/systemd-makefs") "${cfg.package}/lib/systemd/systemd-modules-load" - "${cfg.package}/lib/systemd/systemd-random-seed" "${cfg.package}/lib/systemd/systemd-remount-fs" "${cfg.package}/lib/systemd/systemd-shutdown" "${cfg.package}/lib/systemd/systemd-sulogin-shell" "${cfg.package}/lib/systemd/systemd-sysctl" - # additional systemd directories - "${cfg.package}/lib/systemd/system-generators" + # generators + "${cfg.package}/lib/systemd/system-generators/systemd-debug-generator" + "${cfg.package}/lib/systemd/system-generators/systemd-fstab-generator" + "${cfg.package}/lib/systemd/system-generators/systemd-gpt-auto-generator" + "${cfg.package}/lib/systemd/system-generators/systemd-hibernate-resume-generator" + "${cfg.package}/lib/systemd/system-generators/systemd-run-generator" # utilities needed by systemd "${cfg.package.util-linux}/bin/mount" @@ -441,8 +417,8 @@ in { mkdir -p $out/etc/systemd/system touch $out/etc/systemd/system/systemd-{makefs,growfs}@.service '')]; - services."systemd-makefs@".unitConfig.IgnoreOnIsolate = true; - services."systemd-growfs@".unitConfig.IgnoreOnIsolate = true; + services."systemd-makefs@" = lib.mkIf needMakefs { unitConfig.IgnoreOnIsolate = true; }; + services."systemd-growfs@" = lib.mkIf needGrowfs { unitConfig.IgnoreOnIsolate = true; }; services.initrd-nixos-activation = { after = [ "initrd-fs.target" ]; @@ -504,9 +480,23 @@ in { ''systemctl --no-block switch-root /sysroot "''${NEW_INIT}"'' ]; }; + + services.panic-on-fail = { + wantedBy = ["emergency.target"]; + unitConfig = { + DefaultDependencies = false; + ConditionKernelCommandLine = [ + "|boot.panic_on_fail" + "|stage1panic" + ]; + }; + script = '' + echo c > /proc/sysrq-trigger + ''; + serviceConfig.Type = "oneshot"; + }; }; boot.kernelParams = lib.mkIf (config.boot.resumeDevice != "") [ "resume=${config.boot.resumeDevice}" ]; - }; } diff --git a/nixos/modules/system/boot/systemd/shutdown.nix b/nixos/modules/system/boot/systemd/shutdown.nix index 9342693166762..63e1751f9b41b 100644 --- a/nixos/modules/system/boot/systemd/shutdown.nix +++ b/nixos/modules/system/boot/systemd/shutdown.nix @@ -1,31 +1,57 @@ -{ config, lib, ... }: let +{ config, lib, utils, pkgs, ... }: let - cfg = config.boot.systemd.shutdown; + cfg = config.systemd.shutdownRamfs; + + ramfsContents = let + storePaths = map (p: "${p}\n") cfg.storePaths; + contents = lib.mapAttrsToList (_: v: "${v.source}\n${v.target}") (lib.filterAttrs (_: v: v.enable) cfg.contents); + in pkgs.writeText "shutdown-ramfs-contents" (lib.concatStringsSep "\n" (storePaths ++ contents)); in { - options.boot.systemd.shutdown = { + options.systemd.shutdownRamfs = { enable = lib.mkEnableOption "pivoting back to an initramfs for shutdown" // { default = true; }; + contents = lib.mkOption { + description = "Set of files that have to be linked into the shutdown ramfs"; + example = lib.literalExpression '' + { + "/lib/systemd/system-shutdown/zpool-sync-shutdown".source = writeShellScript "zpool" "exec ''${zfs}/bin/zpool sync" + } + ''; + type = utils.systemdUtils.types.initrdContents; + }; + + storePaths = lib.mkOption { + description = '' + Store paths to copy into the shutdown ramfs as well. + ''; + type = lib.types.listOf lib.types.singleLineStr; + default = []; + }; }; config = lib.mkIf cfg.enable { + systemd.shutdownRamfs.contents."/shutdown".source = "${config.systemd.package}/lib/systemd/systemd-shutdown"; + systemd.shutdownRamfs.storePaths = [pkgs.runtimeShell "${pkgs.coreutils}/bin"]; + systemd.services.generate-shutdown-ramfs = { description = "Generate shutdown ramfs"; + wantedBy = [ "shutdown.target" ]; before = [ "shutdown.target" ]; unitConfig = { DefaultDependencies = false; ConditionFileIsExecutable = [ "!/run/initramfs/shutdown" - "/run/current-system/systemd/lib/systemd/systemd-shutdown" ]; }; + path = [pkgs.util-linux pkgs.makeInitrdNGTool pkgs.glibc pkgs.patchelf]; serviceConfig.Type = "oneshot"; script = '' mkdir -p /run/initramfs if ! mountpoint -q /run/initramfs; then mount -t tmpfs tmpfs /run/initramfs fi - cp /run/current-system/systemd/lib/systemd/systemd-shutdown /run/initramfs/shutdown + make-initrd-ng ${ramfsContents} /run/initramfs ''; }; }; diff --git a/nixos/modules/tasks/bcache.nix b/nixos/modules/tasks/bcache.nix index 41fb7664f3d17..0a13522de11f0 100644 --- a/nixos/modules/tasks/bcache.nix +++ b/nixos/modules/tasks/bcache.nix @@ -1,13 +1,23 @@ -{ pkgs, ... }: +{ config, lib, pkgs, ... }: { + options.boot.initrd.services.bcache.enable = (lib.mkEnableOption "bcache support in the initrd") // { + visible = false; # only works with systemd stage 1 + }; - environment.systemPackages = [ pkgs.bcache-tools ]; + config = { - services.udev.packages = [ pkgs.bcache-tools ]; + environment.systemPackages = [ pkgs.bcache-tools ]; - boot.initrd.extraUdevRulesCommands = '' - cp -v ${pkgs.bcache-tools}/lib/udev/rules.d/*.rules $out/ - ''; + services.udev.packages = [ pkgs.bcache-tools ]; + boot.initrd.extraUdevRulesCommands = lib.mkIf (!config.boot.initrd.systemd.enable) '' + cp -v ${pkgs.bcache-tools}/lib/udev/rules.d/*.rules $out/ + ''; + + boot.initrd.services.udev = lib.mkIf config.boot.initrd.services.bcache.enable { + packages = [ pkgs.bcache-tools ]; + binPackages = [ pkgs.bcache-tools ]; + }; + }; } diff --git a/nixos/modules/tasks/filesystems/btrfs.nix b/nixos/modules/tasks/filesystems/btrfs.nix index ae1dab5b8d8d4..b7ebc37dd5cf9 100644 --- a/nixos/modules/tasks/filesystems/btrfs.nix +++ b/nixos/modules/tasks/filesystems/btrfs.nix @@ -66,19 +66,19 @@ in ] ); - boot.initrd.extraUtilsCommands = mkIf inInitrd + boot.initrd.extraUtilsCommands = mkIf (inInitrd && !config.boot.initrd.systemd.enable) '' copy_bin_and_libs ${pkgs.btrfs-progs}/bin/btrfs ln -sv btrfs $out/bin/btrfsck ln -sv btrfsck $out/bin/fsck.btrfs ''; - boot.initrd.extraUtilsCommandsTest = mkIf inInitrd + boot.initrd.extraUtilsCommandsTest = mkIf (inInitrd && !config.boot.initrd.systemd.enable) '' $out/bin/btrfs --version ''; - boot.initrd.postDeviceCommands = mkIf inInitrd + boot.initrd.postDeviceCommands = mkIf (inInitrd && !config.boot.initrd.systemd.enable) '' btrfs device scan ''; diff --git a/nixos/modules/tasks/filesystems/cifs.nix b/nixos/modules/tasks/filesystems/cifs.nix index 47ba0c03c5630..0de292a692082 100644 --- a/nixos/modules/tasks/filesystems/cifs.nix +++ b/nixos/modules/tasks/filesystems/cifs.nix @@ -16,7 +16,7 @@ in boot.initrd.availableKernelModules = mkIf inInitrd [ "cifs" "nls_utf8" "hmac" "md4" "ecb" "des_generic" "sha256" ]; - boot.initrd.extraUtilsCommands = mkIf inInitrd + boot.initrd.extraUtilsCommands = mkIf (inInitrd && !config.boot.initrd.systemd.enable) '' copy_bin_and_libs ${pkgs.cifs-utils}/sbin/mount.cifs ''; diff --git a/nixos/modules/tasks/filesystems/ext.nix b/nixos/modules/tasks/filesystems/ext.nix index a14a3ac38549c..9b61f21643aba 100644 --- a/nixos/modules/tasks/filesystems/ext.nix +++ b/nixos/modules/tasks/filesystems/ext.nix @@ -1,14 +1,20 @@ -{ pkgs, ... }: +{ config, lib, pkgs, ... }: + +let + + inInitrd = lib.any (fs: fs == "ext2" || fs == "ext3" || fs == "ext4") config.boot.initrd.supportedFilesystems; + +in { config = { - system.fsPackages = [ pkgs.e2fsprogs ]; + system.fsPackages = lib.mkIf (config.boot.initrd.systemd.enable -> inInitrd) [ pkgs.e2fsprogs ]; # As of kernel 4.3, there is no separate ext3 driver (they're also handled by ext4.ko) - boot.initrd.availableKernelModules = [ "ext2" "ext4" ]; + boot.initrd.availableKernelModules = lib.mkIf (config.boot.initrd.systemd.enable -> inInitrd) [ "ext2" "ext4" ]; - boot.initrd.extraUtilsCommands = + boot.initrd.extraUtilsCommands = lib.mkIf (!config.boot.initrd.systemd.enable) '' # Copy e2fsck and friends. copy_bin_and_libs ${pkgs.e2fsprogs}/sbin/e2fsck diff --git a/nixos/modules/tasks/filesystems/f2fs.nix b/nixos/modules/tasks/filesystems/f2fs.nix index a305235979a2f..1d52861aa39d1 100644 --- a/nixos/modules/tasks/filesystems/f2fs.nix +++ b/nixos/modules/tasks/filesystems/f2fs.nix @@ -13,7 +13,7 @@ in boot.initrd.availableKernelModules = mkIf inInitrd [ "f2fs" "crc32" ]; - boot.initrd.extraUtilsCommands = mkIf inInitrd '' + boot.initrd.extraUtilsCommands = mkIf (inInitrd && !config.boot.initrd.systemd.enable) '' copy_bin_and_libs ${pkgs.f2fs-tools}/sbin/fsck.f2fs ${optionalString (any (fs: fs.autoResize) fileSystems) '' # We need f2fs-tools' tools to resize filesystems diff --git a/nixos/modules/tasks/filesystems/jfs.nix b/nixos/modules/tasks/filesystems/jfs.nix index fc3905c7dc201..700f05af2bec4 100644 --- a/nixos/modules/tasks/filesystems/jfs.nix +++ b/nixos/modules/tasks/filesystems/jfs.nix @@ -12,7 +12,7 @@ in boot.initrd.kernelModules = mkIf inInitrd [ "jfs" ]; - boot.initrd.extraUtilsCommands = mkIf inInitrd '' + boot.initrd.extraUtilsCommands = mkIf (inInitrd && !boot.initrd.systemd.enable) '' copy_bin_and_libs ${pkgs.jfsutils}/sbin/fsck.jfs ''; }; diff --git a/nixos/modules/tasks/filesystems/reiserfs.nix b/nixos/modules/tasks/filesystems/reiserfs.nix index ab4c43e2ab826..7b017a83db848 100644 --- a/nixos/modules/tasks/filesystems/reiserfs.nix +++ b/nixos/modules/tasks/filesystems/reiserfs.nix @@ -15,7 +15,7 @@ in boot.initrd.kernelModules = mkIf inInitrd [ "reiserfs" ]; - boot.initrd.extraUtilsCommands = mkIf inInitrd + boot.initrd.extraUtilsCommands = mkIf (inInitrd && !config.boot.initrd.systemd.enable) '' copy_bin_and_libs ${pkgs.reiserfsprogs}/sbin/reiserfsck ln -s reiserfsck $out/bin/fsck.reiserfs diff --git a/nixos/modules/tasks/filesystems/unionfs-fuse.nix b/nixos/modules/tasks/filesystems/unionfs-fuse.nix index f54f3559c3411..f9954b5182f91 100644 --- a/nixos/modules/tasks/filesystems/unionfs-fuse.nix +++ b/nixos/modules/tasks/filesystems/unionfs-fuse.nix @@ -6,7 +6,7 @@ (lib.mkIf (lib.any (fs: fs == "unionfs-fuse") config.boot.initrd.supportedFilesystems) { boot.initrd.kernelModules = [ "fuse" ]; - boot.initrd.extraUtilsCommands = '' + boot.initrd.extraUtilsCommands = lib.mkIf (!config.boot.initrd.systemd.enable) '' copy_bin_and_libs ${pkgs.fuse}/sbin/mount.fuse copy_bin_and_libs ${pkgs.unionfs-fuse}/bin/unionfs substitute ${pkgs.unionfs-fuse}/sbin/mount.unionfs-fuse $out/bin/mount.unionfs-fuse \ @@ -16,12 +16,23 @@ chmod +x $out/bin/mount.unionfs-fuse ''; - boot.initrd.postDeviceCommands = '' + boot.initrd.postDeviceCommands = lib.mkIf (!config.boot.initrd.systemd.enable) '' # Hacky!!! fuse hard-codes the path to mount mkdir -p /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${pkgs.util-linux.name}-bin/bin ln -s $(which mount) /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${pkgs.util-linux.name}-bin/bin ln -s $(which umount) /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${pkgs.util-linux.name}-bin/bin ''; + + boot.initrd.systemd.extraBin = { + "mount.fuse" = "${pkgs.fuse}/bin/mount.fuse"; + "unionfs" = "${pkgs.unionfs-fuse}/bin/unionfs"; + "mount.unionfs-fuse" = pkgs.runCommand "mount.unionfs-fuse" {} '' + substitute ${pkgs.unionfs-fuse}/sbin/mount.unionfs-fuse $out \ + --replace '${pkgs.bash}/bin/bash' /bin/sh \ + --replace '${pkgs.fuse}/sbin' /bin \ + --replace '${pkgs.unionfs-fuse}/bin' /bin + ''; + }; }) (lib.mkIf (lib.any (fs: fs == "unionfs-fuse") config.boot.supportedFilesystems) { diff --git a/nixos/modules/tasks/filesystems/vfat.nix b/nixos/modules/tasks/filesystems/vfat.nix index 958e27ae8a32a..5baab1c802cf9 100644 --- a/nixos/modules/tasks/filesystems/vfat.nix +++ b/nixos/modules/tasks/filesystems/vfat.nix @@ -15,7 +15,7 @@ in boot.initrd.kernelModules = mkIf inInitrd [ "vfat" "nls_cp437" "nls_iso8859-1" ]; - boot.initrd.extraUtilsCommands = mkIf inInitrd + boot.initrd.extraUtilsCommands = mkIf (inInitrd && !config.boot.initrd.systemd.enable) '' copy_bin_and_libs ${pkgs.dosfstools}/sbin/dosfsck ln -sv dosfsck $out/bin/fsck.vfat diff --git a/nixos/modules/tasks/filesystems/xfs.nix b/nixos/modules/tasks/filesystems/xfs.nix index 98038701ca580..f81f586465519 100644 --- a/nixos/modules/tasks/filesystems/xfs.nix +++ b/nixos/modules/tasks/filesystems/xfs.nix @@ -15,14 +15,14 @@ in boot.initrd.availableKernelModules = mkIf inInitrd [ "xfs" "crc32c" ]; - boot.initrd.extraUtilsCommands = mkIf inInitrd + boot.initrd.extraUtilsCommands = mkIf (inInitrd && !config.boot.initrd.systemd.enable) '' copy_bin_and_libs ${pkgs.xfsprogs.bin}/bin/fsck.xfs copy_bin_and_libs ${pkgs.xfsprogs.bin}/bin/xfs_repair ''; # Trick just to set 'sh' after the extraUtils nuke-refs. - boot.initrd.extraUtilsCommandsTest = mkIf inInitrd + boot.initrd.extraUtilsCommandsTest = mkIf (inInitrd && !config.boot.initrd.systemd.enable) '' sed -i -e 's,^#!.*,#!'$out/bin/sh, $out/bin/fsck.xfs ''; diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix index fbfc61177d386..5eca68798d5d8 100644 --- a/nixos/modules/tasks/filesystems/zfs.nix +++ b/nixos/modules/tasks/filesystems/zfs.nix @@ -466,6 +466,11 @@ in '') rootPools)); }; + systemd.shutdownRamfs.contents."/etc/systemd/system-shutdown/zpool".source = pkgs.writeShellScript "zpool-sync-shutdown" '' + exec ${cfgZfs.package}/bin/zpool sync + ''; + systemd.shutdownRamfs.storePaths = ["${cfgZfs.package}/bin/zpool"]; + # TODO FIXME See https://github.com/NixOS/nixpkgs/pull/99386#issuecomment-798813567. To not break people's bootloader and as probably not everybody would read release notes that thoroughly add inSystem. boot.loader.grub = mkIf (inInitrd || inSystem) { zfsSupport = true; diff --git a/nixos/modules/testing/test-instrumentation.nix b/nixos/modules/testing/test-instrumentation.nix index 01447e6ada879..81541477b9e09 100644 --- a/nixos/modules/testing/test-instrumentation.nix +++ b/nixos/modules/testing/test-instrumentation.nix @@ -65,33 +65,26 @@ in }; }; - boot.initrd.preDeviceCommands = - '' - echo 600 > /proc/sys/kernel/hung_task_timeout_secs - ''; - - boot.initrd.postDeviceCommands = - '' - # Using acpi_pm as a clock source causes the guest clock to - # slow down under high host load. This is usually a bad - # thing, but for VM tests it should provide a bit more - # determinism (e.g. if the VM runs at lower speed, then - # timeouts in the VM should also be delayed). - echo acpi_pm > /sys/devices/system/clocksource/clocksource0/current_clocksource - ''; - - boot.postBootCommands = - '' - # Panic on out-of-memory conditions rather than letting the - # OOM killer randomly get rid of processes, since this leads - # to failures that are hard to diagnose. - echo 2 > /proc/sys/vm/panic_on_oom - ''; + boot.kernel.sysctl = { + "kernel.hung_task_timeout_secs" = 600; + # Panic on out-of-memory conditions rather than letting the + # OOM killer randomly get rid of processes, since this leads + # to failures that are hard to diagnose. + "vm.panic_on_oom" = lib.mkDefault 2; + }; - # Panic if an error occurs in stage 1 (rather than waiting for - # user intervention). - boot.kernelParams = - [ "console=${qemu-common.qemuSerialDevice}" "panic=1" "boot.panic_on_fail" ]; + boot.kernelParams = [ + "console=${qemu-common.qemuSerialDevice}" + # Panic if an error occurs in stage 1 (rather than waiting for + # user intervention). + "panic=1" "boot.panic_on_fail" + # Using acpi_pm as a clock source causes the guest clock to + # slow down under high host load. This is usually a bad + # thing, but for VM tests it should provide a bit more + # determinism (e.g. if the VM runs at lower speed, then + # timeouts in the VM should also be delayed). + "clock=acpi_pm" + ]; # `xwininfo' is used by the test driver to query open windows. environment.systemPackages = [ pkgs.xorg.xwininfo ]; diff --git a/nixos/modules/virtualisation/nixos-containers.nix b/nixos/modules/virtualisation/nixos-containers.nix index 0838a57f0f372..23228a109bce9 100644 --- a/nixos/modules/virtualisation/nixos-containers.nix +++ b/nixos/modules/virtualisation/nixos-containers.nix @@ -4,6 +4,11 @@ with lib; let + configurationPrefix = optionalString (versionAtLeast config.system.stateVersion "22.05") "nixos-"; + configurationDirectoryName = "${configurationPrefix}containers"; + configurationDirectory = "/etc/${configurationDirectoryName}"; + stateDirectory = "/var/lib/${configurationPrefix}containers"; + # The container's init script, a small wrapper around the regular # NixOS stage-2 init script. containerInit = (cfg: @@ -77,7 +82,7 @@ let startScript = cfg: '' mkdir -p -m 0755 "$root/etc" "$root/var/lib" - mkdir -p -m 0700 "$root/var/lib/private" "$root/root" /run/containers + mkdir -p -m 0700 "$root/var/lib/private" "$root/root" /run/nixos-containers if ! [ -e "$root/etc/os-release" ]; then touch "$root/etc/os-release" fi @@ -249,11 +254,11 @@ let SyslogIdentifier = "container %i"; - EnvironmentFile = "-/etc/containers/%i.conf"; + EnvironmentFile = "-${configurationDirectory}/%i.conf"; Type = "notify"; - RuntimeDirectory = lib.optional cfg.ephemeral "containers/%i"; + RuntimeDirectory = lib.optional cfg.ephemeral "${configurationDirectoryName}/%i"; # Note that on reboot, systemd-nspawn returns 133, so this # unit will be restarted. On poweroff, it returns 0, so the @@ -737,15 +742,21 @@ in config = mkIf (config.boot.enableContainers) (let + warnings = flatten [ + (optional (config.virtualisation.containers.enable && versionOlder config.system.stateVersion "22.05") '' + Enabling both boot.enableContainers & virtualisation.containers on system.stateVersion < 22.05 is unsupported. + '') + ]; + unit = { description = "Container '%i'"; - unitConfig.RequiresMountsFor = "/var/lib/containers/%i"; + unitConfig.RequiresMountsFor = "${stateDirectory}/%i"; path = [ pkgs.iproute2 ]; environment = { - root = "/var/lib/containers/%i"; + root = "${stateDirectory}/%i"; INSTANCE = "%i"; }; @@ -782,8 +793,8 @@ in script = startScript containerConfig; postStart = postStartScript containerConfig; serviceConfig = serviceDirectives containerConfig; - unitConfig.RequiresMountsFor = lib.optional (!containerConfig.ephemeral) "/var/lib/containers/%i"; - environment.root = if containerConfig.ephemeral then "/run/containers/%i" else "/var/lib/containers/%i"; + unitConfig.RequiresMountsFor = lib.optional (!containerConfig.ephemeral) "${stateDirectory}/%i"; + environment.root = if containerConfig.ephemeral then "/run/nixos-containers/%i" else "${stateDirectory}/%i"; } // ( if containerConfig.autoStart then { @@ -792,7 +803,7 @@ in after = [ "network.target" ]; restartTriggers = [ containerConfig.path - config.environment.etc."containers/${name}.conf".source + config.environment.etc."${configurationDirectoryName}/${name}.conf".source ]; restartIfChanged = true; } @@ -800,12 +811,12 @@ in )) config.containers) )); - # Generate a configuration file in /etc/containers for each + # Generate a configuration file in /etc/nixos-containers for each # container so that container@.target can get the container # configuration. environment.etc = let mkPortStr = p: p.protocol + ":" + (toString p.hostPort) + ":" + (if p.containerPort == null then toString p.hostPort else toString p.containerPort); - in mapAttrs' (name: cfg: nameValuePair "containers/${name}.conf" + in mapAttrs' (name: cfg: nameValuePair "${configurationDirectoryName}/${name}.conf" { text = '' SYSTEM_PATH=${cfg.path} @@ -854,7 +865,11 @@ in ENV{INTERFACE}=="v[eb]-*", ENV{NM_UNMANAGED}="1" ''; - environment.systemPackages = [ pkgs.nixos-container ]; + environment.systemPackages = [ + (pkgs.nixos-container.override { + inherit stateDirectory configurationDirectory; + }) + ]; boot.kernelModules = [ "bridge" diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix index b1c5a7a6c95fd..f622897aa6207 100644 --- a/nixos/modules/virtualisation/qemu-vm.nix +++ b/nixos/modules/virtualisation/qemu-vm.nix @@ -754,13 +754,13 @@ in ); boot.loader.grub.gfxmodeBios = with cfg.resolution; "${toString x}x${toString y}"; - boot.initrd.extraUtilsCommands = + boot.initrd.extraUtilsCommands = lib.mkIf (!config.boot.initrd.systemd.enable) '' # We need mke2fs in the initrd. copy_bin_and_libs ${pkgs.e2fsprogs}/bin/mke2fs ''; - boot.initrd.postDeviceCommands = + boot.initrd.postDeviceCommands = lib.mkIf (!config.boot.initrd.systemd.enable) '' # If the disk image appears to be empty, run mke2fs to # initialise. @@ -770,7 +770,7 @@ in fi ''; - boot.initrd.postMountCommands = + boot.initrd.postMountCommands = lib.mkIf (!config.boot.initrd.systemd.enable) '' # Mark this as a NixOS machine. mkdir -p $targetRoot/etc @@ -789,6 +789,11 @@ in ''} ''; + systemd.tmpfiles.rules = lib.mkIf config.boot.initrd.systemd.enable [ + "f /etc/NIXOS 0644 root root -" + "d /boot 0644 root root -" + ]; + # After booting, register the closure of the paths in # `virtualisation.additionalPaths' in the Nix database in the VM. This # allows Nix operations to work in the VM. The path to the diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 5158bc681e08b..923464a0c9a3e 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -235,6 +235,7 @@ in input-remapper = handleTest ./input-remapper.nix {}; inspircd = handleTest ./inspircd.nix {}; installer = handleTest ./installer.nix {}; + installer-systemd-stage-1 = handleTest ./installer-systemd-stage-1.nix {}; invoiceplane = handleTest ./invoiceplane.nix {}; iodine = handleTest ./iodine.nix {}; ipfs = handleTest ./ipfs.nix {}; @@ -524,6 +525,7 @@ in systemd-confinement = handleTest ./systemd-confinement.nix {}; systemd-cryptenroll = handleTest ./systemd-cryptenroll.nix {}; systemd-escaping = handleTest ./systemd-escaping.nix {}; + systemd-initrd-btrfs-raid = handleTest ./systemd-initrd-btrfs-raid.nix {}; systemd-initrd-luks-keyfile = handleTest ./systemd-initrd-luks-keyfile.nix {}; systemd-initrd-luks-password = handleTest ./systemd-initrd-luks-password.nix {}; systemd-initrd-shutdown = handleTest ./systemd-shutdown.nix { systemdStage1 = true; }; diff --git a/nixos/tests/containers-ephemeral.nix b/nixos/tests/containers-ephemeral.nix index c9fe2778cacdf..cb4b7d4eba0fd 100644 --- a/nixos/tests/containers-ephemeral.nix +++ b/nixos/tests/containers-ephemeral.nix @@ -33,10 +33,10 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: { machine.succeed("nixos-container start webserver") with subtest("Container got its own root folder"): - machine.succeed("ls /run/containers/webserver") + machine.succeed("ls /run/nixos-containers/webserver") with subtest("Container persistent directory is not created"): - machine.fail("ls /var/lib/containers/webserver") + machine.fail("ls /var/lib/nixos-containers/webserver") # Since "start" returns after the container has reached # multi-user.target, we should now be able to access it. @@ -49,6 +49,6 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: { machine.fail(f"curl --fail --connect-timeout 2 http://{ip}/ > /dev/null") with subtest("Container's root folder was removed"): - machine.fail("ls /run/containers/webserver") + machine.fail("ls /run/nixos-containers/webserver") ''; }) diff --git a/nixos/tests/containers-imperative.nix b/nixos/tests/containers-imperative.nix index 44d2e50288b4a..a21ce97a23b15 100644 --- a/nixos/tests/containers-imperative.nix +++ b/nixos/tests/containers-imperative.nix @@ -69,8 +69,8 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: { with subtest(f"Put the root of {id2} into a bind mount"): machine.succeed( - f"mv /var/lib/containers/{id2} /id2-bindmount", - f"mount --bind /id2-bindmount /var/lib/containers/{id1}", + f"mv /var/lib/nixos-containers/{id2} /id2-bindmount", + f"mount --bind /id2-bindmount /var/lib/nixos-containers/{id1}", ) ip1 = machine.succeed(f"nixos-container show-ip {id1}").rstrip() @@ -88,7 +88,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: { "Create a directory with a dummy file and bind-mount it into both containers." ): for id in id1, id2: - important_path = f"/var/lib/containers/{id}/very/important/data" + important_path = f"/var/lib/nixos-containers/{id}/very/important/data" machine.succeed( f"mkdir -p {important_path}", f"mount --bind /nested-bindmount {important_path}", @@ -154,13 +154,13 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: { machine.succeed("grep -qF 'important data' /nested-bindmount/dummy") 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}") + print(machine.succeed("ls -lsa /var/lib/nixos-containers")) + machine.succeed(f"test ! -e /var/lib/nixos-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("test ! -e /var/lib/containers/b0rk") + machine.succeed("test ! -e /var/lib/nixos-containers/b0rk") ''; }) diff --git a/nixos/tests/containers-tmpfs.nix b/nixos/tests/containers-tmpfs.nix index 7a2c835b120aa..cf5b81656afef 100644 --- a/nixos/tests/containers-tmpfs.nix +++ b/nixos/tests/containers-tmpfs.nix @@ -62,7 +62,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: { machine.succeed( tmpfs_cmd("touch /root/test.file"), tmpfs_cmd("ls -l /root | grep -q test.file"), - "test -e /var/lib/containers/tmpfs/root/test.file", + "test -e /var/lib/nixos-containers/tmpfs/root/test.file", ) with subtest( @@ -73,7 +73,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: { tmpfs_cmd("touch /some/random/path/test.file"), tmpfs_cmd("test -e /some/random/path/test.file"), ) - machine.fail("test -e /var/lib/containers/tmpfs/some/random/path/test.file") + machine.fail("test -e /var/lib/nixos-containers/tmpfs/some/random/path/test.file") with subtest( "files created in the hosts container dir in a path where a tmpfs " @@ -81,9 +81,9 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: { + "the do not exist in the tmpfs" ): machine.succeed( - "touch /var/lib/containers/tmpfs/var/test.file", - "test -e /var/lib/containers/tmpfs/var/test.file", - "ls -l /var/lib/containers/tmpfs/var/ | grep -q test.file 2>/dev/null", + "touch /var/lib/nixos-containers/tmpfs/var/test.file", + "test -e /var/lib/nixos-containers/tmpfs/var/test.file", + "ls -l /var/lib/nixos-containers/tmpfs/var/ | grep -q test.file 2>/dev/null", ) machine.fail(tmpfs_cmd("ls -l /var | grep -q test.file")) ''; diff --git a/nixos/tests/custom-ca.nix b/nixos/tests/custom-ca.nix index 60c6c82223a93..8e91bd3eead2b 100644 --- a/nixos/tests/custom-ca.nix +++ b/nixos/tests/custom-ca.nix @@ -1,9 +1,14 @@ # Checks that `security.pki` options are working in curl and the main browser -# engines: Gecko (via Firefox), Chromium, QtWebEngine (Falkon) and WebKitGTK -# (via Midori). The test checks that certificates issued by a custom trusted -# CA are accepted but those from an unknown CA are rejected. +# engines: Gecko (via Firefox), Chromium, QtWebEngine (via qutebrowser) and +# WebKitGTK (via Midori). The test checks that certificates issued by a custom +# trusted CA are accepted but those from an unknown CA are rejected. -import ./make-test-python.nix ({ pkgs, lib, ... }: +{ system ? builtins.currentSystem, + config ? {}, + pkgs ? import ../.. { inherit system config; } +}: + +with import ../lib/testing-python.nix { inherit system pkgs; }; let makeCert = { caName, domain }: pkgs.runCommand "example-cert" @@ -68,24 +73,8 @@ let domain = "bad.example.com"; }; -in - -{ - name = "custom-ca"; - meta.maintainers = with lib.maintainers; [ rnhmjoj ]; - - enableOCR = true; - - nodes.machine = { pkgs, ... }: - { imports = [ ./common/user-account.nix ./common/x11.nix ]; - - # chromium-based browsers refuse to run as root - test-support.displayManager.auto.user = "alice"; - - # browsers may hang with the default memory - virtualisation.memorySize = 600; - - networking.hosts."127.0.0.1" = [ "good.example.com" "bad.example.com" ]; + webserverConfig = + { networking.hosts."127.0.0.1" = [ "good.example.com" "bad.example.com" ]; security.pki.certificateFiles = [ "${example-good-cert}/ca.crt" ]; services.nginx.enable = true; @@ -107,73 +96,98 @@ in return 200 'It does not work!'; ''; }; - - environment.systemPackages = with pkgs; [ - xdotool - firefox - chromium - qutebrowser - midori - ]; }; - testScript = '' - from typing import Tuple - def execute_as(user: str, cmd: str) -> Tuple[int, str]: - """ - Run a shell command as a specific user. - """ - return machine.execute(f"sudo -u {user} {cmd}") - - - def wait_for_window_as(user: str, cls: str) -> None: - """ - Wait until a X11 window of a given user appears. - """ - - def window_is_visible(last_try: bool) -> bool: - ret, stdout = execute_as(user, f"xdotool search --onlyvisible --class {cls}") - if last_try: - machine.log(f"Last chance to match {cls} on the window list") - return ret == 0 - - with machine.nested("Waiting for a window to appear"): - retry(window_is_visible) - - - machine.start() - - with subtest("Good certificate is trusted in curl"): - machine.wait_for_unit("nginx") - machine.wait_for_open_port(443) - machine.succeed("curl -fv https://good.example.com") - - with subtest("Unknown CA is untrusted in curl"): - machine.fail("curl -fv https://bad.example.com") - - browsers = { - "firefox": "Security Risk", - "chromium": "not private", - "qutebrowser -T": "Certificate error", - "midori": "Security" - } - - machine.wait_for_x() - for command, error in browsers.items(): - browser = command.split()[0] - with subtest("Good certificate is trusted in " + browser): - execute_as( - "alice", f"{command} https://good.example.com >&2 &" - ) - wait_for_window_as("alice", browser) - machine.wait_for_text("It works!") - machine.screenshot("good" + browser) - execute_as("alice", "xdotool key ctrl+w") # close tab - - with subtest("Unknown CA is untrusted in " + browser): - execute_as("alice", f"{command} https://bad.example.com >&2 &") - machine.wait_for_text(error) - machine.screenshot("bad" + browser) - machine.succeed("pkill -f " + browser) - ''; -}) + curlTest = makeTest { + name = "custom-ca-curl"; + meta.maintainers = with lib.maintainers; [ rnhmjoj ]; + nodes.machine = { ... }: webserverConfig; + testScript = '' + with subtest("Good certificate is trusted in curl"): + machine.wait_for_unit("nginx") + machine.wait_for_open_port(443) + machine.succeed("curl -fv https://good.example.com") + + with subtest("Unknown CA is untrusted in curl"): + machine.fail("curl -fv https://bad.example.com") + ''; + }; + + mkBrowserTest = browser: testParams: makeTest { + name = "custom-ca-${browser}"; + meta.maintainers = with lib.maintainers; [ rnhmjoj ]; + + enableOCR = true; + + nodes.machine = { pkgs, ... }: + { imports = + [ ./common/user-account.nix + ./common/x11.nix + webserverConfig + ]; + + # chromium-based browsers refuse to run as root + test-support.displayManager.auto.user = "alice"; + + # browsers may hang with the default memory + virtualisation.memorySize = 600; + + environment.systemPackages = [ pkgs.xdotool pkgs.${browser} ]; + }; + + testScript = '' + from typing import Tuple + def execute_as(user: str, cmd: str) -> Tuple[int, str]: + """ + Run a shell command as a specific user. + """ + return machine.execute(f"sudo -u {user} {cmd}") + + + def wait_for_window_as(user: str, cls: str) -> None: + """ + Wait until a X11 window of a given user appears. + """ + + def window_is_visible(last_try: bool) -> bool: + ret, stdout = execute_as(user, f"xdotool search --onlyvisible --class {cls}") + if last_try: + machine.log(f"Last chance to match {cls} on the window list") + return ret == 0 + + with machine.nested("Waiting for a window to appear"): + retry(window_is_visible) + + + machine.start() + machine.wait_for_x() + + command = "${browser} ${testParams.args or ""}" + with subtest("Good certificate is trusted in ${browser}"): + execute_as( + "alice", f"{command} https://good.example.com >&2 &" + ) + wait_for_window_as("alice", "${browser}") + machine.sleep(4) + execute_as("alice", "xdotool key ctrl+r") # reload to be safe + machine.wait_for_text("It works!") + machine.screenshot("good${browser}") + execute_as("alice", "xdotool key ctrl+w") # close tab + + with subtest("Unknown CA is untrusted in ${browser}"): + execute_as("alice", f"{command} https://bad.example.com >&2 &") + machine.wait_for_text("${testParams.error}") + machine.screenshot("bad${browser}") + ''; + }; + +in + +{ + curl = curlTest; +} // pkgs.lib.mapAttrs mkBrowserTest { + firefox = { error = "Security Risk"; }; + chromium = { error = "not private"; }; + qutebrowser = { args = "-T"; error = "Certificate error"; }; + midori = { error = "Security"; }; +} diff --git a/nixos/tests/gitlab.nix b/nixos/tests/gitlab.nix index e1916ed36f315..4f7d3f07f0657 100644 --- a/nixos/tests/gitlab.nix +++ b/nixos/tests/gitlab.nix @@ -1,9 +1,31 @@ -# This test runs gitlab and checks if it works +# This test runs gitlab and performs the following tests: +# - Creating users +# - Pushing commits +# - over the API +# - over SSH +# - Creating Merge Requests and merging them +# - Opening and closing issues. +# - Downloading repository archives as tar.gz and tar.bz2 +import ./make-test-python.nix ({ pkgs, lib, ... }: + +with lib; let + inherit (import ./ssh-keys.nix pkgs) snakeOilPrivateKey snakeOilPublicKey; initialRootPassword = "notproduction"; -in -import ./make-test-python.nix ({ pkgs, lib, ...} : with lib; { + rootProjectId = "2"; + + aliceUsername = "alice"; + aliceUserId = "2"; + alicePassword = "alicepassword"; + aliceProjectId = "2"; + aliceProjectName = "test-alice"; + + bobUsername = "bob"; + bobUserId = "3"; + bobPassword = "bobpassword"; + bobProjectId = "3"; +in { name = "gitlab"; meta = with pkgs.lib.maintainers; { maintainers = [ globin yayayayaka ]; @@ -31,6 +53,8 @@ import ./make-test-python.nix ({ pkgs, lib, ...} : with lib; { }; }; + services.openssh.enable = true; + services.dovecot2 = { enable = true; enableImap = true; @@ -77,8 +101,43 @@ import ./make-test-python.nix ({ pkgs, lib, ...} : with lib; { password = initialRootPassword; }); - createProject = pkgs.writeText "create-project.json" (builtins.toJSON { - name = "test"; + createUserAlice = pkgs.writeText "create-user-alice.json" (builtins.toJSON rec { + username = aliceUsername; + name = username; + email = "alice@localhost"; + password = alicePassword; + skip_confirmation = true; + }); + + createUserBob = pkgs.writeText "create-user-bob.json" (builtins.toJSON rec { + username = bobUsername; + name = username; + email = "bob@localhost"; + password = bobPassword; + skip_confirmation = true; + }); + + aliceAuth = pkgs.writeText "alice-auth.json" (builtins.toJSON { + grant_type = "password"; + username = aliceUsername; + password = alicePassword; + }); + + bobAuth = pkgs.writeText "bob-auth.json" (builtins.toJSON { + grant_type = "password"; + username = bobUsername; + password = bobPassword; + }); + + aliceAddSSHKey = pkgs.writeText "alice-add-ssh-key.json" (builtins.toJSON { + id = aliceUserId; + title = "snakeoil@nixos"; + key = snakeOilPublicKey; + }); + + createProjectAlice = pkgs.writeText "create-project-alice.json" (builtins.toJSON { + name = aliceProjectName; + visibility = "public"; }); putFile = pkgs.writeText "put-file.json" (builtins.toJSON { @@ -89,6 +148,23 @@ import ./make-test-python.nix ({ pkgs, lib, ...} : with lib; { commit_message = "create a new file"; }); + mergeRequest = pkgs.writeText "merge-request.json" (builtins.toJSON { + id = bobProjectId; + target_project_id = aliceProjectId; + source_branch = "master"; + target_branch = "master"; + title = "Add some other file"; + }); + + newIssue = pkgs.writeText "new-issue.json" (builtins.toJSON { + title = "useful issue title"; + }); + + closeIssue = pkgs.writeText "close-issue.json" (builtins.toJSON { + issue_iid = 1; + state_event = "close"; + }); + # Wait for all GitLab services to be fully started. waitForServices = '' gitlab.wait_for_unit("gitaly.service") @@ -105,6 +181,8 @@ import ./make-test-python.nix ({ pkgs, lib, ...} : with lib; { # The actual test of GitLab. Only push data to GitLab if # `doSetup` is is true. test = doSetup: '' + GIT_SSH_COMMAND = "ssh -o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=/dev/null" + gitlab.succeed( "curl -isSf http://gitlab | grep -i location | grep http://gitlab/users/sign_in" ) @@ -115,27 +193,222 @@ import ./make-test-python.nix ({ pkgs, lib, ...} : with lib; { "echo \"Authorization: Bearer $(curl -X POST -H 'Content-Type: application/json' -d @${auth} http://gitlab/oauth/token | ${pkgs.jq}/bin/jq -r '.access_token')\" >/tmp/headers" ) '' + optionalString doSetup '' - gitlab.succeed( - """[ "$(curl -o /dev/null -w '%{http_code}' -X POST -H 'Content-Type: application/json' -H @/tmp/headers -d @${createProject} http://gitlab/api/v4/projects)" = "201" ]""" - ) - gitlab.succeed( - """[ "$(curl -o /dev/null -w '%{http_code}' -X POST -H 'Content-Type: application/json' -H @/tmp/headers -d @${putFile} http://gitlab/api/v4/projects/2/repository/files/some-file.txt)" = "201" ]""" - ) + with subtest("Create user Alice"): + gitlab.succeed( + """[ "$(curl -o /dev/null -w '%{http_code}' -X POST -H 'Content-Type: application/json' -H @/tmp/headers -d @${createUserAlice} http://gitlab/api/v4/users)" = "201" ]""" + ) + gitlab.succeed( + "echo \"Authorization: Bearer $(curl -X POST -H 'Content-Type: application/json' -d @${aliceAuth} http://gitlab/oauth/token | ${pkgs.jq}/bin/jq -r '.access_token')\" >/tmp/headers-alice" + ) + + with subtest("Create user Bob"): + gitlab.succeed( + """ [ "$(curl -o /dev/null -w '%{http_code}' -X POST -H 'Content-Type: application/json' -H @/tmp/headers -d @${createUserBob} http://gitlab/api/v4/users)" = "201" ]""" + ) + gitlab.succeed( + "echo \"Authorization: Bearer $(curl -X POST -H 'Content-Type: application/json' -d @${bobAuth} http://gitlab/oauth/token | ${pkgs.jq}/bin/jq -r '.access_token')\" >/tmp/headers-bob" + ) + + with subtest("Setup Git and SSH for Alice"): + gitlab.succeed("git config --global user.name Alice") + gitlab.succeed("git config --global user.email alice@nixos.invalid") + gitlab.succeed("mkdir -m 700 /root/.ssh") + gitlab.succeed("cat ${snakeOilPrivateKey} > /root/.ssh/id_ecdsa") + gitlab.succeed("chmod 600 /root/.ssh/id_ecdsa") + gitlab.succeed( + """ + [ "$(curl \ + -o /dev/null \ + -w '%{http_code}' \ + -X POST \ + -H 'Content-Type: application/json' \ + -H @/tmp/headers-alice -d @${aliceAddSSHKey} \ + http://gitlab/api/v4/user/keys)" = "201" ] + """ + ) + + with subtest("Create a new repository"): + # Alice creates a new repository + gitlab.succeed( + """ + [ "$(curl \ + -o /dev/null \ + -w '%{http_code}' \ + -X POST \ + -H 'Content-Type: application/json' \ + -H @/tmp/headers-alice \ + -d @${createProjectAlice} \ + http://gitlab/api/v4/projects)" = "201" ] + """ + ) + + # Alice commits an initial commit + gitlab.succeed( + """ + [ "$(curl \ + -o /dev/null \ + -w '%{http_code}' \ + -X POST \ + -H 'Content-Type: application/json' \ + -H @/tmp/headers-alice \ + -d @${putFile} \ + http://gitlab/api/v4/projects/${aliceProjectId}/repository/files/some-file.txt)" = "201" ]""" + ) + + with subtest("git clone over HTTP"): + gitlab.succeed( + """git clone http://gitlab/alice/${aliceProjectName}.git clone-via-http""", + timeout=15 + ) + + with subtest("Push a commit via SSH"): + gitlab.succeed( + f"""GIT_SSH_COMMAND="{GIT_SSH_COMMAND}" git clone gitlab@gitlab:alice/${aliceProjectName}.git""", + timeout=15 + ) + gitlab.succeed( + """echo "a commit sent over ssh" > ${aliceProjectName}/ssh.txt""" + ) + gitlab.succeed( + """ + cd ${aliceProjectName} || exit 1 + git add . + """ + ) + gitlab.succeed( + """ + cd ${aliceProjectName} || exit 1 + git commit -m "Add a commit to be sent over ssh" + """ + ) + gitlab.succeed( + f""" + cd ${aliceProjectName} || exit 1 + GIT_SSH_COMMAND="{GIT_SSH_COMMAND}" git push --set-upstream origin master + """, + timeout=15 + ) + + with subtest("Fork a project"): + # Bob forks Alice's project + gitlab.succeed( + """ + [ "$(curl \ + -o /dev/null \ + -w '%{http_code}' \ + -X POST \ + -H 'Content-Type: application/json' \ + -H @/tmp/headers-bob \ + http://gitlab/api/v4/projects/${aliceProjectId}/fork)" = "201" ] + """ + ) + + # Bob creates a commit + gitlab.wait_until_succeeds( + """ + [ "$(curl \ + -o /dev/null \ + -w '%{http_code}' \ + -X POST \ + -H 'Content-Type: application/json' \ + -H @/tmp/headers-bob \ + -d @${putFile} \ + http://gitlab/api/v4/projects/${bobProjectId}/repository/files/some-other-file.txt)" = "201" ] + """ + ) + + with subtest("Create a Merge Request"): + # Bob opens a merge request against Alice's repository + gitlab.wait_until_succeeds( + """ + [ "$(curl \ + -o /dev/null \ + -w '%{http_code}' \ + -X POST \ + -H 'Content-Type: application/json' \ + -H @/tmp/headers-bob \ + -d @${mergeRequest} \ + http://gitlab/api/v4/projects/${bobProjectId}/merge_requests)" = "201" ] + """ + ) + + # Alice merges the MR + gitlab.wait_until_succeeds( + """ + [ "$(curl \ + -o /dev/null \ + -w '%{http_code}' \ + -X PUT \ + -H 'Content-Type: application/json' \ + -H @/tmp/headers-alice \ + -d @${mergeRequest} \ + http://gitlab/api/v4/projects/${aliceProjectId}/merge_requests/1/merge)" = "200" ] + """ + ) + + with subtest("Create an Issue"): + # Bob opens an issue on Alice's repository + gitlab.succeed( + """[ "$(curl \ + -o /dev/null \ + -w '%{http_code}' \ + -X POST \ + -H 'Content-Type: application/json' \ + -H @/tmp/headers-bob \ + -d @${newIssue} \ + http://gitlab/api/v4/projects/${aliceProjectId}/issues)" = "201" ] + """ + ) + + # Alice closes the issue + gitlab.wait_until_succeeds( + """ + [ "$(curl \ + -o /dev/null \ + -w '%{http_code}' \ + -X PUT \ + -H 'Content-Type: application/json' \ + -H @/tmp/headers-alice -d @${closeIssue} http://gitlab/api/v4/projects/${aliceProjectId}/issues/1)" = "200" ] + """ + ) '' + '' - gitlab.succeed( - """[ "$(curl -o /dev/null -w '%{http_code}' -H @/tmp/headers http://gitlab/api/v4/projects/2/repository/archive.tar.gz)" = "200" ]""" - ) - gitlab.succeed( - """curl -H @/tmp/headers http://gitlab/api/v4/projects/2/repository/archive.tar.gz > /tmp/archive.tar.gz""" - ) - gitlab.succeed( - """[ "$(curl -o /dev/null -w '%{http_code}' -H @/tmp/headers http://gitlab/api/v4/projects/2/repository/archive.tar.bz2)" = "200" ]""" - ) - gitlab.succeed( - """curl -o /dev/null -w '%{http_code}' -H @/tmp/headers http://gitlab/api/v4/projects/2/repository/archive.tar.bz2 > /tmp/archive.tar.bz2""" - ) - gitlab.succeed("test -s /tmp/archive.tar.gz") - gitlab.succeed("test -s /tmp/archive.tar.bz2") + with subtest("Download archive.tar.gz"): + gitlab.succeed( + """ + [ "$(curl \ + -o /dev/null \ + -w '%{http_code}' \ + -H @/tmp/headers-alice \ + http://gitlab/api/v4/projects/${aliceProjectId}/repository/archive.tar.gz)" = "200" ] + """ + ) + gitlab.succeed( + """ + curl \ + -H @/tmp/headers-alice \ + http://gitlab/api/v4/projects/${aliceProjectId}/repository/archive.tar.gz > /tmp/archive.tar.gz + """ + ) + gitlab.succeed("test -s /tmp/archive.tar.gz") + + with subtest("Download archive.tar.bz2"): + gitlab.succeed( + """ + [ "$(curl \ + -o /dev/null \ + -w '%{http_code}' \ + -H @/tmp/headers-alice \ + http://gitlab/api/v4/projects/${aliceProjectId}/repository/archive.tar.bz2)" = "200" ] + """ + ) + gitlab.succeed( + """ + curl \ + -H @/tmp/headers-alice \ + http://gitlab/api/v4/projects/${aliceProjectId}/repository/archive.tar.bz2 > /tmp/archive.tar.bz2 + """ + ) + gitlab.succeed("test -s /tmp/archive.tar.bz2") ''; in '' diff --git a/nixos/tests/installer-systemd-stage-1.nix b/nixos/tests/installer-systemd-stage-1.nix new file mode 100644 index 0000000000000..a8b418626e660 --- /dev/null +++ b/nixos/tests/installer-systemd-stage-1.nix @@ -0,0 +1,33 @@ +{ system ? builtins.currentSystem +, config ? {} +, pkgs ? import ../.. { inherit system config; } +}: + +{ + # Some of these tests don't work with systemd stage 1 yet. Uncomment + # them when fixed. + inherit (import ./installer.nix { inherit system config pkgs; systemdStage1 = true; }) + # bcache + # btrfsSimple + # btrfsSubvolDefault + # btrfsSubvols + # encryptedFSWithKeyfile + # grub1 + # luksroot + # luksroot-format1 + # luksroot-format2 + # lvm + separateBoot + separateBootFat + simple + simpleLabels + simpleProvided + simpleSpecialised + simpleUefiGrub + simpleUefiGrubSpecialisation + simpleUefiSystemdBoot + # swraid + # zfsroot + ; + +} diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix index ea2b2d04ed19d..d8187d8e019d6 100644 --- a/nixos/tests/installer.nix +++ b/nixos/tests/installer.nix @@ -1,6 +1,7 @@ { system ? builtins.currentSystem, config ? {}, - pkgs ? import ../.. { inherit system config; } + pkgs ? import ../.. { inherit system config; }, + systemdStage1 ? false }: with import ../lib/testing-python.nix { inherit system pkgs; }; @@ -23,6 +24,8 @@ let # To ensure that we can rebuild the grub configuration on the nixos-rebuild system.extraDependencies = with pkgs; [ stdenvNoCC ]; + ${optionalString systemdStage1 "boot.initrd.systemd.enable = true;"} + ${optionalString (bootLoader == "grub") '' boot.loader.grub.version = ${toString grubVersion}; ${optionalString (grubVersion == 1) '' @@ -290,6 +293,8 @@ let virtualisation.cores = 8; virtualisation.memorySize = 1536; + boot.initrd.systemd.enable = systemdStage1; + # 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. diff --git a/nixos/tests/kexec.nix b/nixos/tests/kexec.nix index 7e5cc010ef918..7238a9f58e09e 100644 --- a/nixos/tests/kexec.nix +++ b/nixos/tests/kexec.nix @@ -1,5 +1,3 @@ -# Test whether fast reboots via kexec work. - import ./make-test-python.nix ({ pkgs, lib, ... }: { name = "kexec"; meta = with lib.maintainers; { @@ -18,13 +16,16 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: { node2 = { modulesPath, ... }: { virtualisation.vlans = [ ]; + environment.systemPackages = [ pkgs.hello ]; imports = [ "${modulesPath}/installer/kexec/kexec-boot.nix" + "${modulesPath}/profiles/minimal.nix" ]; }; }; testScript = { nodes, ... }: '' + # Test whether reboot via kexec works. node1.wait_for_unit("multi-user.target") node1.succeed('kexec --load /run/current-system/kernel --initrd /run/current-system/initrd --command-line "$(</proc/cmdline)"') node1.execute("systemctl kexec >&2 &", check_return=False) @@ -32,14 +33,17 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: { node1.connect() node1.wait_for_unit("multi-user.target") - # Check the machine with kexec-boot.nix profile boots up + # Check if the machine with kexec-boot.nix profile boots up node2.wait_for_unit("multi-user.target") node2.shutdown() # Kexec node1 to the toplevel of node2 via the kexec-boot script node1.succeed('touch /run/foo') + node1.fail('hello') node1.execute('${nodes.node2.config.system.build.kexecBoot}/kexec-boot', check_return=False) node1.succeed('! test -e /run/foo') + node1.succeed('hello') + node1.succeed('[ "$(hostname)" = "node2" ]') node1.shutdown() ''; diff --git a/nixos/tests/lxd.nix b/nixos/tests/lxd.nix index 81b36124cc6b2..162bbcc47e871 100644 --- a/nixos/tests/lxd.nix +++ b/nixos/tests/lxd.nix @@ -6,16 +6,47 @@ let # # I've chosen to import Alpine Linux, because its image is turbo-tiny and, # generally, sufficient for our tests. - alpine-meta = pkgs.fetchurl { + alpine-meta-x86 = pkgs.fetchurl { url = "https://tarballs.nixos.org/alpine/3.12/lxd.tar.xz"; hash = "sha256-1tcKaO9lOkvqfmG/7FMbfAEToAuFy2YMewS8ysBKuLA="; }; + alpine-meta-for = arch: pkgs.stdenv.mkDerivation { + name = "alpine-meta-${arch}"; + version = "3.12"; + unpackPhase = "true"; + buildPhase = '' + runHook preBuild - alpine-rootfs = pkgs.fetchurl { - url = "https://tarballs.nixos.org/alpine/3.12/rootfs.tar.xz"; - hash = "sha256-Tba9sSoaiMtQLY45u7p5DMqXTSDgs/763L/SQp0bkCA="; + tar xvf ${alpine-meta-x86} + sed -i 's/architecture: .*/architecture: ${arch}/' metadata.yaml + + runHook postBuild + ''; + installPhase = '' + runHook preInstall + + tar czRf $out * + + runHook postInstall + ''; }; + alpine-meta = { + x86_64-linux = alpine-meta-x86; + aarch64-linux = alpine-meta-for "aarch64"; + }.${pkgs.system} or (throw "Unsupported system: ${pkgs.system}"); + + alpine-rootfs = { + x86_64-linux = pkgs.fetchurl { + url = "https://tarballs.nixos.org/alpine/3.12/rootfs.tar.xz"; + hash = "sha256-Tba9sSoaiMtQLY45u7p5DMqXTSDgs/763L/SQp0bkCA="; + }; + aarch64-linux = pkgs.fetchurl { + url = "https://dl-cdn.alpinelinux.org/alpine/v3.15/releases/aarch64/alpine-minirootfs-3.15.4-aarch64.tar.gz"; + hash = "sha256-9kBz8Jwmo8XepJhTMt5zilCaHHpflnUH7y9+0To39Us="; + }; + }.${pkgs.system} or (throw "Unsupported system: ${pkgs.system}"); + lxd-config = pkgs.writeText "config.yaml" '' storage_pools: - name: default diff --git a/nixos/tests/systemd-initrd-btrfs-raid.nix b/nixos/tests/systemd-initrd-btrfs-raid.nix new file mode 100644 index 0000000000000..40fd2d4dc611c --- /dev/null +++ b/nixos/tests/systemd-initrd-btrfs-raid.nix @@ -0,0 +1,45 @@ +import ./make-test-python.nix ({ lib, pkgs, ... }: { + name = "systemd-initrd-btrfs-raid"; + + nodes.machine = { pkgs, ... }: { + # Use systemd-boot + virtualisation = { + emptyDiskImages = [ 512 512 ]; + useBootLoader = true; + useEFIBoot = true; + }; + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + + environment.systemPackages = with pkgs; [ btrfs-progs ]; + boot.initrd.systemd = { + enable = true; + emergencyAccess = true; + }; + + specialisation.boot-btrfs-raid.configuration = { + fileSystems = lib.mkVMOverride { + "/".fsType = lib.mkForce "btrfs"; + }; + virtualisation.bootDevice = "/dev/vdc"; + }; + }; + + testScript = '' + # Create RAID + machine.succeed("mkfs.btrfs -d raid0 /dev/vdc /dev/vdd") + machine.succeed("mkdir -p /mnt && mount /dev/vdc /mnt && echo hello > /mnt/test && umount /mnt") + + # Boot from the RAID + machine.succeed("bootctl set-default nixos-generation-1-specialisation-boot-btrfs-raid.conf") + machine.succeed("sync") + machine.crash() + machine.wait_for_unit("multi-user.target") + + # Ensure we have successfully booted from the RAID + assert "(initrd)" in machine.succeed("systemd-analyze") # booted with systemd in stage 1 + assert "/dev/vdc on / type btrfs" in machine.succeed("mount") + assert "hello" in machine.succeed("cat /test") + assert "Total devices 2" in machine.succeed("btrfs filesystem show") + ''; +}) diff --git a/nixos/tests/systemd-initrd-luks-keyfile.nix b/nixos/tests/systemd-initrd-luks-keyfile.nix index 970163c36a4fc..25c0c5bd866d3 100644 --- a/nixos/tests/systemd-initrd-luks-keyfile.nix +++ b/nixos/tests/systemd-initrd-luks-keyfile.nix @@ -32,7 +32,7 @@ in { }; }; virtualisation.bootDevice = "/dev/mapper/cryptroot"; - boot.initrd.systemd.contents."/etc/cryptroot.key".source = keyfile; + boot.initrd.secrets."/etc/cryptroot.key" = keyfile; }; }; diff --git a/nixos/tests/systemd-shutdown.nix b/nixos/tests/systemd-shutdown.nix index 9283489c25591..688cd6dd2c175 100644 --- a/nixos/tests/systemd-shutdown.nix +++ b/nixos/tests/systemd-shutdown.nix @@ -1,4 +1,6 @@ -import ./make-test-python.nix ({ pkgs, systemdStage1 ? false, ...} : { +import ./make-test-python.nix ({ pkgs, systemdStage1 ? false, ...} : let + msg = "Shutting down NixOS"; +in { name = "systemd-shutdown"; meta = with pkgs.lib.maintainers; { maintainers = [ das_j ]; @@ -6,7 +8,9 @@ import ./make-test-python.nix ({ pkgs, systemdStage1 ? false, ...} : { nodes.machine = { imports = [ ../modules/profiles/minimal.nix ]; - boot.initrd.systemd.enable = systemdStage1; + systemd.shutdownRamfs.contents."/etc/systemd/system-shutdown/shutdown-message".source = pkgs.writeShellScript "shutdown-message" '' + echo "${msg}" + ''; }; testScript = '' @@ -14,7 +18,8 @@ import ./make-test-python.nix ({ pkgs, systemdStage1 ? false, ...} : { # .shutdown() would wait for the machine to power off machine.succeed("systemctl poweroff") # Message printed by systemd-shutdown - machine.wait_for_console_text("All filesystems, swaps, loop devices, MD devices and DM devices detached.") + machine.wait_for_console_text("Unmounting '/oldroot'") + machine.wait_for_console_text("${msg}") # Don't try to sync filesystems machine.booted = False ''; |