diff options
Diffstat (limited to 'nixos')
143 files changed, 2211 insertions, 685 deletions
diff --git a/nixos/doc/manual/configuration/configuration.xml b/nixos/doc/manual/configuration/configuration.xml index 44ff1f1b571a7..6949189b8883c 100644 --- a/nixos/doc/manual/configuration/configuration.xml +++ b/nixos/doc/manual/configuration/configuration.xml @@ -23,6 +23,7 @@ <xi:include href="xfce.xml" /> <xi:include href="networking.xml" /> <xi:include href="linux-kernel.xml" /> + <xi:include href="subversion.xml" /> <xi:include href="../generated/modules.xml" xpointer="xpointer(//section[@id='modules']/*)" /> <xi:include href="profiles.xml" /> <xi:include href="kubernetes.xml" /> diff --git a/nixos/doc/manual/configuration/gpu-accel.xml b/nixos/doc/manual/configuration/gpu-accel.xml index 95ee13f4796e8..3695a5ff445a4 100644 --- a/nixos/doc/manual/configuration/gpu-accel.xml +++ b/nixos/doc/manual/configuration/gpu-accel.xml @@ -65,16 +65,16 @@ Platform Vendor Advanced Micro Devices, Inc.</screen> <title>AMD</title> <para> - Modern AMD <link - xlink:href="https://en.wikipedia.org/wiki/Graphics_Core_Next">Graphics - Core Next</link> (GCN) GPUs are supported through the - <package>rocm-opencl-icd</package> package. Adding this package to - <xref linkend="opt-hardware.opengl.extraPackages"/> enables OpenCL - support: - - <programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [ - rocm-opencl-icd -];</programlisting> + Modern AMD <link + xlink:href="https://en.wikipedia.org/wiki/Graphics_Core_Next">Graphics + Core Next</link> (GCN) GPUs are supported through the + <package>rocm-opencl-icd</package> package. Adding this package to + <xref linkend="opt-hardware.opengl.extraPackages"/> enables OpenCL + support: + + <programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [ + rocm-opencl-icd + ];</programlisting> </para> </section> @@ -100,9 +100,9 @@ Platform Vendor Advanced Micro Devices, Inc.</screen> support. For example, for Gen8 and later GPUs, the following configuration can be used: - <programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [ - intel-compute-runtime -];</programlisting> + <programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [ + intel-compute-runtime + ];</programlisting> </para> </section> @@ -173,31 +173,31 @@ GPU1: <title>AMD</title> <para> - Modern AMD <link - xlink:href="https://en.wikipedia.org/wiki/Graphics_Core_Next">Graphics - Core Next</link> (GCN) GPUs are supported through either radv, which is - part of <package>mesa</package>, or the <package>amdvlk</package> package. - Adding the <package>amdvlk</package> package to - <xref linkend="opt-hardware.opengl.extraPackages"/> makes both drivers - available for applications and lets them choose. A specific driver can - be forced as follows: - - <programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [ - pkgs.<package>amdvlk</package> -]; - -# To enable Vulkan support for 32-bit applications, also add: -<xref linkend="opt-hardware.opengl.extraPackages32"/> = [ - pkgs.driversi686Linux.<package>amdvlk</package> -]; - -# For amdvlk -<xref linkend="opt-environment.variables"/>.VK_ICD_FILENAMES = - "/run/opengl-driver/share/vulkan/icd.d/amd_icd64.json"; -# For radv -<xref linkend="opt-environment.variables"/>.VK_ICD_FILENAMES = - "/run/opengl-driver/share/vulkan/icd.d/radeon_icd.x86_64.json"; -</programlisting> + Modern AMD <link + xlink:href="https://en.wikipedia.org/wiki/Graphics_Core_Next">Graphics + Core Next</link> (GCN) GPUs are supported through either radv, which is + part of <package>mesa</package>, or the <package>amdvlk</package> package. + Adding the <package>amdvlk</package> package to + <xref linkend="opt-hardware.opengl.extraPackages"/> makes both drivers + available for applications and lets them choose. A specific driver can + be forced as follows: + + <programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [ + pkgs.<package>amdvlk</package> + ]; + + # To enable Vulkan support for 32-bit applications, also add: + <xref linkend="opt-hardware.opengl.extraPackages32"/> = [ + pkgs.driversi686Linux.<package>amdvlk</package> + ]; + + # For amdvlk + <xref linkend="opt-environment.variables"/>.VK_ICD_FILENAMES = + "/run/opengl-driver/share/vulkan/icd.d/amd_icd64.json"; + # For radv + <xref linkend="opt-environment.variables"/>.VK_ICD_FILENAMES = + "/run/opengl-driver/share/vulkan/icd.d/radeon_icd.x86_64.json"; + </programlisting> </para> </section> </section> diff --git a/nixos/doc/manual/configuration/subversion.xml b/nixos/doc/manual/configuration/subversion.xml new file mode 100644 index 0000000000000..940d63cc4e6de --- /dev/null +++ b/nixos/doc/manual/configuration/subversion.xml @@ -0,0 +1,140 @@ +<chapter xmlns="http://docbook.org/ns/docbook" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xi="http://www.w3.org/2001/XInclude" + version="5.0" + xml:id="module-services-subversion"> + <title>Subversion</title> + + <para> + <link xlink:href="https://subversion.apache.org/">Subversion</link> + is a centralized version-control system. It can use a <link + xlink:href="http://svnbook.red-bean.com/en/1.7/svn-book.html#svn.serverconfig.choosing">variety + of protocols</link> for communication between client and server. + </para> + <section xml:id="module-services-subversion-apache-httpd"> + <title>Subversion inside Apache HTTP</title> + + <para> + This section focuses on configuring a web-based server on top of + the Apache HTTP server, which uses + <link xlink:href="http://www.webdav.org/">WebDAV</link>/<link + xlink:href="http://www.webdav.org/deltav/WWW10/deltav-intro.htm">DeltaV</link> + for communication. + </para> + + <para>For more information on the general setup, please refer to + the <link + xlink:href="http://svnbook.red-bean.com/en/1.7/svn-book.html#svn.serverconfig.httpd">the + appropriate section of the Subversion book</link>. + </para> + + <para>To configure, include in + <literal>/etc/nixos/configuration.nix</literal> code to activate + Apache HTTP, setting <xref linkend="opt-services.httpd.adminAddr" /> + appropriately: + </para> + + <para> +<programlisting> + services.httpd.enable = true; + services.httpd.adminAddr = ...; + networking.firewall.allowedTCPPorts = [ 80 443 ]; +</programlisting> + </para> + + <para>For a simple Subversion server with basic authentication, + configure the Subversion module for Apache as follows, setting + <literal>hostName</literal> and <literal>documentRoot</literal> + appropriately, and <literal>SVNParentPath</literal> to the parent + directory of the repositories, + <literal>AuthzSVNAccessFile</literal> to the location of the + <code>.authz</code> file describing access permission, and + <literal>AuthUserFile</literal> to the password file. + </para> + <para> +<programlisting> +services.httpd.extraModules = [ + # note that order is *super* important here + { name = "dav_svn"; path = "${pkgs.apacheHttpdPackages.subversion}/modules/mod_dav_svn.so"; } + { name = "authz_svn"; path = "${pkgs.apacheHttpdPackages.subversion}/modules/mod_authz_svn.so"; } + ]; + services.httpd.virtualHosts = { + "svn" = { + hostName = HOSTNAME; + documentRoot = DOCUMENTROOT; + locations."/svn".extraConfig = '' + DAV svn + SVNParentPath REPO_PARENT + AuthzSVNAccessFile ACCESS_FILE + AuthName "SVN Repositories" + AuthType Basic + AuthUserFile PASSWORD_FILE + Require valid-user + ''; + } +</programlisting> + </para> + + <para> + The key <code>"svn"</code> is just a symbolic name identifying the + virtual host. The <code>"/svn"</code> in + <code>locations."/svn".extraConfig</code> is the path underneath + which the repositories will be served. + </para> + + <para><link + xlink:href="https://wiki.archlinux.org/index.php/Subversion">This + page</link> explains how to set up the Subversion configuration + itself. This boils down to the following: + </para> + <para> + Underneath <literal>REPO_PARENT</literal> repositories can be set up + as follows: + </para> + <para> +<screen> +<prompt>$ </prompt> svn create REPO_NAME +</screen> + </para> + <para>Repository files need to be accessible by + <literal>wwwrun</literal>: + </para> + <para> +<screen> +<prompt>$ </prompt> chown -R wwwrun:wwwrun REPO_PARENT +</screen> + </para> + <para> + The password file <literal>PASSWORD_FILE</literal> can be created as follows: + </para> + <para> +<screen> +<prompt>$ </prompt> htpasswd -cs PASSWORD_FILE USER_NAME +</screen> + </para> + <para> + Additional users can be set up similarly, omitting the + <code>c</code> flag: + </para> + <para> +<screen> +<prompt>$ </prompt> htpasswd -s PASSWORD_FILE USER_NAME +</screen> + </para> + <para> + The file describing access permissions + <literal>ACCESS_FILE</literal> will look something like + the following: + </para> + <para> +<programlisting> +[/] +* = r + +[REPO_NAME:/] +USER_NAME = rw +</programlisting> + </para> + <para>The Subversion repositories will be accessible as <code>http://HOSTNAME/svn/REPO_NAME</code>.</para> + </section> +</chapter> diff --git a/nixos/doc/manual/contributing-to-this-manual.xml b/nixos/doc/manual/contributing-to-this-manual.xml index 9820e75fc337b..935dd66bc141c 100644 --- a/nixos/doc/manual/contributing-to-this-manual.xml +++ b/nixos/doc/manual/contributing-to-this-manual.xml @@ -12,7 +12,7 @@ xlink:href="https://github.com/NixOS/nixpkgs">Nixpkgs</link> repository. You can quickly check your edits with the following: </para> <screen> -<prompt>$ </prompt>cd /path/to/nixpkgs/nixos/doc/manual +<prompt>$ </prompt>cd /path/to/nixpkgs <prompt>$ </prompt>nix-build nixos/release.nix -A manual.x86_64-linux </screen> <para> diff --git a/nixos/doc/manual/installation/installing-from-other-distro.xml b/nixos/doc/manual/installation/installing-from-other-distro.xml index f10a7d6588798..43f69b923d14d 100644 --- a/nixos/doc/manual/installation/installing-from-other-distro.xml +++ b/nixos/doc/manual/installation/installing-from-other-distro.xml @@ -161,6 +161,13 @@ nixpkgs https://nixos.org/channels/nixpkgs-unstable</screen> existing systems without the help of a rescue USB drive or similar. </para> </warning> + <note> + <para> + On some distributions there are separate PATHS for programs intended only for root. + In order for the installation to succeed, you might have to use <literal>PATH="$PATH:/usr/sbin:/sbin"</literal> + in the following command. + </para> + </note> <screen><prompt>$ </prompt>sudo PATH="$PATH" NIX_PATH="$NIX_PATH" `which nixos-install` --root /mnt</screen> <para> Again, please refer to the <literal>nixos-install</literal> step in diff --git a/nixos/doc/manual/release-notes/rl-2009.xml b/nixos/doc/manual/release-notes/rl-2009.xml index 75c8adbf45ed2..afb09d7c5d262 100644 --- a/nixos/doc/manual/release-notes/rl-2009.xml +++ b/nixos/doc/manual/release-notes/rl-2009.xml @@ -234,7 +234,17 @@ </listitem> </itemizedlist> </listitem> - + <listitem> + <para> + Starting with this release, the hydra-build-result + <literal>nixos-<replaceable>YY.MM</replaceable></literal> + branches no longer exist in the <link + xlink:href="https://github.com/nixos/nixpkgs-channels">deprecated + nixpkgs-channels repository</link>. These branches are now in + <link xlink:href="https://github.com/nixos/nixpkgs">the main nixpkgs + repository</link>. + </para> + </listitem> </itemizedlist> </section> @@ -1593,30 +1603,30 @@ services.transmission.settings.rpc-bind-address = "0.0.0.0"; <para> Agda has been heavily reworked. <itemizedlist> - <listitem> - <para> - <literal>agda.mkDerivation</literal> has been heavily changed and - is now located at <package>agdaPackages.mkDerivation</package>. - </para> - </listitem> - <listitem> - <para> - New top-level packages <package>agda</package> and - <literal>agda.withPackages</literal> have been added, the second - of which sets up agda with access to chosen libraries. - </para> - </listitem> - <listitem> - <para> - All agda libraries now live under - <literal>agdaPackages</literal>. - </para> - </listitem> - <listitem> - <para> - Many broken libraries have been removed. - </para> - </listitem> + <listitem> + <para> + <literal>agda.mkDerivation</literal> has been heavily changed and + is now located at <package>agdaPackages.mkDerivation</package>. + </para> + </listitem> + <listitem> + <para> + New top-level packages <package>agda</package> and + <literal>agda.withPackages</literal> have been added, the second + of which sets up agda with access to chosen libraries. + </para> + </listitem> + <listitem> + <para> + All agda libraries now live under + <literal>agdaPackages</literal>. + </para> + </listitem> + <listitem> + <para> + Many broken libraries have been removed. + </para> + </listitem> </itemizedlist> See the <link xlink:href="https://nixos.org/nixpkgs/manual/#agda">new diff --git a/nixos/doc/manual/release-notes/rl-2103.xml b/nixos/doc/manual/release-notes/rl-2103.xml index 709b2ba5228f8..3186eb7449fe6 100644 --- a/nixos/doc/manual/release-notes/rl-2103.xml +++ b/nixos/doc/manual/release-notes/rl-2103.xml @@ -56,6 +56,11 @@ section of the NixOS manual</link> for more information. </para> </listitem> + <listitem> + <para> + <xref linkend="opt-services.samba-wsdd.enable" /> Web Services Dynamic Discovery host daemon + </para> + </listitem> </itemizedlist> </section> @@ -90,6 +95,25 @@ </para> </listitem> <listitem> + <para> + <literal>rubyMinimal</literal> was removed due to being unused and + unusable. The default ruby interpreter includes JIT support, which makes + it reference it's compiler. Since JIT support is probably needed by some + Gems, it was decided to enable this feature with all cc references by + default, and allow to build a Ruby derivation without references to cc, + by setting <literal>jitSupport = false;</literal> in an overlay. See + <link xlink:href="https://github.com/NixOS/nixpkgs/pull/90151">#90151</link> + for more info. + </para> + </listitem> + <listitem> + <para> + Setting <option>services.openssh.authorizedKeysFiles</option> now also affects which keys <option>security.pam.enableSSHAgentAuth</option> will use. + + WARNING: If you are using these options in combination do make sure that any key paths you use are present in <option>services.openssh.authorizedKeysFiles</option>! + </para> + </listitem> + <listitem> <para> The option <option>fonts.enableFontDir</option> has been renamed to <xref linkend="opt-fonts.fontDir.enable"/>. The path of font directory @@ -116,6 +140,13 @@ </listitem> <listitem> <para> + Paperwork was updated to version 2. The on-disk format slightly changed, + and it is not possible to downgrade from Paperwork 2 back to Paperwork + 1.3. Back your documents up before upgrading. See <link xlink:href="https://forum.openpaper.work/t/paperwork-2-0/112/5">this thread</link> for more details. + </para> + </listitem> + <listitem> + <para> PowerDNS has been updated from <literal>4.2.x</literal> to <literal>4.3.x</literal>. Please be sure to review the <link xlink:href="https://doc.powerdns.com/authoritative/upgrading.html#x-to-4-3-0">Upgrade Notes</link> provided by upstream before upgrading. Worth specifically noting is that the service now runs @@ -146,6 +177,68 @@ <link xlink:href="http://www.mutt.org/relnotes/2.0/">release notes for Mutt 2.0</link>. </para> </listitem> + <listitem> + <para> + <literal>vim</literal> switched to Python 3, dropping all Python 2 support. + </para> + </listitem> + <listitem> + <para> + <link linkend="opt-boot.zfs.forceImportAll">boot.zfs.forceImportAll</link> + previously did nothing, but has been fixed. However its default has been + changed to <literal>false</literal> to preserve the existing default + behaviour. If you have this explicitly set to <literal>true</literal>, + please note that your non-root pools will now be forcibly imported. + </para> + </listitem> + <listitem> + <para> + <package>openafs</package> now points to <package>openafs_1_8</package>, + which is the new stable release. OpenAFS 1.6 was removed. + </para> + </listitem> + <listitem> + <para> + The <literal>openldap</literal> module now has support for OLC-style + configuration, users of the <literal>configDir</literal> option may wish + to migrate. If you continue to use <literal>configDir</literal>, ensure that + <literal>olcPidFile</literal> is set to <literal>/run/slapd/slapd.pid</literal>. + </para> + <para> + As a result, <literal>extraConfig</literal> and <literal>extraDatabaseConfig</literal> + are removed. To help with migration, you can convert your <literal>slapd.conf</literal> + file to OLC configuration with the following script (find the location of this + configuration file by running <literal>systemctl status openldap</literal>, it is the + <literal>-f</literal> option. + </para> + <programlisting> + TMPDIR=$(mktemp -d) + slaptest -f /path/to/slapd.conf $TMPDIR + slapcat -F $TMPDIR -n0 -H 'ldap:///???(!(objectClass=olcSchemaConfig))' + </programlisting> + <para> + This will dump your current configuration in LDIF format, which should be + straightforward to convert into Nix settings. This does not show your schema + configuration, as this is unnecessarily verbose for users of the default schemas + and <literal>slaptest</literal> is buggy with schemas directly in the config file. + </para> + </listitem> + <listitem> + <para> + Amazon EC2 and OpenStack Compute (nova) images now re-fetch instance meta data and user data from the instance + metadata service (IMDS) on each boot. For example: stopping an EC2 instance, changing its user data, and + restarting the instance will now cause it to fetch and apply the new user data. + </para> + <warning> + <para> + Specifically, <literal>/etc/ec2-metadata</literal> is re-populated on each boot. Some NixOS scripts that read + from this directory are guarded to only run if the files they want to manipulate do not already exist, and so + will not re-apply their changes if the IMDS response changes. Examples: <literal>root</literal>'s SSH key is + only added if <literal>/root/.ssh/authorized_keys</literal> does not exist, and SSH host keys are only set from + user data if they do not exist in <literal>/etc/ssh</literal>. + </para> + </warning> + </listitem> </itemizedlist> </section> diff --git a/nixos/doc/varlistentry-fixer.rb b/nixos/doc/varlistentry-fixer.rb index 6c7cc1e6439b1..02168016b554b 100755 --- a/nixos/doc/varlistentry-fixer.rb +++ b/nixos/doc/varlistentry-fixer.rb @@ -15,8 +15,8 @@ require "rexml/document" include REXML if ARGV.length < 1 then - $stderr.puts "Needs a filename." - exit 1 + $stderr.puts "Needs a filename." + exit 1 end filename = ARGV.shift @@ -51,17 +51,17 @@ $touched = false # Generates: --optionnamevalue # ^^ ^^ doc.elements.each("//varlistentry/term") do |term| - ["varname", "function", "option", "replaceable"].each do |prev_name| - term.elements.each(prev_name) do |el| - if el.next_element and - el.next_element.name == "replaceable" and - el.next_sibling_node.class == Element - then - $touched = true - term.insert_after(el, Text.new(" ")) - end - end - end + ["varname", "function", "option", "replaceable"].each do |prev_name| + term.elements.each(prev_name) do |el| + if el.next_element and + el.next_element.name == "replaceable" and + el.next_sibling_node.class == Element + then + $touched = true + term.insert_after(el, Text.new(" ")) + end + end + end end @@ -75,17 +75,17 @@ end # Generates: -Ipath # ^^ doc.elements.each("//cmdsynopsis/arg") do |term| - ["option", "replaceable"].each do |prev_name| - term.elements.each(prev_name) do |el| - if el.next_element and - el.next_element.name == "replaceable" and - el.next_sibling_node.class == Element - then - $touched = true - term.insert_after(el, Text.new(" ")) - end - end - end + ["option", "replaceable"].each do |prev_name| + term.elements.each(prev_name) do |el| + if el.next_element and + el.next_element.name == "replaceable" and + el.next_sibling_node.class == Element + then + $touched = true + term.insert_after(el, Text.new(" ")) + end + end + end end # <cmdsynopsis> @@ -104,21 +104,21 @@ end # Generates: [{--profile-name | -p }name] # ^^^^ doc.elements.each("//cmdsynopsis/arg") do |term| - ["group"].each do |prev_name| - term.elements.each(prev_name) do |el| - if el.next_element and - el.next_element.name == "replaceable" and - el.next_sibling_node.class == Element - then - $touched = true - term.insert_after(el, Text.new(" ")) - end - end - end + ["group"].each do |prev_name| + term.elements.each(prev_name) do |el| + if el.next_element and + el.next_element.name == "replaceable" and + el.next_sibling_node.class == Element + then + $touched = true + term.insert_after(el, Text.new(" ")) + end + end + end end if $touched then - doc.context[:attribute_quote] = :quote - doc.write(output: File.open(filename, "w")) + doc.context[:attribute_quote] = :quote + doc.write(output: File.open(filename, "w")) end diff --git a/nixos/lib/make-disk-image.nix b/nixos/lib/make-disk-image.nix index a4a488a1b3ea9..0ad0cf1fef5af 100644 --- a/nixos/lib/make-disk-image.nix +++ b/nixos/lib/make-disk-image.nix @@ -134,7 +134,7 @@ let format' = format; in let binPath = with pkgs; makeBinPath ( [ rsync - utillinux + util-linux parted e2fsprogs lkl @@ -239,7 +239,7 @@ let format' = format; in let in pkgs.vmTools.runInLinuxVM ( pkgs.runCommand name { preVM = prepareImage; - buildInputs = with pkgs; [ utillinux e2fsprogs dosfstools ]; + buildInputs = with pkgs; [ util-linux e2fsprogs dosfstools ]; postVM = '' ${if format == "raw" then '' mv $diskImage $out/${filename} diff --git a/nixos/lib/make-iso9660-image.nix b/nixos/lib/make-iso9660-image.nix index 6a0e0e7c635a4..549530965f6e1 100644 --- a/nixos/lib/make-iso9660-image.nix +++ b/nixos/lib/make-iso9660-image.nix @@ -48,7 +48,7 @@ assert usbBootable -> isohybridMbrImage != ""; stdenv.mkDerivation { name = isoName; builder = ./make-iso9660-image.sh; - buildInputs = [ xorriso syslinux zstd libossp_uuid ]; + nativeBuildInputs = [ xorriso syslinux zstd libossp_uuid ]; inherit isoName bootable bootImage compressImage volumeID efiBootImage efiBootable isohybridMbrImage usbBootable; diff --git a/nixos/lib/make-system-tarball.nix b/nixos/lib/make-system-tarball.nix index dee91a6ce3f49..dab168f4a4813 100644 --- a/nixos/lib/make-system-tarball.nix +++ b/nixos/lib/make-system-tarball.nix @@ -37,7 +37,7 @@ in stdenv.mkDerivation { name = "tarball"; builder = ./make-system-tarball.sh; - buildInputs = extraInputs; + nativeBuildInputs = extraInputs; inherit fileName extraArgs extraCommands compressCommand; diff --git a/nixos/lib/test-driver/test-driver.py b/nixos/lib/test-driver/test-driver.py index 68bd35dd98e93..96b75a49928f0 100644 --- a/nixos/lib/test-driver/test-driver.py +++ b/nixos/lib/test-driver/test-driver.py @@ -634,8 +634,7 @@ class Machine: shutil.copy(intermediate, abs_target) def dump_tty_contents(self, tty: str) -> None: - """Debugging: Dump the contents of the TTY<n> - """ + """Debugging: Dump the contents of the TTY<n>""" self.execute("fold -w 80 /dev/vcs{} | systemd-cat".format(tty)) def get_screen_text(self) -> str: @@ -860,8 +859,7 @@ class Machine: self.send_monitor_command("set_link virtio-net-pci.1 off") def unblock(self) -> None: - """Make the machine reachable. - """ + """Make the machine reachable.""" self.send_monitor_command("set_link virtio-net-pci.1 on") diff --git a/nixos/modules/config/malloc.nix b/nixos/modules/config/malloc.nix index 31a659ee83fe9..a3eb55d8a42e8 100644 --- a/nixos/modules/config/malloc.nix +++ b/nixos/modules/config/malloc.nix @@ -23,7 +23,7 @@ let }; scudo = { - libPath = "${pkgs.llvmPackages.compiler-rt}/lib/linux/libclang_rt.scudo-x86_64.so"; + libPath = "${pkgs.llvmPackages_latest.compiler-rt}/lib/linux/libclang_rt.scudo-x86_64.so"; description = '' A user-mode allocator based on LLVM Sanitizer’s CombinedAllocator, which aims at providing additional mitigations against heap based diff --git a/nixos/modules/config/pulseaudio.nix b/nixos/modules/config/pulseaudio.nix index 044fa48853db4..a77524d75d8dc 100644 --- a/nixos/modules/config/pulseaudio.nix +++ b/nixos/modules/config/pulseaudio.nix @@ -263,7 +263,7 @@ in { (drv: drv.override { pulseaudio = overriddenPackage; }) cfg.extraModules; modulePaths = builtins.map - (drv: "${drv}/lib/pulse-${overriddenPackage.version}/modules") + (drv: "${drv}/${overriddenPackage.pulseDir}/modules") # User-provided extra modules take precedence (overriddenModules ++ [ overriddenPackage ]); in lib.concatStringsSep ":" modulePaths; diff --git a/nixos/modules/config/swap.nix b/nixos/modules/config/swap.nix index adb4e2294213d..4bb66e9b51449 100644 --- a/nixos/modules/config/swap.nix +++ b/nixos/modules/config/swap.nix @@ -187,7 +187,7 @@ in before = [ "${realDevice'}.swap" ]; # If swap is encrypted, depending on rngd resolves a possible entropy starvation during boot after = mkIf (config.security.rngd.enable && sw.randomEncryption.enable) [ "rngd.service" ]; - path = [ pkgs.utillinux ] ++ optional sw.randomEncryption.enable pkgs.cryptsetup; + path = [ pkgs.util-linux ] ++ optional sw.randomEncryption.enable pkgs.cryptsetup; script = '' diff --git a/nixos/modules/config/system-path.nix b/nixos/modules/config/system-path.nix index c65fa1a684f8e..27d1cef849bc0 100644 --- a/nixos/modules/config/system-path.nix +++ b/nixos/modules/config/system-path.nix @@ -37,7 +37,7 @@ let pkgs.procps pkgs.su pkgs.time - pkgs.utillinux + pkgs.util-linux pkgs.which pkgs.zstd ]; diff --git a/nixos/modules/config/update-users-groups.pl b/nixos/modules/config/update-users-groups.pl index e220aa6109081..fd3affae899cc 100644 --- a/nixos/modules/config/update-users-groups.pl +++ b/nixos/modules/config/update-users-groups.pl @@ -16,8 +16,7 @@ my $gidMap = -e $gidMapFile ? decode_json(read_file($gidMapFile)) : {}; sub updateFile { my ($path, $contents, $perms) = @_; - write_file("$path.tmp", { binmode => ':utf8', perms => $perms // 0644 }, $contents); - rename("$path.tmp", $path) or die; + write_file($path, { atomic => 1, binmode => ':utf8', perms => $perms // 0644 }, $contents) or die; } @@ -98,7 +97,7 @@ sub parseGroup { return ($f[0], { name => $f[0], password => $f[1], gid => $gid, members => $f[3] }); } -my %groupsCur = -f "/etc/group" ? map { parseGroup } read_file("/etc/group") : (); +my %groupsCur = -f "/etc/group" ? map { parseGroup } read_file("/etc/group", { binmode => ":utf8" }) : (); # Read the current /etc/passwd. sub parseUser { @@ -109,20 +108,19 @@ sub parseUser { return ($f[0], { name => $f[0], fakePassword => $f[1], uid => $uid, gid => $f[3], description => $f[4], home => $f[5], shell => $f[6] }); } - -my %usersCur = -f "/etc/passwd" ? map { parseUser } read_file("/etc/passwd") : (); +my %usersCur = -f "/etc/passwd" ? map { parseUser } read_file("/etc/passwd", { binmode => ":utf8" }) : (); # Read the groups that were created declaratively (i.e. not by groups) # in the past. These must be removed if they are no longer in the # current spec. my $declGroupsFile = "/var/lib/nixos/declarative-groups"; my %declGroups; -$declGroups{$_} = 1 foreach split / /, -e $declGroupsFile ? read_file($declGroupsFile) : ""; +$declGroups{$_} = 1 foreach split / /, -e $declGroupsFile ? read_file($declGroupsFile, { binmode => ":utf8" }) : ""; # Idem for the users. my $declUsersFile = "/var/lib/nixos/declarative-users"; my %declUsers; -$declUsers{$_} = 1 foreach split / /, -e $declUsersFile ? read_file($declUsersFile) : ""; +$declUsers{$_} = 1 foreach split / /, -e $declUsersFile ? read_file($declUsersFile, { binmode => ":utf8" }) : ""; # Generate a new /etc/group containing the declared groups. @@ -175,7 +173,7 @@ foreach my $name (keys %groupsCur) { # Rewrite /etc/group. FIXME: acquire lock. my @lines = map { join(":", $_->{name}, $_->{password}, $_->{gid}, $_->{members}) . "\n" } (sort { $a->{gid} <=> $b->{gid} } values(%groupsOut)); -updateFile($gidMapFile, encode_json($gidMap)); +updateFile($gidMapFile, to_json($gidMap)); updateFile("/etc/group", \@lines); system("nscd --invalidate group"); @@ -251,7 +249,7 @@ foreach my $name (keys %usersCur) { # Rewrite /etc/passwd. FIXME: acquire lock. @lines = map { join(":", $_->{name}, $_->{fakePassword}, $_->{uid}, $_->{gid}, $_->{description}, $_->{home}, $_->{shell}) . "\n" } (sort { $a->{uid} <=> $b->{uid} } (values %usersOut)); -updateFile($uidMapFile, encode_json($uidMap)); +updateFile($uidMapFile, to_json($uidMap)); updateFile("/etc/passwd", \@lines); system("nscd --invalidate passwd"); @@ -260,7 +258,7 @@ system("nscd --invalidate passwd"); my @shadowNew; my %shadowSeen; -foreach my $line (-f "/etc/shadow" ? read_file("/etc/shadow") : ()) { +foreach my $line (-f "/etc/shadow" ? read_file("/etc/shadow", { binmode => ":utf8" }) : ()) { chomp $line; my ($name, $hashedPassword, @rest) = split(':', $line, -9); my $u = $usersOut{$name};; diff --git a/nixos/modules/config/zram.nix b/nixos/modules/config/zram.nix index 5e9870bf6b1cf..1f513b7e4daef 100644 --- a/nixos/modules/config/zram.nix +++ b/nixos/modules/config/zram.nix @@ -80,6 +80,15 @@ in ''; }; + memoryMax = mkOption { + default = null; + type = with types; nullOr int; + description = '' + Maximum total amount of memory (in bytes) that can be used by the zram + swap devices. + ''; + }; + priority = mkOption { default = 5; type = types.int; @@ -146,11 +155,16 @@ in # Calculate memory to use for zram mem=$(${pkgs.gawk}/bin/awk '/MemTotal: / { - print int($2*${toString cfg.memoryPercent}/100.0/${toString devicesCount}*1024) + value=int($2*${toString cfg.memoryPercent}/100.0/${toString devicesCount}*1024); + ${lib.optionalString (cfg.memoryMax != null) '' + memory_max=int(${toString cfg.memoryMax}/${toString devicesCount}); + if (value > memory_max) { value = memory_max } + ''} + print value }' /proc/meminfo) - ${pkgs.utillinux}/sbin/zramctl --size $mem --algorithm ${cfg.algorithm} /dev/${dev} - ${pkgs.utillinux}/sbin/mkswap /dev/${dev} + ${pkgs.util-linux}/sbin/zramctl --size $mem --algorithm ${cfg.algorithm} /dev/${dev} + ${pkgs.util-linux}/sbin/mkswap /dev/${dev} ''; restartIfChanged = false; }; diff --git a/nixos/modules/hardware/acpilight.nix b/nixos/modules/hardware/acpilight.nix index 34e8a22209653..2de448a265c79 100644 --- a/nixos/modules/hardware/acpilight.nix +++ b/nixos/modules/hardware/acpilight.nix @@ -19,6 +19,7 @@ in }; config = mkIf cfg.enable { + environment.systemPackages = with pkgs; [ acpilight ]; services.udev.packages = with pkgs; [ acpilight ]; }; } diff --git a/nixos/modules/installer/cd-dvd/sd-image.nix b/nixos/modules/installer/cd-dvd/sd-image.nix index 231c7bf0a6c25..d9799aa69c957 100644 --- a/nixos/modules/installer/cd-dvd/sd-image.nix +++ b/nixos/modules/installer/cd-dvd/sd-image.nix @@ -147,10 +147,10 @@ in sdImage.storePaths = [ config.system.build.toplevel ]; system.build.sdImage = pkgs.callPackage ({ stdenv, dosfstools, e2fsprogs, - mtools, libfaketime, utillinux, zstd }: stdenv.mkDerivation { + mtools, libfaketime, util-linux, zstd }: stdenv.mkDerivation { name = config.sdImage.imageName; - nativeBuildInputs = [ dosfstools e2fsprogs mtools libfaketime utillinux zstd ]; + nativeBuildInputs = [ dosfstools e2fsprogs mtools libfaketime util-linux zstd ]; inherit (config.sdImage) compressImage; @@ -221,7 +221,7 @@ in set -euo pipefail set -x # Figure out device names for the boot device and root filesystem. - rootPart=$(${pkgs.utillinux}/bin/findmnt -n -o SOURCE /) + rootPart=$(${pkgs.util-linux}/bin/findmnt -n -o SOURCE /) bootDevice=$(lsblk -npo PKNAME $rootPart) # Resize the root partition and the filesystem to fit the disk diff --git a/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix b/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix index 8408f56f94f91..0e67ae7de6980 100644 --- a/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix +++ b/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix @@ -96,7 +96,7 @@ in boot.initrd.extraUtilsCommands = '' - copy_bin_and_libs ${pkgs.utillinux}/sbin/hwclock + copy_bin_and_libs ${pkgs.util-linux}/sbin/hwclock ''; boot.initrd.postDeviceCommands = diff --git a/nixos/modules/installer/tools/nix-fallback-paths.nix b/nixos/modules/installer/tools/nix-fallback-paths.nix index bd70bd20013b4..699fb555615be 100644 --- a/nixos/modules/installer/tools/nix-fallback-paths.nix +++ b/nixos/modules/installer/tools/nix-fallback-paths.nix @@ -1,6 +1,6 @@ { - x86_64-linux = "/nix/store/qxayqjmlpqnmwg5yfsjjayw220ls8i2r-nix-2.3.8"; - i686-linux = "/nix/store/5834psaay75048jp6d07liqh4j0v1swd-nix-2.3.8"; - aarch64-linux = "/nix/store/pic90a5fxvifz05jzkd0zak21f9mjin6-nix-2.3.8"; - x86_64-darwin = "/nix/store/cjx3f8z12wlayp5983kli2a52ipi8jz2-nix-2.3.8"; + x86_64-linux = "/nix/store/fwak7l5jjl0py4wldsqjbv7p7rdzql0b-nix-2.3.9"; + i686-linux = "/nix/store/jlqrx9zw3vkwcczndaar5ban1j8g519z-nix-2.3.9"; + aarch64-linux = "/nix/store/kzvpzlm12185hw27l5znrprgvcja54d0-nix-2.3.9"; + x86_64-darwin = "/nix/store/kanh3awpf370pxfnjfvkh2m343wr3hj0-nix-2.3.9"; } diff --git a/nixos/modules/misc/documentation.nix b/nixos/modules/misc/documentation.nix index 71a40b4f4d6e2..bc43cc33b5d43 100644 --- a/nixos/modules/misc/documentation.nix +++ b/nixos/modules/misc/documentation.nix @@ -40,9 +40,9 @@ let in scrubbedEval.options; }; - helpScript = pkgs.writeScriptBin "nixos-help" - '' - #! ${pkgs.runtimeShell} -e + + nixos-help = let + helpScript = pkgs.writeShellScriptBin "nixos-help" '' # Finds first executable browser in a colon-separated list. # (see how xdg-open defines BROWSER) browser="$( @@ -59,14 +59,22 @@ let exec "$browser" ${manual.manualHTMLIndex} ''; - desktopItem = pkgs.makeDesktopItem { - name = "nixos-manual"; - desktopName = "NixOS Manual"; - genericName = "View NixOS documentation in a web browser"; - icon = "nix-snowflake"; - exec = "${helpScript}/bin/nixos-help"; - categories = "System"; - }; + desktopItem = pkgs.makeDesktopItem { + name = "nixos-manual"; + desktopName = "NixOS Manual"; + genericName = "View NixOS documentation in a web browser"; + icon = "nix-snowflake"; + exec = "nixos-help"; + categories = "System"; + }; + + in pkgs.symlinkJoin { + name = "nixos-help"; + paths = [ + helpScript + desktopItem + ]; + }; in @@ -250,8 +258,8 @@ in environment.systemPackages = [] ++ optional cfg.man.enable manual.manpages - ++ optionals cfg.doc.enable ([ manual.manualHTML helpScript ] - ++ optionals config.services.xserver.enable [ desktopItem pkgs.nixos-icons ]); + ++ optionals cfg.doc.enable ([ manual.manualHTML nixos-help ] + ++ optionals config.services.xserver.enable [ pkgs.nixos-icons ]); services.mingetty.helpLine = mkIf cfg.doc.enable ( "\nRun 'nixos-help' for the NixOS manual." diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index bafa222504009..cf0198d7b93d0 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -135,7 +135,7 @@ in #keys = 96; # unused #haproxy = 97; # dynamically allocated as of 2020-03-11 mongodb = 98; - openldap = 99; + #openldap = 99; # dynamically allocated as of PR#94610 #users = 100; # unused cgminer = 101; munin = 102; @@ -451,7 +451,7 @@ in keys = 96; #haproxy = 97; # dynamically allocated as of 2020-03-11 #mongodb = 98; # unused - openldap = 99; + #openldap = 99; # dynamically allocated as of PR#94610 munin = 102; #logcheck = 103; # unused #nix-ssh = 104; # unused diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 6ac12e4e13874..f5e6c5f4d619a 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -147,6 +147,7 @@ ./programs/npm.nix ./programs/oblogout.nix ./programs/plotinus.nix + ./programs/proxychains.nix ./programs/qt5ct.nix ./programs/screen.nix ./programs/sedutil.nix @@ -542,6 +543,7 @@ ./services/monitoring/kapacitor.nix ./services/monitoring/loki.nix ./services/monitoring/longview.nix + ./services/monitoring/mackerel-agent.nix ./services/monitoring/monit.nix ./services/monitoring/munin.nix ./services/monitoring/nagios.nix @@ -582,6 +584,7 @@ ./services/network-filesystems/orangefs/client.nix ./services/network-filesystems/rsyncd.nix ./services/network-filesystems/samba.nix + ./services/network-filesystems/samba-wsdd.nix ./services/network-filesystems/tahoe.nix ./services/network-filesystems/diod.nix ./services/network-filesystems/u9fs.nix diff --git a/nixos/modules/programs/bandwhich.nix b/nixos/modules/programs/bandwhich.nix index 5413044f46141..1cffb5fa2765c 100644 --- a/nixos/modules/programs/bandwhich.nix +++ b/nixos/modules/programs/bandwhich.nix @@ -4,7 +4,7 @@ with lib; let cfg = config.programs.bandwhich; in { - meta.maintainers = with maintainers; [ filalex77 ]; + meta.maintainers = with maintainers; [ Br1ght0ne ]; options = { programs.bandwhich = { diff --git a/nixos/modules/programs/proxychains.nix b/nixos/modules/programs/proxychains.nix new file mode 100644 index 0000000000000..7743f79c1c0a9 --- /dev/null +++ b/nixos/modules/programs/proxychains.nix @@ -0,0 +1,165 @@ +{ config, lib, pkgs, ... }: +with lib; +let + + cfg = config.programs.proxychains; + + configFile = '' + ${cfg.chain.type}_chain + ${optionalString (cfg.chain.type == "random") + "chain_len = ${builtins.toString cfg.chain.length}"} + ${optionalString cfg.proxyDNS "proxy_dns"} + ${optionalString cfg.quietMode "quiet_mode"} + remote_dns_subnet ${builtins.toString cfg.remoteDNSSubnet} + tcp_read_time_out ${builtins.toString cfg.tcpReadTimeOut} + tcp_connect_time_out ${builtins.toString cfg.tcpConnectTimeOut} + localnet ${cfg.localnet} + [ProxyList] + ${builtins.concatStringsSep "\n" + (lib.mapAttrsToList (k: v: "${v.type} ${v.host} ${builtins.toString v.port}") + (lib.filterAttrs (k: v: v.enable) cfg.proxies))} + ''; + + proxyOptions = { + options = { + enable = mkEnableOption "this proxy"; + + type = mkOption { + type = types.enum [ "http" "socks4" "socks5" ]; + description = "Proxy type."; + }; + + host = mkOption { + type = types.str; + description = "Proxy host or IP address."; + }; + + port = mkOption { + type = types.port; + description = "Proxy port"; + }; + }; + }; + +in { + + ###### interface + + options = { + + programs.proxychains = { + + enable = mkEnableOption "installing proxychains configuration"; + + chain = { + type = mkOption { + type = types.enum [ "dynamic" "strict" "random" ]; + default = "strict"; + description = '' + <literal>dynamic</literal> - Each connection will be done via chained proxies + all proxies chained in the order as they appear in the list + at least one proxy must be online to play in chain + (dead proxies are skipped) + otherwise <literal>EINTR</literal> is returned to the app. + + <literal>strict</literal> - Each connection will be done via chained proxies + all proxies chained in the order as they appear in the list + all proxies must be online to play in chain + otherwise <literal>EINTR</literal> is returned to the app. + + <literal>random</literal> - Each connection will be done via random proxy + (or proxy chain, see <option>programs.proxychains.chain.length</option>) from the list. + ''; + }; + length = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + Chain length for random chain. + ''; + }; + }; + + proxyDNS = mkOption { + type = types.bool; + default = true; + description = "Proxy DNS requests - no leak for DNS data."; + }; + + quietMode = mkEnableOption "Quiet mode (no output from the library)."; + + remoteDNSSubnet = mkOption { + type = types.enum [ 10 127 224 ]; + default = 224; + description = '' + Set the class A subnet number to use for the internal remote DNS mapping, uses the reserved 224.x.x.x range by default. + ''; + }; + + tcpReadTimeOut = mkOption { + type = types.int; + default = 15000; + description = "Connection read time-out in milliseconds."; + }; + + tcpConnectTimeOut = mkOption { + type = types.int; + default = 8000; + description = "Connection time-out in milliseconds."; + }; + + localnet = mkOption { + type = types.str; + default = "127.0.0.0/255.0.0.0"; + description = "By default enable localnet for loopback address ranges."; + }; + + proxies = mkOption { + type = types.attrsOf (types.submodule proxyOptions); + description = '' + Proxies to be used by proxychains. + ''; + + example = literalExample '' + { myproxy = + { type = "socks4"; + host = "127.0.0.1"; + port = 1337; + }; + } + ''; + }; + + }; + + }; + + ###### implementation + + meta.maintainers = with maintainers; [ sorki ]; + + config = mkIf cfg.enable { + + assertions = singleton { + assertion = cfg.chain.type != "random" && cfg.chain.length == null; + message = '' + Option `programs.proxychains.chain.length` + only makes sense with `programs.proxychains.chain.type` = "random". + ''; + }; + + programs.proxychains.proxies = mkIf config.services.tor.client.enable + { + torproxy = mkDefault { + enable = true; + type = "socks4"; + host = "127.0.0.1"; + port = 9050; + }; + }; + + environment.etc."proxychains.conf".text = configFile; + environment.systemPackages = [ pkgs.proxychains ]; + }; + +} diff --git a/nixos/modules/programs/ssmtp.nix b/nixos/modules/programs/ssmtp.nix index 98ff21bd37f26..1f49ddc91bb38 100644 --- a/nixos/modules/programs/ssmtp.nix +++ b/nixos/modules/programs/ssmtp.nix @@ -142,6 +142,13 @@ in config = mkIf cfg.enable { + assertions = [ + { + assertion = cfg.useSTARTTLS -> cfg.useTLS; + message = "services.ssmtp.useSTARTTLS has no effect without services.ssmtp.useTLS"; + } + ]; + services.ssmtp.settings = mkMerge [ ({ MailHub = cfg.hostName; diff --git a/nixos/modules/programs/x2goserver.nix b/nixos/modules/programs/x2goserver.nix index 7d74231e956b7..05707a56542f7 100644 --- a/nixos/modules/programs/x2goserver.nix +++ b/nixos/modules/programs/x2goserver.nix @@ -110,7 +110,7 @@ in { "L+ /usr/local/bin/chmod - - - - ${coreutils}/bin/chmod" "L+ /usr/local/bin/cp - - - - ${coreutils}/bin/cp" "L+ /usr/local/bin/sed - - - - ${gnused}/bin/sed" - "L+ /usr/local/bin/setsid - - - - ${utillinux}/bin/setsid" + "L+ /usr/local/bin/setsid - - - - ${util-linux}/bin/setsid" "L+ /usr/local/bin/xrandr - - - - ${xorg.xrandr}/bin/xrandr" "L+ /usr/local/bin/xmodmap - - - - ${xorg.xmodmap}/bin/xmodmap" ]; diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix index a517f9e51ce17..a428103eaa963 100644 --- a/nixos/modules/security/pam.nix +++ b/nixos/modules/security/pam.nix @@ -396,7 +396,7 @@ let ${optionalString cfg.logFailures "auth required pam_tally.so"} ${optionalString (config.security.pam.enableSSHAgentAuth && cfg.sshAgentAuth) - "auth sufficient ${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so file=~/.ssh/authorized_keys:~/.ssh/authorized_keys2:/etc/ssh/authorized_keys.d/%u"} + "auth sufficient ${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so file=${lib.concatStringsSep ":" config.services.openssh.authorizedKeysFiles}"} ${optionalString cfg.fprintAuth "auth sufficient ${pkgs.fprintd}/lib/security/pam_fprintd.so"} ${let p11 = config.security.pam.p11; in optionalString cfg.p11Auth diff --git a/nixos/modules/security/pam_mount.nix b/nixos/modules/security/pam_mount.nix index 89211bfbde48d..9a0143c155c57 100644 --- a/nixos/modules/security/pam_mount.nix +++ b/nixos/modules/security/pam_mount.nix @@ -60,7 +60,7 @@ in <!-- if activated, requires ofl from hxtools to be present --> <logout wait="0" hup="no" term="no" kill="no" /> <!-- set PATH variable for pam_mount module --> - <path>${pkgs.utillinux}/bin</path> + <path>${pkgs.util-linux}/bin</path> <!-- create mount point if not present --> <mkmountpoint enable="1" remove="true" /> diff --git a/nixos/modules/security/wrappers/default.nix b/nixos/modules/security/wrappers/default.nix index 52de21bca9bfd..de6213714ac3a 100644 --- a/nixos/modules/security/wrappers/default.nix +++ b/nixos/modules/security/wrappers/default.nix @@ -163,8 +163,8 @@ in # These are mount related wrappers that require the +s permission. fusermount.source = "${pkgs.fuse}/bin/fusermount"; fusermount3.source = "${pkgs.fuse3}/bin/fusermount3"; - mount.source = "${lib.getBin pkgs.utillinux}/bin/mount"; - umount.source = "${lib.getBin pkgs.utillinux}/bin/umount"; + mount.source = "${lib.getBin pkgs.util-linux}/bin/mount"; + umount.source = "${lib.getBin pkgs.util-linux}/bin/umount"; }; boot.specialFileSystems.${parentWrapperDir} = { diff --git a/nixos/modules/services/admin/salt/master.nix b/nixos/modules/services/admin/salt/master.nix index cb803d323bbd2..a3069c81c19ae 100644 --- a/nixos/modules/services/admin/salt/master.nix +++ b/nixos/modules/services/admin/salt/master.nix @@ -45,7 +45,7 @@ in wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; path = with pkgs; [ - utillinux # for dmesg + util-linux # for dmesg ]; serviceConfig = { ExecStart = "${pkgs.salt}/bin/salt-master"; diff --git a/nixos/modules/services/admin/salt/minion.nix b/nixos/modules/services/admin/salt/minion.nix index c8fa9461a2094..ac124c570d8d4 100644 --- a/nixos/modules/services/admin/salt/minion.nix +++ b/nixos/modules/services/admin/salt/minion.nix @@ -50,7 +50,7 @@ in wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; path = with pkgs; [ - utillinux + util-linux ]; serviceConfig = { ExecStart = "${pkgs.salt}/bin/salt-minion"; diff --git a/nixos/modules/services/backup/tarsnap.nix b/nixos/modules/services/backup/tarsnap.nix index 6d99a1efb6138..e1200731c2ca7 100644 --- a/nixos/modules/services/backup/tarsnap.nix +++ b/nixos/modules/services/backup/tarsnap.nix @@ -308,7 +308,7 @@ in requires = [ "network-online.target" ]; after = [ "network-online.target" ]; - path = with pkgs; [ iputils tarsnap utillinux ]; + path = with pkgs; [ iputils tarsnap util-linux ]; # In order for the persistent tarsnap timer to work reliably, we have to # make sure that the tarsnap server is reachable after systemd starts up @@ -355,7 +355,7 @@ in description = "Tarsnap restore '${name}'"; requires = [ "network-online.target" ]; - path = with pkgs; [ iputils tarsnap utillinux ]; + path = with pkgs; [ iputils tarsnap util-linux ]; script = let tarsnap = ''tarsnap --configfile "/etc/tarsnap/${name}.conf"''; diff --git a/nixos/modules/services/cluster/kubernetes/kubelet.nix b/nixos/modules/services/cluster/kubernetes/kubelet.nix index c3d67552cc8c3..2b6e45ba1b905 100644 --- a/nixos/modules/services/cluster/kubernetes/kubelet.nix +++ b/nixos/modules/services/cluster/kubernetes/kubelet.nix @@ -241,7 +241,7 @@ in description = "Kubernetes Kubelet Service"; wantedBy = [ "kubernetes.target" ]; after = [ "network.target" "docker.service" "kube-apiserver.service" ]; - path = with pkgs; [ gitMinimal openssh docker utillinux iproute ethtool thin-provisioning-tools iptables socat ] ++ top.path; + path = with pkgs; [ gitMinimal openssh docker util-linux iproute ethtool thin-provisioning-tools iptables socat ] ++ top.path; preStart = '' ${concatMapStrings (img: '' echo "Seeding docker image: ${img}" diff --git a/nixos/modules/services/computing/torque/mom.nix b/nixos/modules/services/computing/torque/mom.nix index 0c5f43cf3e6a2..6747bd4b0d5aa 100644 --- a/nixos/modules/services/computing/torque/mom.nix +++ b/nixos/modules/services/computing/torque/mom.nix @@ -32,7 +32,7 @@ in environment.systemPackages = [ pkgs.torque ]; systemd.services.torque-mom-init = { - path = with pkgs; [ torque utillinux procps inetutils ]; + path = with pkgs; [ torque util-linux procps inetutils ]; script = '' pbs_mkdirs -v aux diff --git a/nixos/modules/services/computing/torque/server.nix b/nixos/modules/services/computing/torque/server.nix index 21c5a4f46724d..8d923fc04d46d 100644 --- a/nixos/modules/services/computing/torque/server.nix +++ b/nixos/modules/services/computing/torque/server.nix @@ -21,7 +21,7 @@ in environment.systemPackages = [ pkgs.torque ]; systemd.services.torque-server-init = { - path = with pkgs; [ torque utillinux procps inetutils ]; + path = with pkgs; [ torque util-linux procps inetutils ]; script = '' tmpsetup=$(mktemp -t torque-XXXX) diff --git a/nixos/modules/services/continuous-integration/gitlab-runner.nix b/nixos/modules/services/continuous-integration/gitlab-runner.nix index 431555309cc9c..c358a5db77c2f 100644 --- a/nixos/modules/services/continuous-integration/gitlab-runner.nix +++ b/nixos/modules/services/continuous-integration/gitlab-runner.nix @@ -541,7 +541,7 @@ in jq moreutils remarshal - utillinux + util-linux cfg.package ] ++ cfg.extraPackages; reloadIfChanged = true; diff --git a/nixos/modules/services/databases/foundationdb.nix b/nixos/modules/services/databases/foundationdb.nix index 18727acc7c756..e22127403e91c 100644 --- a/nixos/modules/services/databases/foundationdb.nix +++ b/nixos/modules/services/databases/foundationdb.nix @@ -233,7 +233,7 @@ in type = types.str; default = "Check.Valid=1,Check.Unexpired=1"; description = '' - "Peer verification string". This may be used to adjust which TLS + "Peer verification string". This may be used to adjust which TLS client certificates a server will accept, as a form of user authorization; for example, it may only accept TLS clients who offer a certificate abiding by some locality or organization name. diff --git a/nixos/modules/services/databases/openldap.nix b/nixos/modules/services/databases/openldap.nix index 7472538b887e3..94a5c573768b3 100644 --- a/nixos/modules/services/databases/openldap.nix +++ b/nixos/modules/services/databases/openldap.nix @@ -1,43 +1,121 @@ { config, lib, pkgs, ... }: with lib; - let - cfg = config.services.openldap; + legacyOptions = [ "rootpwFile" "suffix" "dataDir" "rootdn" "rootpw" ]; openldap = cfg.package; - - dataFile = pkgs.writeText "ldap-contents.ldif" cfg.declarativeContents; - configFile = pkgs.writeText "slapd.conf" ((optionalString cfg.defaultSchemas '' - include ${openldap.out}/etc/schema/core.schema - include ${openldap.out}/etc/schema/cosine.schema - include ${openldap.out}/etc/schema/inetorgperson.schema - include ${openldap.out}/etc/schema/nis.schema - '') + '' - ${cfg.extraConfig} - database ${cfg.database} - suffix ${cfg.suffix} - rootdn ${cfg.rootdn} - ${if (cfg.rootpw != null) then '' - rootpw ${cfg.rootpw} - '' else '' - include ${cfg.rootpwFile} - ''} - directory ${cfg.dataDir} - ${cfg.extraDatabaseConfig} - ''); - configOpts = if cfg.configDir == null then "-f ${configFile}" - else "-F ${cfg.configDir}"; -in - -{ - - ###### interface - + configDir = if cfg.configDir != null then cfg.configDir else "/etc/openldap/slapd.d"; + + ldapValueType = let + # Can't do types.either with multiple non-overlapping submodules, so define our own + singleLdapValueType = lib.mkOptionType rec { + name = "LDAP"; + description = "LDAP value"; + check = x: lib.isString x || (lib.isAttrs x && (x ? path || x ? base64)); + merge = lib.mergeEqualOption; + }; + # We don't coerce to lists of single values, as some values must be unique + in types.either singleLdapValueType (types.listOf singleLdapValueType); + + ldapAttrsType = + let + options = { + attrs = mkOption { + type = types.attrsOf ldapValueType; + default = {}; + description = "Attributes of the parent entry."; + }; + children = mkOption { + # Hide the child attributes, to avoid infinite recursion in e.g. documentation + # Actual Nix evaluation is lazy, so this is not an issue there + type = let + hiddenOptions = lib.mapAttrs (name: attr: attr // { visible = false; }) options; + in types.attrsOf (types.submodule { options = hiddenOptions; }); + default = {}; + description = "Child entries of the current entry, with recursively the same structure."; + example = lib.literalExample '' + { + "cn=schema" = { + # The attribute used in the DN must be defined + attrs = { cn = "schema"; }; + children = { + # This entry's DN is expanded to "cn=foo,cn=schema" + "cn=foo" = { ... }; + }; + # These includes are inserted after "cn=schema", but before "cn=foo,cn=schema" + includes = [ ... ]; + }; + } + ''; + }; + includes = mkOption { + type = types.listOf types.path; + default = []; + description = '' + LDIF files to include after the parent's attributes but before its children. + ''; + }; + }; + in types.submodule { inherit options; }; + + valueToLdif = attr: values: let + listValues = if lib.isList values then values else lib.singleton values; + in map (value: + if lib.isAttrs value then + if lib.hasAttr "path" value + then "${attr}:< file://${value.path}" + else "${attr}:: ${value.base64}" + else "${attr}: ${lib.replaceStrings [ "\n" ] [ "\n " ] value}" + ) listValues; + + attrsToLdif = dn: { attrs, children, includes, ... }: ['' + dn: ${dn} + ${lib.concatStringsSep "\n" (lib.flatten (lib.mapAttrsToList valueToLdif attrs))} + ''] ++ (map (path: "include: file://${path}\n") includes) ++ ( + lib.flatten (lib.mapAttrsToList (name: value: attrsToLdif "${name},${dn}" value) children) + ); +in { + imports = let + deprecationNote = "This option is removed due to the deprecation of `slapd.conf` upstream. Please migrate to `services.openldap.settings`, see the release notes for advice with this process."; + mkDatabaseOption = old: new: + lib.mkChangedOptionModule [ "services" "openldap" old ] [ "services" "openldap" "settings" "children" ] + (config: let + database = lib.getAttrFromPath [ "services" "openldap" "database" ] config; + value = lib.getAttrFromPath [ "services" "openldap" old ] config; + in lib.setAttrByPath ([ "olcDatabase={1}${database}" "attrs" ] ++ new) value); + in [ + (lib.mkRemovedOptionModule [ "services" "openldap" "extraConfig" ] deprecationNote) + (lib.mkRemovedOptionModule [ "services" "openldap" "extraDatabaseConfig" ] deprecationNote) + + (lib.mkChangedOptionModule [ "services" "openldap" "logLevel" ] [ "services" "openldap" "settings" "attrs" "olcLogLevel" ] + (config: lib.splitString " " (lib.getAttrFromPath [ "services" "openldap" "logLevel" ] config))) + (lib.mkChangedOptionModule [ "services" "openldap" "defaultSchemas" ] [ "services" "openldap" "settings" "children" "cn=schema" "includes"] + (config: lib.optionals (lib.getAttrFromPath [ "services" "openldap" "defaultSchemas" ] config) ( + map (schema: "${openldap}/etc/schema/${schema}.ldif") [ "core" "cosine" "inetorgperson" "nis" ]))) + + (lib.mkChangedOptionModule [ "services" "openldap" "database" ] [ "services" "openldap" "settings" "children" ] + (config: let + database = lib.getAttrFromPath [ "services" "openldap" "database" ] config; + in { + "olcDatabase={1}${database}".attrs = { + # objectClass is case-insensitive, so don't need to capitalize ${database} + objectClass = [ "olcdatabaseconfig" "olc${database}config" ]; + olcDatabase = "{1}${database}"; + olcDbDirectory = lib.mkDefault "/var/db/openldap"; + }; + "cn=schema".includes = lib.mkDefault ( + map (schema: "${openldap}/etc/schema/${schema}.ldif") [ "core" "cosine" "inetorgperson" "nis" ] + ); + })) + (mkDatabaseOption "rootpwFile" [ "olcRootPW" "path" ]) + (mkDatabaseOption "suffix" [ "olcSuffix" ]) + (mkDatabaseOption "dataDir" [ "olcDbDirectory" ]) + (mkDatabaseOption "rootdn" [ "olcRootDN" ]) + (mkDatabaseOption "rootpw" [ "olcRootPW" ]) + ]; options = { - services.openldap = { - enable = mkOption { type = types.bool; default = false; @@ -77,224 +155,170 @@ in example = [ "ldaps:///" ]; }; - dataDir = mkOption { - type = types.path; - default = "/var/db/openldap"; - description = "The database directory."; - }; - - defaultSchemas = mkOption { - type = types.bool; - default = true; - description = '' - Include the default schemas core, cosine, inetorgperson and nis. - This setting will be ignored if configDir is set. - ''; - }; - - database = mkOption { - type = types.str; - default = "mdb"; - description = '' - Database type to use for the LDAP. - This setting will be ignored if configDir is set. - ''; - }; - - suffix = mkOption { - type = types.str; - example = "dc=example,dc=org"; - description = '' - Specify the DN suffix of queries that will be passed to this backend - database. - This setting will be ignored if configDir is set. - ''; - }; - - rootdn = mkOption { - type = types.str; - example = "cn=admin,dc=example,dc=org"; - description = '' - Specify the distinguished name that is not subject to access control - or administrative limit restrictions for operations on this database. - This setting will be ignored if configDir is set. - ''; - }; - - rootpw = mkOption { - type = types.nullOr types.str; - default = null; - description = '' - Password for the root user. - This setting will be ignored if configDir is set. - Using this option will store the root password in plain text in the - world-readable nix store. To avoid this the <literal>rootpwFile</literal> can be used. + settings = mkOption { + type = ldapAttrsType; + description = "Configuration for OpenLDAP, in OLC format"; + example = lib.literalExample '' + { + attrs.olcLogLevel = [ "stats" ]; + children = { + "cn=schema".includes = [ + "\${pkgs.openldap}/etc/schema/core.ldif" + "\${pkgs.openldap}/etc/schema/cosine.ldif" + "\${pkgs.openldap}/etc/schema/inetorgperson.ldif" + ]; + "olcDatabase={-1}frontend" = { + attrs = { + objectClass = "olcDatabaseConfig"; + olcDatabase = "{-1}frontend"; + olcAccess = [ "{0}to * by dn.exact=uidNumber=0+gidNumber=0,cn=peercred,cn=external,cn=auth manage stop by * none stop" ]; + }; + }; + "olcDatabase={0}config" = { + attrs = { + objectClass = "olcDatabaseConfig"; + olcDatabase = "{0}config"; + olcAccess = [ "{0}to * by * none break" ]; + }; + }; + "olcDatabase={1}mdb" = { + attrs = { + objectClass = [ "olcDatabaseConfig" "olcMdbConfig" ]; + olcDatabase = "{1}mdb"; + olcDbDirectory = "/var/db/ldap"; + olcDbIndex = [ + "objectClass eq" + "cn pres,eq" + "uid pres,eq" + "sn pres,eq,subany" + ]; + olcSuffix = "dc=example,dc=com"; + olcAccess = [ "{0}to * by * read break" ]; + }; + }; + }; + }; ''; }; - rootpwFile = mkOption { - type = types.nullOr types.str; - default = null; - description = '' - Password file for the root user. - The file should contain the string <literal>rootpw</literal> followed by the password. - e.g.: <literal>rootpw mysecurepassword</literal> - ''; - }; - - logLevel = mkOption { - type = types.str; - default = "0"; - example = "acl trace"; - description = "The log level selector of slapd."; - }; - + # This option overrides settings configDir = mkOption { type = types.nullOr types.path; default = null; - description = "Use this optional config directory instead of using slapd.conf"; + description = '' + Use this config directory instead of generating one from the + <literal>settings</literal> option. Overrides all NixOS settings. If + you use this option,ensure `olcPidFile` is set to `/run/slapd/slapd.conf`. + ''; example = "/var/db/slapd.d"; }; - extraConfig = mkOption { - type = types.lines; - default = ""; - description = " - slapd.conf configuration - "; - example = literalExample '' - ''' - include ${openldap.out}/etc/schema/core.schema - include ${openldap.out}/etc/schema/cosine.schema - include ${openldap.out}/etc/schema/inetorgperson.schema - include ${openldap.out}/etc/schema/nis.schema - - database bdb - suffix dc=example,dc=org - rootdn cn=admin,dc=example,dc=org - # NOTE: change after first start - rootpw secret - directory /var/db/openldap - ''' - ''; - }; - declarativeContents = mkOption { - type = with types; nullOr lines; - default = null; + type = with types; attrsOf lines; + default = {}; description = '' - Declarative contents for the LDAP database, in LDIF format. + Declarative contents for the LDAP database, in LDIF format by suffix. - Note a few facts when using it. First, the database - <emphasis>must</emphasis> be stored in the directory defined by - <code>dataDir</code>. Second, all <code>dataDir</code> will be erased - when starting the LDAP server. Third, modifications to the database - are not prevented, they are just dropped on the next reboot of the - server. Finally, performance-wise the database and indexes are rebuilt - on each server startup, so this will slow down server startup, + All data will be erased when starting the LDAP server. Modifications + to the database are not prevented, they are just dropped on the next + reboot of the server. Performance-wise the database and indexes are + rebuilt on each server startup, so this will slow down server startup, especially with large databases. ''; - example = '' - dn: dc=example,dc=org - objectClass: domain - dc: example - - dn: ou=users,dc=example,dc=org - objectClass = organizationalUnit - ou: users - - # ... + example = lib.literalExample '' + { + "dc=example,dc=org" = ''' + dn= dn: dc=example,dc=org + objectClass: domain + dc: example + + dn: ou=users,dc=example,dc=org + objectClass = organizationalUnit + ou: users + + # ... + '''; + } ''; }; - - extraDatabaseConfig = mkOption { - type = types.lines; - default = ""; - description = '' - slapd.conf configuration after the database option. - This setting will be ignored if configDir is set. - ''; - example = '' - # Indices to maintain for this directory - # unique id so equality match only - index uid eq - # allows general searching on commonname, givenname and email - index cn,gn,mail eq,sub - # allows multiple variants on surname searching - index sn eq,sub - # sub above includes subintial,subany,subfinal - # optimise department searches - index ou eq - # if searches will include objectClass uncomment following - # index objectClass eq - # shows use of default index parameter - index default eq,sub - # indices missing - uses default eq,sub - index telephonenumber - - # other database parameters - # read more in slapd.conf reference section - cachesize 10000 - checkpoint 128 15 - ''; - }; - }; - - }; - - meta = { - maintainers = [ lib.maintainers.mic92 ]; }; - - ###### implementation + meta.maintainers = with lib.maintainters; [ mic92 kwohlfahrt ]; config = mkIf cfg.enable { - assertions = [ - { - assertion = cfg.configDir != null || cfg.rootpwFile != null || cfg.rootpw != null; - message = "services.openldap: Unless configDir is set, either rootpw or rootpwFile must be set"; - } - ]; - + assertions = map (opt: { + assertion = ((getAttr opt cfg) != "_mkMergedOptionModule") -> (cfg.database != "_mkMergedOptionModule"); + message = "Legacy OpenLDAP option `services.openldap.${opt}` requires `services.openldap.database` (use value \"mdb\" if unsure)"; + }) legacyOptions; environment.systemPackages = [ openldap ]; + # Literal attributes must always be set + services.openldap.settings = { + attrs = { + objectClass = "olcGlobal"; + cn = "config"; + olcPidFile = "/run/slapd/slapd.pid"; + }; + children."cn=schema".attrs = { + cn = "schema"; + objectClass = "olcSchemaConfig"; + }; + }; + systemd.services.openldap = { description = "LDAP server"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; - preStart = '' + preStart = let + settingsFile = pkgs.writeText "config.ldif" (lib.concatStringsSep "\n" (attrsToLdif "cn=config" cfg.settings)); + + dbSettings = lib.filterAttrs (name: value: lib.hasPrefix "olcDatabase=" name) cfg.settings.children; + dataDirs = lib.mapAttrs' (name: value: lib.nameValuePair value.attrs.olcSuffix value.attrs.olcDbDirectory) + (lib.filterAttrs (_: value: value.attrs ? olcDbDirectory) dbSettings); + dataFiles = lib.mapAttrs (dn: contents: pkgs.writeText "${dn}.ldif" contents) cfg.declarativeContents; + mkLoadScript = dn: let + dataDir = lib.escapeShellArg (getAttr dn dataDirs); + in '' + rm -rf ${dataDir}/* + ${openldap}/bin/slapadd -F ${lib.escapeShellArg configDir} -b ${dn} -l ${getAttr dn dataFiles} + chown -R "${cfg.user}:${cfg.group}" ${dataDir} + ''; + in '' mkdir -p /run/slapd chown -R "${cfg.user}:${cfg.group}" /run/slapd - ${optionalString (cfg.declarativeContents != null) '' - rm -Rf "${cfg.dataDir}" - ''} - mkdir -p "${cfg.dataDir}" - ${optionalString (cfg.declarativeContents != null) '' - ${openldap.out}/bin/slapadd ${configOpts} -l ${dataFile} - ''} - chown -R "${cfg.user}:${cfg.group}" "${cfg.dataDir}" - ${openldap}/bin/slaptest ${configOpts} + mkdir -p ${lib.escapeShellArg configDir} ${lib.escapeShellArgs (lib.attrValues dataDirs)} + chown "${cfg.user}:${cfg.group}" ${lib.escapeShellArg configDir} ${lib.escapeShellArgs (lib.attrValues dataDirs)} + + ${lib.optionalString (cfg.configDir == null) ('' + rm -Rf ${configDir}/* + ${openldap}/bin/slapadd -F ${configDir} -bcn=config -l ${settingsFile} + '')} + chown -R "${cfg.user}:${cfg.group}" ${lib.escapeShellArg configDir} + + ${lib.concatStrings (map mkLoadScript (lib.attrNames cfg.declarativeContents))} + ${openldap}/bin/slaptest -u -F ${lib.escapeShellArg configDir} ''; - serviceConfig.ExecStart = - "${openldap.out}/libexec/slapd -d '${cfg.logLevel}' " + - "-u '${cfg.user}' -g '${cfg.group}' " + - "-h '${concatStringsSep " " cfg.urlList}' " + - "${configOpts}"; + serviceConfig = { + ExecStart = lib.escapeShellArgs ([ + "${openldap}/libexec/slapd" "-u" cfg.user "-g" cfg.group "-F" configDir + "-h" (lib.concatStringsSep " " cfg.urlList) + ]); + Type = "forking"; + PIDFile = cfg.settings.attrs.olcPidFile; + }; }; - users.users.openldap = - { name = cfg.user; + users.users = lib.optionalAttrs (cfg.user == "openldap") { + openldap = { group = cfg.group; - uid = config.ids.uids.openldap; - }; - - users.groups.openldap = - { name = cfg.group; - gid = config.ids.gids.openldap; + isSystemUser = true; }; + }; + users.groups = lib.optionalAttrs (cfg.group == "openldap") { + openldap = {}; + }; }; } diff --git a/nixos/modules/services/databases/riak.nix b/nixos/modules/services/databases/riak.nix index 885215209bdf4..657eeea87bf4c 100644 --- a/nixos/modules/services/databases/riak.nix +++ b/nixos/modules/services/databases/riak.nix @@ -118,7 +118,7 @@ in after = [ "network.target" ]; path = [ - pkgs.utillinux # for `logger` + pkgs.util-linux # for `logger` pkgs.bash ]; diff --git a/nixos/modules/services/desktops/pipewire.nix b/nixos/modules/services/desktops/pipewire.nix index 5179cbaf6bc22..c4923cfd3f00c 100644 --- a/nixos/modules/services/desktops/pipewire.nix +++ b/nixos/modules/services/desktops/pipewire.nix @@ -17,10 +17,6 @@ let mkdir -p "$out/lib" ln -s "${pkgs.pipewire.jack}/lib" "$out/lib/pipewire" ''; - pulse-libs = pkgs.runCommand "pulse-libs" {} '' - mkdir -p "$out/lib" - ln -s "${pkgs.pipewire.pulse}/lib" "$out/lib/pipewire" - ''; in { meta = { @@ -50,7 +46,7 @@ in { }; pulse = { - enable = mkEnableOption "PulseAudio emulation"; + enable = mkEnableOption "PulseAudio server emulation"; }; }; }; @@ -61,23 +57,24 @@ in { assertions = [ { assertion = cfg.pulse.enable -> !config.hardware.pulseaudio.enable; - message = "PipeWire based PulseAudio emulation doesn't use the PulseAudio service"; + message = "PipeWire based PulseAudio server emulation replaces PulseAudio"; } { assertion = cfg.jack.enable -> !config.services.jack.jackd.enable; - message = "PIpeWire based JACK emulation doesn't use the JACK service"; + message = "PipeWire based JACK emulation doesn't use the JACK service"; } ]; environment.systemPackages = [ pkgs.pipewire ] - ++ lib.optional cfg.jack.enable jack-libs - ++ lib.optional cfg.pulse.enable pulse-libs; + ++ lib.optional cfg.jack.enable jack-libs; - systemd.packages = [ pkgs.pipewire ]; + systemd.packages = [ pkgs.pipewire ] + ++ lib.optional cfg.pulse.enable pkgs.pipewire.pulse; # PipeWire depends on DBUS but doesn't list it. Without this booting # into a terminal results in the service crashing with an error. systemd.user.sockets.pipewire.wantedBy = lib.mkIf cfg.socketActivation [ "sockets.target" ]; + systemd.user.sockets.pipewire-pulse.wantedBy = lib.mkIf (cfg.socketActivation && cfg.pulse.enable) ["sockets.target"]; systemd.user.services.pipewire.bindsTo = [ "dbus.service" ]; services.udev.packages = [ pkgs.pipewire ]; @@ -100,6 +97,6 @@ in { source = "${pkgs.pipewire}/share/alsa/alsa.conf.d/50-pipewire.conf"; }; environment.sessionVariables.LD_LIBRARY_PATH = - lib.optional (cfg.jack.enable || cfg.pulse.enable) "/run/current-system/sw/lib/pipewire"; + lib.optional cfg.jack.enable "/run/current-system/sw/lib/pipewire"; }; } diff --git a/nixos/modules/services/desktops/profile-sync-daemon.nix b/nixos/modules/services/desktops/profile-sync-daemon.nix index a8ac22ac12765..6206295272fc5 100644 --- a/nixos/modules/services/desktops/profile-sync-daemon.nix +++ b/nixos/modules/services/desktops/profile-sync-daemon.nix @@ -36,7 +36,7 @@ in { description = "Profile Sync daemon"; wants = [ "psd-resync.service" ]; wantedBy = [ "default.target" ]; - path = with pkgs; [ rsync kmod gawk nettools utillinux profile-sync-daemon ]; + path = with pkgs; [ rsync kmod gawk nettools util-linux profile-sync-daemon ]; unitConfig = { RequiresMountsFor = [ "/home/" ]; }; @@ -55,7 +55,7 @@ in { wants = [ "psd-resync.timer" ]; partOf = [ "psd.service" ]; wantedBy = [ "default.target" ]; - path = with pkgs; [ rsync kmod gawk nettools utillinux profile-sync-daemon ]; + path = with pkgs; [ rsync kmod gawk nettools util-linux profile-sync-daemon ]; serviceConfig = { Type = "oneshot"; ExecStart = "${pkgs.profile-sync-daemon}/bin/profile-sync-daemon resync"; diff --git a/nixos/modules/services/games/factorio.nix b/nixos/modules/services/games/factorio.nix index 4b2e1a3c07f06..73099ae33634a 100644 --- a/nixos/modules/services/games/factorio.nix +++ b/nixos/modules/services/games/factorio.nix @@ -49,8 +49,13 @@ in default = 34197; description = '' The port to which the service should bind. - - This option will also open up the UDP port in the firewall configuration. + ''; + }; + openFirewall = mkOption { + type = types.bool; + default = false; + description = '' + Whether to automatically open the specified UDP port in the firewall. ''; }; saveName = mkOption { @@ -237,6 +242,6 @@ in }; }; - networking.firewall.allowedUDPPorts = [ cfg.port ]; + networking.firewall.allowedUDPPorts = if cfg.openFirewall then [ cfg.port ] else []; }; } diff --git a/nixos/modules/services/hardware/bluetooth.nix b/nixos/modules/services/hardware/bluetooth.nix index 230492c6b091d..6f5a6d3bf2886 100644 --- a/nixos/modules/services/hardware/bluetooth.nix +++ b/nixos/modules/services/hardware/bluetooth.nix @@ -15,6 +15,8 @@ in { hardware.bluetooth = { enable = mkEnableOption "support for Bluetooth"; + hsphfpd.enable = mkEnableOption "support for hsphfpd[-prototype] implementation"; + powerOnBoot = mkOption { type = types.bool; default = true; @@ -72,7 +74,8 @@ in { }; }; - environment.systemPackages = [ bluez-bluetooth ]; + environment.systemPackages = [ bluez-bluetooth ] + ++ optionals cfg.hsphfpd.enable [ pkgs.hsphfpd ]; environment.etc."bluetooth/main.conf"= { source = pkgs.writeText "main.conf" @@ -80,7 +83,8 @@ in { }; services.udev.packages = [ bluez-bluetooth ]; - services.dbus.packages = [ bluez-bluetooth ]; + services.dbus.packages = [ bluez-bluetooth ] + ++ optionals cfg.hsphfpd.enable [ pkgs.hsphfpd ]; systemd.packages = [ bluez-bluetooth ]; systemd.services = { @@ -90,11 +94,31 @@ in { # restarting can leave people without a mouse/keyboard unitConfig.X-RestartIfChanged = false; }; - }; + } + // (optionalAttrs cfg.hsphfpd.enable { + hsphfpd = { + after = [ "bluetooth.service" ]; + requires = [ "bluetooth.service" ]; + wantedBy = [ "multi-user.target" ]; + + description = "A prototype implementation used for connecting HSP/HFP Bluetooth devices"; + serviceConfig.ExecStart = "${pkgs.hsphfpd}/bin/hsphfpd.pl"; + }; + }) + ; systemd.user.services = { obex.aliases = [ "dbus-org.bluez.obex.service" ]; - }; + } + // (optionalAttrs cfg.hsphfpd.enable { + telephony_client = { + wantedBy = [ "default.target"]; + + description = "telephony_client for hsphfpd"; + serviceConfig.ExecStart = "${pkgs.hsphfpd}/bin/telephony_client.pl"; + }; + }) + ; }; diff --git a/nixos/modules/services/hardware/udev.nix b/nixos/modules/services/hardware/udev.nix index 587b9b0234aa4..a212adb7342dd 100644 --- a/nixos/modules/services/hardware/udev.nix +++ b/nixos/modules/services/hardware/udev.nix @@ -57,8 +57,8 @@ let substituteInPlace $i \ --replace \"/sbin/modprobe \"${pkgs.kmod}/bin/modprobe \ --replace \"/sbin/mdadm \"${pkgs.mdadm}/sbin/mdadm \ - --replace \"/sbin/blkid \"${pkgs.utillinux}/sbin/blkid \ - --replace \"/bin/mount \"${pkgs.utillinux}/bin/mount \ + --replace \"/sbin/blkid \"${pkgs.util-linux}/sbin/blkid \ + --replace \"/bin/mount \"${pkgs.util-linux}/bin/mount \ --replace /usr/bin/readlink ${pkgs.coreutils}/bin/readlink \ --replace /usr/bin/basename ${pkgs.coreutils}/bin/basename done @@ -280,7 +280,7 @@ in services.udev.packages = [ extraUdevRules extraHwdbFile ]; - services.udev.path = [ pkgs.coreutils pkgs.gnused pkgs.gnugrep pkgs.utillinux udev ]; + services.udev.path = [ pkgs.coreutils pkgs.gnused pkgs.gnugrep pkgs.util-linux udev ]; boot.kernelParams = mkIf (!config.networking.usePredictableInterfaceNames) [ "net.ifnames=0" ]; diff --git a/nixos/modules/services/mail/postfix.nix b/nixos/modules/services/mail/postfix.nix index fd4d16cdc37b0..319b3b638444f 100644 --- a/nixos/modules/services/mail/postfix.nix +++ b/nixos/modules/services/mail/postfix.nix @@ -834,12 +834,6 @@ in }; services.postfix.masterConfig = { - smtp_inet = { - name = "smtp"; - type = "inet"; - private = false; - command = "smtpd"; - }; pickup = { private = false; wakeup = 60; @@ -921,6 +915,12 @@ in in concatLists (mapAttrsToList mkKeyVal cfg.submissionOptions); }; } // optionalAttrs cfg.enableSmtp { + smtp_inet = { + name = "smtp"; + type = "inet"; + private = false; + command = "smtpd"; + }; smtp = {}; relay = { command = "smtp"; diff --git a/nixos/modules/services/mail/rspamd.nix b/nixos/modules/services/mail/rspamd.nix index 86a3f52107d51..a6c19a2af73eb 100644 --- a/nixos/modules/services/mail/rspamd.nix +++ b/nixos/modules/services/mail/rspamd.nix @@ -408,7 +408,7 @@ in }; imports = [ (mkRemovedOptionModule [ "services" "rspamd" "socketActivation" ] - "Socket activation never worked correctly and could at this time not be fixed and so was removed") + "Socket activation never worked correctly and could at this time not be fixed and so was removed") (mkRenamedOptionModule [ "services" "rspamd" "bindSocket" ] [ "services" "rspamd" "workers" "normal" "bindSockets" ]) (mkRenamedOptionModule [ "services" "rspamd" "bindUISocket" ] [ "services" "rspamd" "workers" "controller" "bindSockets" ]) (mkRemovedOptionModule [ "services" "rmilter" ] "Use services.rspamd.* instead to set up milter service") diff --git a/nixos/modules/services/misc/cfdyndns.nix b/nixos/modules/services/misc/cfdyndns.nix index dcf416022734f..15af1f50da1d6 100644 --- a/nixos/modules/services/misc/cfdyndns.nix +++ b/nixos/modules/services/misc/cfdyndns.nix @@ -6,6 +6,12 @@ let cfg = config.services.cfdyndns; in { + imports = [ + (mkRemovedOptionModule + [ "services" "cfdyndns" "apikey" ] + "Use services.cfdyndns.apikeyFile instead.") + ]; + options = { services.cfdyndns = { enable = mkEnableOption "Cloudflare Dynamic DNS Client"; @@ -17,10 +23,12 @@ in ''; }; - apikey = mkOption { - type = types.str; + apikeyFile = mkOption { + default = null; + type = types.nullOr types.str; description = '' - The API Key to use to authenticate to CloudFlare. + The path to a file containing the API Key + used to authenticate with CloudFlare. ''; }; @@ -45,13 +53,17 @@ in Type = "simple"; User = config.ids.uids.cfdyndns; Group = config.ids.gids.cfdyndns; - ExecStart = "/bin/sh -c '${pkgs.cfdyndns}/bin/cfdyndns'"; }; environment = { CLOUDFLARE_EMAIL="${cfg.email}"; - CLOUDFLARE_APIKEY="${cfg.apikey}"; CLOUDFLARE_RECORDS="${concatStringsSep "," cfg.records}"; }; + script = '' + ${optionalString (cfg.apikeyFile != null) '' + export CLOUDFLARE_APIKEY="$(cat ${escapeShellArg cfg.apikeyFile})" + ''} + ${pkgs.cfdyndns}/bin/cfdyndns + ''; }; users.users = { diff --git a/nixos/modules/services/misc/disnix.nix b/nixos/modules/services/misc/disnix.nix index 69386cdbb3812..41483d80a2ddb 100644 --- a/nixos/modules/services/misc/disnix.nix +++ b/nixos/modules/services/misc/disnix.nix @@ -34,6 +34,14 @@ in defaultText = "pkgs.disnix"; }; + enableProfilePath = mkEnableOption "exposing the Disnix profiles in the system's PATH"; + + profiles = mkOption { + type = types.listOf types.string; + default = [ "default" ]; + example = [ "default" ]; + description = "Names of the Disnix profiles to expose in the system's PATH"; + }; }; }; @@ -44,6 +52,7 @@ in dysnomia.enable = true; environment.systemPackages = [ pkgs.disnix ] ++ optional cfg.useWebServiceInterface pkgs.DisnixWebService; + environment.variables.PATH = lib.optionals cfg.enableProfilePath (map (profileName: "/nix/var/nix/profiles/disnix/${profileName}/bin" ) cfg.profiles); services.dbus.enable = true; services.dbus.packages = [ pkgs.disnix ]; @@ -68,7 +77,8 @@ in ++ optional config.services.postgresql.enable "postgresql.service" ++ optional config.services.tomcat.enable "tomcat.service" ++ optional config.services.svnserve.enable "svnserve.service" - ++ optional config.services.mongodb.enable "mongodb.service"; + ++ optional config.services.mongodb.enable "mongodb.service" + ++ optional config.services.influxdb.enable "influxdb.service"; restartIfChanged = false; diff --git a/nixos/modules/services/misc/dysnomia.nix b/nixos/modules/services/misc/dysnomia.nix index 4b52963500d1b..eb94791fbbfff 100644 --- a/nixos/modules/services/misc/dysnomia.nix +++ b/nixos/modules/services/misc/dysnomia.nix @@ -66,6 +66,19 @@ let ) (builtins.attrNames cfg.components)} ''; }; + + dysnomiaFlags = { + enableApacheWebApplication = config.services.httpd.enable; + enableAxis2WebService = config.services.tomcat.axis2.enable; + enableDockerContainer = config.virtualisation.docker.enable; + enableEjabberdDump = config.services.ejabberd.enable; + enableMySQLDatabase = config.services.mysql.enable; + enablePostgreSQLDatabase = config.services.postgresql.enable; + enableTomcatWebApplication = config.services.tomcat.enable; + enableMongoDatabase = config.services.mongodb.enable; + enableSubversionRepository = config.services.svnserve.enable; + enableInfluxDatabase = config.services.influxdb.enable; + }; in { options = { @@ -117,6 +130,12 @@ in description = "A list of paths containing additional modules that are added to the search folders"; default = []; }; + + enableLegacyModules = mkOption { + type = types.bool; + default = true; + description = "Whether to enable Dysnomia legacy process and wrapper modules"; + }; }; }; @@ -142,34 +161,48 @@ in environment.systemPackages = [ cfg.package ]; - dysnomia.package = pkgs.dysnomia.override (origArgs: { - enableApacheWebApplication = config.services.httpd.enable; - enableAxis2WebService = config.services.tomcat.axis2.enable; - enableEjabberdDump = config.services.ejabberd.enable; - enableMySQLDatabase = config.services.mysql.enable; - enablePostgreSQLDatabase = config.services.postgresql.enable; - enableSubversionRepository = config.services.svnserve.enable; - enableTomcatWebApplication = config.services.tomcat.enable; - enableMongoDatabase = config.services.mongodb.enable; - enableInfluxDatabase = config.services.influxdb.enable; + dysnomia.package = pkgs.dysnomia.override (origArgs: dysnomiaFlags // lib.optionalAttrs (cfg.enableLegacyModules) { + enableLegacy = builtins.trace '' + WARNING: Dysnomia has been configured to use the legacy 'process' and 'wrapper' + modules for compatibility reasons! If you rely on these modules, consider + migrating to better alternatives. + + More information: https://raw.githubusercontent.com/svanderburg/dysnomia/f65a9a84827bcc4024d6b16527098b33b02e4054/README-legacy.md + + If you have migrated already or don't rely on these Dysnomia modules, you can + disable legacy mode with the following NixOS configuration option: + + dysnomia.enableLegacyModules = false; + + In a future version of Dysnomia (and NixOS) the legacy option will go away! + '' true; }); dysnomia.properties = { hostname = config.networking.hostName; inherit (config.nixpkgs.localSystem) system; - supportedTypes = (import "${pkgs.stdenv.mkDerivation { - name = "supportedtypes"; - buildCommand = '' - ( echo -n "[ " - cd ${cfg.package}/libexec/dysnomia - for i in * - do - echo -n "\"$i\" " - done - echo -n " ]") > $out - ''; - }}"); + supportedTypes = [ + "echo" + "fileset" + "process" + "wrapper" + + # These are not base modules, but they are still enabled because they work with technology that are always enabled in NixOS + "systemd-unit" + "sysvinit-script" + "nixos-configuration" + ] + ++ optional (dysnomiaFlags.enableApacheWebApplication) "apache-webapplication" + ++ optional (dysnomiaFlags.enableAxis2WebService) "axis2-webservice" + ++ optional (dysnomiaFlags.enableDockerContainer) "docker-container" + ++ optional (dysnomiaFlags.enableEjabberdDump) "ejabberd-dump" + ++ optional (dysnomiaFlags.enableInfluxDatabase) "influx-database" + ++ optional (dysnomiaFlags.enableMySQLDatabase) "mysql-database" + ++ optional (dysnomiaFlags.enablePostgreSQLDatabase) "postgresql-database" + ++ optional (dysnomiaFlags.enableTomcatWebApplication) "tomcat-webapplication" + ++ optional (dysnomiaFlags.enableMongoDatabase) "mongo-database" + ++ optional (dysnomiaFlags.enableSubversionRepository) "subversion-repository"; }; dysnomia.containers = lib.recursiveUpdate ({ @@ -185,9 +218,9 @@ in }; } // lib.optionalAttrs (config.services.mysql.enable) { mysql-database = { mysqlPort = config.services.mysql.port; + mysqlSocket = "/run/mysqld/mysqld.sock"; } // lib.optionalAttrs cfg.enableAuthentication { mysqlUsername = "root"; - mysqlPassword = builtins.readFile (config.services.mysql.rootPassword); }; } // lib.optionalAttrs (config.services.postgresql.enable) { postgresql-database = { @@ -199,6 +232,13 @@ in tomcatPort = 8080; }; } // lib.optionalAttrs (config.services.mongodb.enable) { mongo-database = {}; } + // lib.optionalAttrs (config.services.influxdb.enable) { + influx-database = { + influxdbUsername = config.services.influxdb.user; + influxdbDataDir = "${config.services.influxdb.dataDir}/data"; + influxdbMetaDir = "${config.services.influxdb.dataDir}/meta"; + }; + } // lib.optionalAttrs (config.services.svnserve.enable) { subversion-repository = { svnBaseDir = config.services.svnserve.svnBaseDir; }; }) cfg.extraContainerProperties; diff --git a/nixos/modules/services/misc/fstrim.nix b/nixos/modules/services/misc/fstrim.nix index b8841a7fe74ce..5258f5acb410c 100644 --- a/nixos/modules/services/misc/fstrim.nix +++ b/nixos/modules/services/misc/fstrim.nix @@ -31,7 +31,7 @@ in { config = mkIf cfg.enable { - systemd.packages = [ pkgs.utillinux ]; + systemd.packages = [ pkgs.util-linux ]; systemd.timers.fstrim = { timerConfig = { diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix index 122bc3000b416..9342039927900 100644 --- a/nixos/modules/services/misc/gitlab.nix +++ b/nixos/modules/services/misc/gitlab.nix @@ -43,9 +43,13 @@ let [gitlab-shell] dir = "${cfg.packages.gitlab-shell}" + + [gitlab] secret_file = "${cfg.statePath}/gitlab_shell_secret" - gitlab_url = "http+unix://${pathUrlQuote gitlabSocket}" - http_settings = { self_signed_cert = false } + url = "http+unix://${pathUrlQuote gitlabSocket}" + + [gitlab.http-settings] + self_signed_cert = false ${concatStringsSep "\n" (attrValues (mapAttrs (k: v: '' [[storage]] @@ -119,6 +123,7 @@ let receive_pack = true; }; workhorse.secret_file = "${cfg.statePath}/.gitlab_workhorse_secret"; + gitlab_kas.secret_file = "${cfg.statePath}/.gitlab_kas_secret"; git.bin_path = "git"; monitoring = { ip_whitelist = [ "127.0.0.0/8" "::1/128" ]; @@ -653,7 +658,7 @@ in { script = '' set -eu - PSQL="${pkgs.utillinux}/bin/runuser -u ${pgsql.superUser} -- psql --port=${toString pgsql.port}" + PSQL="${pkgs.util-linux}/bin/runuser -u ${pgsql.superUser} -- psql --port=${toString pgsql.port}" $PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = '${cfg.databaseName}'" | grep -q 1 || $PSQL -tAc 'CREATE DATABASE "${cfg.databaseName}" OWNER "${cfg.databaseUsername}"' current_owner=$($PSQL -tAc "SELECT pg_catalog.pg_get_userbyid(datdba) FROM pg_catalog.pg_database WHERE datname = '${cfg.databaseName}'") @@ -668,6 +673,7 @@ in { rm "${config.services.postgresql.dataDir}/.reassigning_${cfg.databaseName}" fi $PSQL '${cfg.databaseName}' -tAc "CREATE EXTENSION IF NOT EXISTS pg_trgm" + $PSQL '${cfg.databaseName}' -tAc "CREATE EXTENSION IF NOT EXISTS btree_gist;" ''; serviceConfig = { @@ -750,7 +756,8 @@ in { }; systemd.services.gitaly = { - after = [ "network.target" ]; + after = [ "network.target" "gitlab.service" ]; + requires = [ "gitlab.service" ]; wantedBy = [ "multi-user.target" ]; path = with pkgs; [ openssh @@ -839,7 +846,7 @@ in { }; systemd.services.gitlab = { - after = [ "gitlab-workhorse.service" "gitaly.service" "network.target" "gitlab-postgresql.service" "redis.service" ]; + after = [ "gitlab-workhorse.service" "network.target" "gitlab-postgresql.service" "redis.service" ]; requires = [ "gitlab-sidekiq.service" ]; wantedBy = [ "multi-user.target" ]; environment = gitlabEnv; diff --git a/nixos/modules/services/misc/matrix-synapse.nix b/nixos/modules/services/misc/matrix-synapse.nix index 7f42184735c89..3abb9b7d69c88 100644 --- a/nixos/modules/services/misc/matrix-synapse.nix +++ b/nixos/modules/services/misc/matrix-synapse.nix @@ -713,7 +713,7 @@ in { ${ concatMapStringsSep "\n " (x: "--config-path ${x} \\") ([ configFile ] ++ cfg.extraConfigFiles) } --keys-directory ${cfg.dataDir} ''; - ExecReload = "${pkgs.utillinux}/bin/kill -HUP $MAINPID"; + ExecReload = "${pkgs.util-linux}/bin/kill -HUP $MAINPID"; Restart = "on-failure"; }; }; diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix index ed05882a6343a..0eeff31d6c4d4 100644 --- a/nixos/modules/services/misc/nix-daemon.nix +++ b/nixos/modules/services/misc/nix-daemon.nix @@ -539,7 +539,7 @@ in systemd.sockets.nix-daemon.wantedBy = [ "sockets.target" ]; systemd.services.nix-daemon = - { path = [ nix pkgs.utillinux config.programs.ssh.package ] + { path = [ nix pkgs.util-linux config.programs.ssh.package ] ++ optionals cfg.distributedBuilds [ pkgs.gzip ]; environment = cfg.envVars diff --git a/nixos/modules/services/misc/siproxd.nix b/nixos/modules/services/misc/siproxd.nix index 0e87fc461d3fc..20fe0793b84b6 100644 --- a/nixos/modules/services/misc/siproxd.nix +++ b/nixos/modules/services/misc/siproxd.nix @@ -39,7 +39,7 @@ in default = false; description = '' Whether to enable the Siproxd SIP - proxy/masquerading daemon. + proxy/masquerading daemon. ''; }; @@ -57,29 +57,29 @@ in hostsAllowReg = mkOption { type = types.listOf types.str; - default = [ ]; + default = [ ]; example = [ "192.168.1.0/24" "192.168.2.0/24" ]; - description = '' + description = '' Acess control list for incoming SIP registrations. ''; }; hostsAllowSip = mkOption { type = types.listOf types.str; - default = [ ]; + default = [ ]; example = [ "123.45.0.0/16" "123.46.0.0/16" ]; - description = '' + description = '' Acess control list for incoming SIP traffic. ''; }; hostsDenySip = mkOption { type = types.listOf types.str; - default = [ ]; + default = [ ]; example = [ "10.0.0.0/8" "11.0.0.0/8" ]; - description = '' + description = '' Acess control list for denying incoming - SIP registrations and traffic. + SIP registrations and traffic. ''; }; @@ -87,7 +87,7 @@ in type = types.int; default = 5060; description = '' - Port to listen for incoming SIP messages. + Port to listen for incoming SIP messages. ''; }; diff --git a/nixos/modules/services/misc/svnserve.nix b/nixos/modules/services/misc/svnserve.nix index 3335ed09d40e0..f70e3ca7fef0a 100644 --- a/nixos/modules/services/misc/svnserve.nix +++ b/nixos/modules/services/misc/svnserve.nix @@ -25,7 +25,7 @@ in svnBaseDir = mkOption { default = "/repos"; - description = "Base directory from which Subversion repositories are accessed."; + description = "Base directory from which Subversion repositories are accessed."; }; }; diff --git a/nixos/modules/services/monitoring/mackerel-agent.nix b/nixos/modules/services/monitoring/mackerel-agent.nix new file mode 100644 index 0000000000000..7046de9d403cf --- /dev/null +++ b/nixos/modules/services/monitoring/mackerel-agent.nix @@ -0,0 +1,111 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.mackerel-agent; + settingsFmt = pkgs.formats.toml {}; +in { + options.services.mackerel-agent = { + enable = mkEnableOption "mackerel.io agent"; + + # the upstream package runs as root, but doesn't seem to be strictly + # necessary for basic functionality + runAsRoot = mkEnableOption "Whether to run as root."; + + autoRetirement = mkEnableOption '' + Whether to automatically retire the host upon OS shutdown. + ''; + + apiKeyFile = mkOption { + type = types.path; + default = ""; + example = "/run/keys/mackerel-api-key"; + description = '' + Path to file containing the Mackerel API key. The file should contain a + single line of the following form: + + <literallayout>apikey = "EXAMPLE_API_KEY"</literallayout> + ''; + }; + + settings = mkOption { + description = '' + Options for mackerel-agent.conf. + + Documentation: + <link xlink:href="https://mackerel.io/docs/entry/spec/agent"/> + ''; + + default = {}; + example = { + verbose = false; + silent = false; + }; + + type = types.submodule { + freeformType = settingsFmt.type; + + options.host_status = { + on_start = mkOption { + type = types.enum [ "working" "standby" "maintenance" "poweroff" ]; + description = "Host status after agent startup."; + default = "working"; + }; + on_stop = mkOption { + type = types.enum [ "working" "standby" "maintenance" "poweroff" ]; + description = "Host status after agent shutdown."; + default = "poweroff"; + }; + }; + + options.diagnostic = + mkEnableOption "Collect memory usage for the agent itself"; + }; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = with pkgs; [ mackerel-agent ]; + + environment.etc = { + "mackerel-agent/mackerel-agent.conf".source = + settingsFmt.generate "mackerel-agent.conf" cfg.settings; + "mackerel-agent/conf.d/api-key.conf".source = cfg.apiKeyFile; + }; + + services.mackerel-agent.settings = { + root = mkDefault "/var/lib/mackerel-agent"; + pidfile = mkDefault "/run/mackerel-agent/mackerel-agent.pid"; + + # conf.d stores the symlink to cfg.apiKeyFile + include = mkDefault "/etc/mackerel-agent/conf.d/*.conf"; + }; + + # upstream service file in https://git.io/JUt4Q + systemd.services.mackerel-agent = { + description = "mackerel.io agent"; + after = [ "network-online.target" "nss-lookup.target" ]; + wantedBy = [ "multi-user.target" ]; + environment = { + MACKEREL_PLUGIN_WORKDIR = mkDefault "%C/mackerel-agent"; + }; + serviceConfig = { + DynamicUser = !cfg.runAsRoot; + PrivateTmp = mkDefault true; + CacheDirectory = "mackerel-agent"; + ConfigurationDirectory = "mackerel-agent"; + RuntimeDirectory = "mackerel-agent"; + StateDirectory = "mackerel-agent"; + ExecStart = "${pkgs.mackerel-agent}/bin/mackerel-agent supervise"; + ExecStopPost = mkIf cfg.autoRetirement "${pkg.mackerel-agent}/bin/mackerel-agent retire -force"; + ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + LimitNOFILE = mkDefault 65536; + LimitNPROC = mkDefault 65536; + }; + restartTriggers = [ + config.environment.etc."mackerel-agent/mackerel-agent.conf".source + ]; + }; + }; +} diff --git a/nixos/modules/services/monitoring/netdata.nix b/nixos/modules/services/monitoring/netdata.nix index 2e73e15d3a867..db51fdbd2c617 100644 --- a/nixos/modules/services/monitoring/netdata.nix +++ b/nixos/modules/services/monitoring/netdata.nix @@ -142,7 +142,7 @@ in { serviceConfig = { Environment="PYTHONPATH=${cfg.package}/libexec/netdata/python.d/python_modules"; ExecStart = "${cfg.package}/bin/netdata -P /run/netdata/netdata.pid -D -c ${configFile}"; - ExecReload = "${pkgs.utillinux}/bin/kill -s HUP -s USR1 -s USR2 $MAINPID"; + ExecReload = "${pkgs.util-linux}/bin/kill -s HUP -s USR1 -s USR2 $MAINPID"; TimeoutStopSec = 60; Restart = "on-failure"; # User and group diff --git a/nixos/modules/services/monitoring/smartd.nix b/nixos/modules/services/monitoring/smartd.nix index c72b4abfcdce3..3ea254371142b 100644 --- a/nixos/modules/services/monitoring/smartd.nix +++ b/nixos/modules/services/monitoring/smartd.nix @@ -36,7 +36,7 @@ let $SMARTD_MESSAGE EOF - } | ${pkgs.utillinux}/bin/wall 2>/dev/null + } | ${pkgs.util-linux}/bin/wall 2>/dev/null ''} ${optionalString nx.enable '' export DISPLAY=${nx.display} diff --git a/nixos/modules/services/monitoring/telegraf.nix b/nixos/modules/services/monitoring/telegraf.nix index 5d131557e8be9..b341a9005c2a4 100644 --- a/nixos/modules/services/monitoring/telegraf.nix +++ b/nixos/modules/services/monitoring/telegraf.nix @@ -5,14 +5,8 @@ with lib; let cfg = config.services.telegraf; - configFile = pkgs.runCommand "config.toml" { - buildInputs = [ pkgs.remarshal ]; - preferLocalBuild = true; - } '' - remarshal -if json -of toml \ - < ${pkgs.writeText "config.json" (builtins.toJSON cfg.extraConfig)} \ - > $out - ''; + settingsFormat = pkgs.formats.toml {}; + configFile = settingsFormat.generate "config.toml" cfg.extraConfig; in { ###### interface options = { @@ -26,22 +20,31 @@ in { type = types.package; }; + environmentFiles = mkOption { + type = types.listOf types.path; + default = []; + example = "/run/keys/telegraf.env"; + description = '' + File to load as environment file. Environment variables + from this file will be interpolated into the config file + using envsubst with this syntax: + <literal>$ENVIRONMENT ''${VARIABLE}</literal> + This is useful to avoid putting secrets into the nix store. + ''; + }; + extraConfig = mkOption { default = {}; description = "Extra configuration options for telegraf"; - type = types.attrs; + type = settingsFormat.type; example = { - outputs = { - influxdb = { - urls = ["http://localhost:8086"]; - database = "telegraf"; - }; + outputs.influxdb = { + urls = ["http://localhost:8086"]; + database = "telegraf"; }; - inputs = { - statsd = { - service_address = ":8125"; - delete_timings = true; - }; + inputs.statsd = { + service_address = ":8125"; + delete_timings = true; }; }; }; @@ -51,15 +54,28 @@ in { ###### implementation config = mkIf config.services.telegraf.enable { - systemd.services.telegraf = { + systemd.services.telegraf = let + finalConfigFile = if config.services.telegraf.environmentFiles == [] + then configFile + else "/var/run/telegraf/config.toml"; + in { description = "Telegraf Agent"; wantedBy = [ "multi-user.target" ]; after = [ "network-online.target" ]; serviceConfig = { - ExecStart=''${cfg.package}/bin/telegraf -config "${configFile}"''; + EnvironmentFile = config.services.telegraf.environmentFiles; + ExecStartPre = lib.optional (config.services.telegraf.environmentFiles != []) + (pkgs.writeShellScript "pre-start" '' + umask 077 + ${pkgs.envsubst}/bin/envsubst -i "${configFile}" > /var/run/telegraf/config.toml + ''); + ExecStart=''${cfg.package}/bin/telegraf -config ${finalConfigFile}''; ExecReload="${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + RuntimeDirectory = "telegraf"; User = "telegraf"; Restart = "on-failure"; + # for ping probes + AmbientCapabilities = [ "CAP_NET_RAW" ]; }; }; diff --git a/nixos/modules/services/network-filesystems/netatalk.nix b/nixos/modules/services/network-filesystems/netatalk.nix index 7674c8f7fa8d1..ca9d32311f5f3 100644 --- a/nixos/modules/services/network-filesystems/netatalk.nix +++ b/nixos/modules/services/network-filesystems/netatalk.nix @@ -108,10 +108,10 @@ in extmap = mkOption { type = types.lines; - default = ""; - description = '' - File name extension mappings. - See <literal>man extmap.conf</literal> for more information. + default = ""; + description = '' + File name extension mappings. + See <literal>man extmap.conf</literal> for more information. ''; }; @@ -132,10 +132,10 @@ in Type = "forking"; GuessMainPID = "no"; PIDFile = "/run/lock/netatalk"; - ExecStartPre = "${pkgs.coreutils}/bin/mkdir -m 0755 -p /var/lib/netatalk/CNID"; + ExecStartPre = "${pkgs.coreutils}/bin/mkdir -m 0755 -p /var/lib/netatalk/CNID"; ExecStart = "${pkgs.netatalk}/sbin/netatalk -F ${afpConfFile}"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; - ExecStop = "${pkgs.coreutils}/bin/kill -TERM $MAINPID"; + ExecStop = "${pkgs.coreutils}/bin/kill -TERM $MAINPID"; Restart = "always"; RestartSec = 1; }; diff --git a/nixos/modules/services/network-filesystems/openafs/client.nix b/nixos/modules/services/network-filesystems/openafs/client.nix index 677111814a018..03884cb729760 100644 --- a/nixos/modules/services/network-filesystems/openafs/client.nix +++ b/nixos/modules/services/network-filesystems/openafs/client.nix @@ -244,7 +244,7 @@ in # postStop, then we get a hang + kernel oops, because AFS can't be # stopped simply by sending signals to processes. preStop = '' - ${pkgs.utillinux}/bin/umount ${cfg.mountPoint} + ${pkgs.util-linux}/bin/umount ${cfg.mountPoint} ${openafsBin}/sbin/afsd -shutdown ${pkgs.kmod}/sbin/rmmod libafs ''; diff --git a/nixos/modules/services/network-filesystems/openafs/server.nix b/nixos/modules/services/network-filesystems/openafs/server.nix index 095024d2c8af0..d782f78216563 100644 --- a/nixos/modules/services/network-filesystems/openafs/server.nix +++ b/nixos/modules/services/network-filesystems/openafs/server.nix @@ -251,7 +251,6 @@ in { wantedBy = [ "multi-user.target" ]; restartIfChanged = false; unitConfig.ConditionPathExists = [ - "|/etc/openafs/server/rxkad.keytab" "|/etc/openafs/server/KeyFileExt" ]; preStart = '' diff --git a/nixos/modules/services/network-filesystems/samba-wsdd.nix b/nixos/modules/services/network-filesystems/samba-wsdd.nix new file mode 100644 index 0000000000000..004d07064afd4 --- /dev/null +++ b/nixos/modules/services/network-filesystems/samba-wsdd.nix @@ -0,0 +1,124 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.samba-wsdd; + +in { + options = { + services.samba-wsdd = { + enable = mkEnableOption '' + Enable Web Services Dynamic Discovery host daemon. This enables (Samba) hosts, like your local NAS device, + to be found by Web Service Discovery Clients like Windows. + <note> + <para>If you use the firewall consider adding the following:</para> + <programlisting> + networking.firewall.allowedTCPPorts = [ 5357 ]; + networking.firewall.allowedUDPPorts = [ 3702 ]; + </programlisting> + </note> + ''; + interface = mkOption { + type = types.nullOr types.str; + default = null; + example = "eth0"; + description = "Interface or address to use."; + }; + hoplimit = mkOption { + type = types.nullOr types.int; + default = null; + example = 2; + description = "Hop limit for multicast packets (default = 1)."; + }; + workgroup = mkOption { + type = types.nullOr types.str; + default = null; + example = "HOME"; + description = "Set workgroup name (default WORKGROUP)."; + }; + hostname = mkOption { + type = types.nullOr types.str; + default = null; + example = "FILESERVER"; + description = "Override (NetBIOS) hostname to be used (default hostname)."; + }; + domain = mkOption { + type = types.nullOr types.str; + default = null; + description = "Set domain name (disables workgroup)."; + }; + discovery = mkOption { + type = types.bool; + default = false; + description = "Enable discovery operation mode."; + }; + listen = mkOption { + type = types.str; + default = "/run/wsdd/wsdd.sock"; + description = "Listen on path or localhost port in discovery mode."; + }; + extraOptions = mkOption { + type = types.listOf types.str; + default = [ "--shortlog" ]; + example = [ "--verbose" "--no-http" "--ipv4only" "--no-host" ]; + description = "Additional wsdd options."; + }; + }; + }; + + config = mkIf cfg.enable { + + environment.systemPackages = [ pkgs.wsdd ]; + + systemd.services.samba-wsdd = { + description = "Web Services Dynamic Discovery host daemon"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + DynamicUser = true; + Type = "simple"; + ExecStart = '' + ${pkgs.wsdd}/bin/wsdd ${optionalString (cfg.interface != null) "--interface '${cfg.interface}'"} \ + ${optionalString (cfg.hoplimit != null) "--hoplimit '${toString cfg.hoplimit}'"} \ + ${optionalString (cfg.workgroup != null) "--workgroup '${cfg.workgroup}'"} \ + ${optionalString (cfg.hostname != null) "--hostname '${cfg.hostname}'"} \ + ${optionalString (cfg.domain != null) "--domain '${cfg.domain}'"} \ + ${optionalString cfg.discovery "--discovery --listen '${cfg.listen}'"} \ + ${escapeShellArgs cfg.extraOptions} + ''; + # Runtime directory and mode + RuntimeDirectory = "wsdd"; + RuntimeDirectoryMode = "0750"; + # Access write directories + UMask = "0027"; + # Capabilities + CapabilityBoundingSet = ""; + # Security + NoNewPrivileges = true; + # Sandboxing + ProtectSystem = "strict"; + ProtectHome = true; + PrivateTmp = true; + PrivateDevices = true; + PrivateUsers = false; + ProtectHostname = true; + ProtectClock = true; + ProtectKernelTunables = true; + ProtectKernelModules = true; + ProtectKernelLogs = true; + ProtectControlGroups = true; + RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ]; + RestrictNamespaces = true; + LockPersonality = true; + MemoryDenyWriteExecute = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + PrivateMounts = true; + # System Call Filtering + SystemCallArchitectures = "native"; + SystemCallFilter = "~@clock @cpu-emulation @debug @module @mount @obsolete @privileged @raw-io @reboot @resources @swap"; + }; + }; + }; +} diff --git a/nixos/modules/services/network-filesystems/xtreemfs.nix b/nixos/modules/services/network-filesystems/xtreemfs.nix index b8f8c1d71174b..27a9fe847c581 100644 --- a/nixos/modules/services/network-filesystems/xtreemfs.nix +++ b/nixos/modules/services/network-filesystems/xtreemfs.nix @@ -112,7 +112,7 @@ in description = '' Must be set to a unique identifier, preferably a UUID according to RFC 4122. UUIDs can be generated with `uuidgen` command, found in - the `utillinux` package. + the `util-linux` package. ''; }; port = mkOption { @@ -232,7 +232,7 @@ in description = '' Must be set to a unique identifier, preferably a UUID according to RFC 4122. UUIDs can be generated with `uuidgen` command, found in - the `utillinux` package. + the `util-linux` package. ''; }; port = mkOption { @@ -370,7 +370,7 @@ in description = '' Must be set to a unique identifier, preferably a UUID according to RFC 4122. UUIDs can be generated with `uuidgen` command, found in - the `utillinux` package. + the `util-linux` package. ''; }; port = mkOption { diff --git a/nixos/modules/services/networking/kresd.nix b/nixos/modules/services/networking/kresd.nix index ccb34163d5f36..6f1c4c48b430a 100644 --- a/nixos/modules/services/networking/kresd.nix +++ b/nixos/modules/services/networking/kresd.nix @@ -23,18 +23,14 @@ let ''; configFile = pkgs.writeText "kresd.conf" ( - optionalString (cfg.listenDoH != []) '' - modules.load('http') - '' + "" + concatMapStrings (mkListen "dns") cfg.listenPlain + concatMapStrings (mkListen "tls") cfg.listenTLS - + concatMapStrings (mkListen "doh") cfg.listenDoH + + concatMapStrings (mkListen "doh2") cfg.listenDoH + cfg.extraConfig ); - package = if cfg.listenDoH == [] - then pkgs.knot-resolver # never force `extraFeatures = false` - else pkgs.knot-resolver.override { extraFeatures = true; }; + package = pkgs.knot-resolver; in { meta.maintainers = [ maintainers.vcunat /* upstream developer */ ]; @@ -92,7 +88,7 @@ in { default = []; example = [ "198.51.100.1:443" "[2001:db8::1]:443" "443" ]; description = '' - Addresses and ports on which kresd should provide DNS over HTTPS (see RFC 8484). + Addresses and ports on which kresd should provide DNS over HTTPS/2 (see RFC 8484). For detailed syntax see ListenStream in man systemd.socket. ''; }; diff --git a/nixos/modules/services/networking/morty.nix b/nixos/modules/services/networking/morty.nix index e3a6444c11635..e110a5c86101f 100644 --- a/nixos/modules/services/networking/morty.nix +++ b/nixos/modules/services/networking/morty.nix @@ -29,9 +29,11 @@ in key = mkOption { type = types.str; default = ""; - description = "HMAC url validation key (hexadecimal encoded). - Leave blank to disable. Without validation key, anyone can - submit proxy requests. Leave blank to disable."; + description = '' + HMAC url validation key (hexadecimal encoded). + Leave blank to disable. Without validation key, anyone can + submit proxy requests. Leave blank to disable. + ''; defaultText = "No HMAC url validation. Generate with echo -n somevalue | openssl dgst -sha1 -hmac somekey"; }; @@ -85,10 +87,10 @@ in serviceConfig = { User = "morty"; ExecStart = ''${cfg.package}/bin/morty \ - -listen ${cfg.listenAddress}:${toString cfg.port} \ - ${optionalString cfg.ipv6 "-ipv6"} \ - ${optionalString (cfg.key != "") "-key " + cfg.key} \ - ''; + -listen ${cfg.listenAddress}:${toString cfg.port} \ + ${optionalString cfg.ipv6 "-ipv6"} \ + ${optionalString (cfg.key != "") "-key " + cfg.key} \ + ''; }; }; environment.systemPackages = [ cfg.package ]; diff --git a/nixos/modules/services/networking/mosquitto.nix b/nixos/modules/services/networking/mosquitto.nix index 4a85b3956daeb..10b49d9b2206e 100644 --- a/nixos/modules/services/networking/mosquitto.nix +++ b/nixos/modules/services/networking/mosquitto.nix @@ -232,6 +232,16 @@ in Restart = "on-failure"; ExecStart = "${pkgs.mosquitto}/bin/mosquitto -c ${mosquittoConf}"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + + ProtectSystem = "strict"; + ProtectHome = true; + PrivateDevices = true; + PrivateTmp = true; + ReadWritePaths = "${cfg.dataDir}"; + ProtectControlGroups = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + NoNewPrivileges = true; }; preStart = '' rm -f ${cfg.dataDir}/passwd diff --git a/nixos/modules/services/networking/mullvad-vpn.nix b/nixos/modules/services/networking/mullvad-vpn.nix index d9e6e57c92cc6..6f595ca4be2b2 100644 --- a/nixos/modules/services/networking/mullvad-vpn.nix +++ b/nixos/modules/services/networking/mullvad-vpn.nix @@ -15,6 +15,9 @@ with lib; config = mkIf cfg.enable { boot.kernelModules = [ "tun" ]; + # mullvad-daemon writes to /etc/iproute2/rt_tables + networking.iproute2.enable = true; + systemd.services.mullvad-daemon = { description = "Mullvad VPN daemon"; wantedBy = [ "multi-user.target" ]; diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix index 201a51ff70b1c..2e680544ec245 100644 --- a/nixos/modules/services/networking/networkmanager.nix +++ b/nixos/modules/services/networking/networkmanager.nix @@ -465,7 +465,7 @@ in { restartTriggers = [ configFile overrideNameserversScript ]; # useful binaries for user-specified hooks - path = [ pkgs.iproute pkgs.utillinux pkgs.coreutils ]; + path = [ pkgs.iproute pkgs.util-linux pkgs.coreutils ]; aliases = [ "dbus-org.freedesktop.nm-dispatcher.service" ]; }; diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix index 1b745931c4fa8..3cc77e4cb9387 100644 --- a/nixos/modules/services/networking/ssh/sshd.nix +++ b/nixos/modules/services/networking/ssh/sshd.nix @@ -477,7 +477,7 @@ in # https://github.com/NixOS/nixpkgs/pull/10155 # https://github.com/NixOS/nixpkgs/pull/41745 services.openssh.authorizedKeysFiles = - [ ".ssh/authorized_keys" ".ssh/authorized_keys2" "/etc/ssh/authorized_keys.d/%u" ]; + [ "%h/.ssh/authorized_keys" "%h/.ssh/authorized_keys2" "/etc/ssh/authorized_keys.d/%u" ]; services.openssh.extraConfig = mkOrder 0 '' diff --git a/nixos/modules/services/networking/strongswan-swanctl/module.nix b/nixos/modules/services/networking/strongswan-swanctl/module.nix index 0fec3ef00ad99..f67eedac29612 100644 --- a/nixos/modules/services/networking/strongswan-swanctl/module.nix +++ b/nixos/modules/services/networking/strongswan-swanctl/module.nix @@ -63,7 +63,7 @@ in { description = "strongSwan IPsec IKEv1/IKEv2 daemon using swanctl"; wantedBy = [ "multi-user.target" ]; after = [ "network-online.target" ]; - path = with pkgs; [ kmod iproute iptables utillinux ]; + path = with pkgs; [ kmod iproute iptables util-linux ]; environment = { STRONGSWAN_CONF = pkgs.writeTextFile { name = "strongswan.conf"; diff --git a/nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix b/nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix index 808cb863a9cf8..1d1e0bd1ca19a 100644 --- a/nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix +++ b/nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix @@ -1173,20 +1173,20 @@ in { ppk = mkPrefixedAttrsOfParams { secret = mkOptionalStrParam '' - Value of the PPK. It may either be an ASCII string, a hex encoded string - if it has a <literal>0x</literal> prefix or a Base64 encoded string if - it has a <literal>0s</literal> prefix in its value. Should have at least - 256 bits of entropy for 128-bit security. + Value of the PPK. It may either be an ASCII string, a hex encoded string + if it has a <literal>0x</literal> prefix or a Base64 encoded string if + it has a <literal>0s</literal> prefix in its value. Should have at least + 256 bits of entropy for 128-bit security. ''; id = mkPrefixedAttrsOfParam (mkOptionalStrParam "") '' - PPK identity the PPK belongs to. Multiple unique identities may be - specified, each having an <literal>id</literal> prefix, if a secret is - shared between multiple peers. + PPK identity the PPK belongs to. Multiple unique identities may be + specified, each having an <literal>id</literal> prefix, if a secret is + shared between multiple peers. ''; } '' - Postquantum Preshared Key (PPK) section for a specific secret. Each PPK is - defined in a unique section having the <literal>ppk</literal> prefix. + Postquantum Preshared Key (PPK) section for a specific secret. Each PPK is + defined in a unique section having the <literal>ppk</literal> prefix. ''; private = mkPrefixedAttrsOfParams { diff --git a/nixos/modules/services/networking/strongswan.nix b/nixos/modules/services/networking/strongswan.nix index 13a1a897c5ed8..f6170b8136545 100644 --- a/nixos/modules/services/networking/strongswan.nix +++ b/nixos/modules/services/networking/strongswan.nix @@ -152,7 +152,7 @@ in systemd.services.strongswan = { description = "strongSwan IPSec Service"; wantedBy = [ "multi-user.target" ]; - path = with pkgs; [ kmod iproute iptables utillinux ]; # XXX Linux + path = with pkgs; [ kmod iproute iptables util-linux ]; # XXX Linux after = [ "network-online.target" ]; environment = { STRONGSWAN_CONF = strongswanConf { inherit setup connections ca secretsFile managePlugins enabledPlugins; }; diff --git a/nixos/modules/services/networking/wasabibackend.nix b/nixos/modules/services/networking/wasabibackend.nix index 6eacffe709b0d..8482823e197f7 100644 --- a/nixos/modules/services/networking/wasabibackend.nix +++ b/nixos/modules/services/networking/wasabibackend.nix @@ -21,7 +21,7 @@ let RegTestBitcoinCoreRpcEndPoint = "${cfg.rpc.ip}:${toString cfg.rpc.port}"; }; - configFile = pkgs.writeText "wasabibackend.conf" (builtins.toJSON confOptions); + configFile = pkgs.writeText "wasabibackend.conf" (builtins.toJSON confOptions); in { diff --git a/nixos/modules/services/security/oauth2_proxy.nix b/nixos/modules/services/security/oauth2_proxy.nix index 2f9e94bd77bac..486f3ab05386d 100644 --- a/nixos/modules/services/security/oauth2_proxy.nix +++ b/nixos/modules/services/security/oauth2_proxy.nix @@ -448,7 +448,7 @@ in default = false; description = '' In case when running behind a reverse proxy, controls whether headers - like <literal>X-Real-Ip</literal> are accepted. Usage behind a reverse + like <literal>X-Real-Ip</literal> are accepted. Usage behind a reverse proxy will require this flag to be set to avoid logging the reverse proxy IP address. ''; @@ -524,7 +524,7 @@ in type = types.nullOr types.str; default = null; description = '' - Profile access endpoint. + Profile access endpoint. ''; }; diff --git a/nixos/modules/services/system/cloud-init.nix b/nixos/modules/services/system/cloud-init.nix index 15fe822aec679..3518e0ee9dca0 100644 --- a/nixos/modules/services/system/cloud-init.nix +++ b/nixos/modules/services/system/cloud-init.nix @@ -9,7 +9,7 @@ let cfg = config.services.cloud-init; nettools openssh shadow - utillinux + util-linux ] ++ optional cfg.btrfs.enable btrfs-progs ++ optional cfg.ext4.enable e2fsprogs ; diff --git a/nixos/modules/services/system/dbus.nix b/nixos/modules/services/system/dbus.nix index f8d909a4a3cca..d4cacb85694b9 100644 --- a/nixos/modules/services/system/dbus.nix +++ b/nixos/modules/services/system/dbus.nix @@ -11,6 +11,7 @@ let homeDir = "/run/dbus"; configDir = pkgs.makeDBusConf { + inherit (cfg) apparmor; suidHelper = "${config.security.wrapperDir}/dbus-daemon-launch-helper"; serviceDirectories = cfg.packages; }; @@ -51,6 +52,20 @@ in ''; }; + apparmor = mkOption { + type = types.enum [ "enabled" "disabled" "required" ]; + description = '' + AppArmor mode for dbus. + + <literal>enabled</literal> enables mediation when it's + supported in the kernel, <literal>disabled</literal> + always disables AppArmor even with kernel support, and + <literal>required</literal> fails when AppArmor was not found + in the kernel. + ''; + default = "disabled"; + }; + socketActivated = mkOption { type = types.nullOr types.bool; default = null; diff --git a/nixos/modules/services/torrent/transmission.nix b/nixos/modules/services/torrent/transmission.nix index 717c18d367f01..7bec073e26f71 100644 --- a/nixos/modules/services/torrent/transmission.nix +++ b/nixos/modules/services/torrent/transmission.nix @@ -397,9 +397,9 @@ in mr ${getLib pkgs.openssl}/lib/libcrypto*.so*, mr ${getLib pkgs.openssl}/lib/libssl*.so*, mr ${getLib pkgs.systemd}/lib/libsystemd*.so*, - mr ${getLib pkgs.utillinuxMinimal.out}/lib/libblkid.so*, - mr ${getLib pkgs.utillinuxMinimal.out}/lib/libmount.so*, - mr ${getLib pkgs.utillinuxMinimal.out}/lib/libuuid.so*, + mr ${getLib pkgs.util-linuxMinimal.out}/lib/libblkid.so*, + mr ${getLib pkgs.util-linuxMinimal.out}/lib/libmount.so*, + mr ${getLib pkgs.util-linuxMinimal.out}/lib/libuuid.so*, mr ${getLib pkgs.xz}/lib/liblzma*.so*, mr ${getLib pkgs.zlib}/lib/libz*.so*, diff --git a/nixos/modules/services/ttys/agetty.nix b/nixos/modules/services/ttys/agetty.nix index f3a629f7af700..d07746be2377a 100644 --- a/nixos/modules/services/ttys/agetty.nix +++ b/nixos/modules/services/ttys/agetty.nix @@ -5,7 +5,7 @@ with lib; let autologinArg = optionalString (config.services.mingetty.autologinUser != null) "--autologin ${config.services.mingetty.autologinUser}"; - gettyCmd = extraArgs: "@${pkgs.utillinux}/sbin/agetty agetty --login-program ${pkgs.shadow}/bin/login ${autologinArg} ${extraArgs}"; + gettyCmd = extraArgs: "@${pkgs.util-linux}/sbin/agetty agetty --login-program ${pkgs.shadow}/bin/login ${autologinArg} ${extraArgs}"; in diff --git a/nixos/modules/services/web-apps/codimd.nix b/nixos/modules/services/web-apps/codimd.nix index c787c36b877c8..0fbc9ee820e66 100644 --- a/nixos/modules/services/web-apps/codimd.nix +++ b/nixos/modules/services/web-apps/codimd.nix @@ -6,8 +6,10 @@ let cfg = config.services.codimd; prettyJSON = conf: - pkgs.runCommand "codimd-config.json" { preferLocalBuild = true; } '' - echo '${builtins.toJSON conf}' | ${pkgs.jq}/bin/jq \ + pkgs.runCommandLocal "codimd-config.json" { + nativeBuildInputs = [ pkgs.jq ]; + } '' + echo '${builtins.toJSON conf}' | jq \ '{production:del(.[]|nulls)|del(.[][]?|nulls)}' > $out ''; in @@ -878,7 +880,6 @@ in }; }; - environmentFile = mkOption { type = with types; nullOr path; default = null; @@ -908,6 +909,14 @@ in <literal>CodiMD</literal> is running. ''; }; + + package = mkOption { + type = types.package; + default = pkgs.codimd; + description = '' + Package that provides CodiMD. + ''; + }; }; config = mkIf cfg.enable { @@ -938,7 +947,7 @@ in ''; serviceConfig = { WorkingDirectory = cfg.workDir; - ExecStart = "${pkgs.codimd}/bin/codimd"; + ExecStart = "${cfg.package}/bin/codimd"; EnvironmentFile = mkIf (cfg.environmentFile != null) [ cfg.environmentFile ]; Environment = [ "CMD_CONFIG_FILE=${cfg.workDir}/config.json" diff --git a/nixos/modules/services/web-apps/gerrit.nix b/nixos/modules/services/web-apps/gerrit.nix index 657b1a4fc5bac..864587aea5651 100644 --- a/nixos/modules/services/web-apps/gerrit.nix +++ b/nixos/modules/services/web-apps/gerrit.nix @@ -143,7 +143,7 @@ in Set a UUID that uniquely identifies the server. This can be generated with - <literal>nix-shell -p utillinux --run uuidgen</literal>. + <literal>nix-shell -p util-linux --run uuidgen</literal>. ''; }; }; diff --git a/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixos/modules/services/web-servers/apache-httpd/default.nix index 6ffda3d63614d..dc78728d66360 100644 --- a/nixos/modules/services/web-servers/apache-httpd/default.nix +++ b/nixos/modules/services/web-servers/apache-httpd/default.nix @@ -750,8 +750,8 @@ in # Get rid of old semaphores. These tend to accumulate across # server restarts, eventually preventing it from restarting # successfully. - for i in $(${pkgs.utillinux}/bin/ipcs -s | grep ' ${cfg.user} ' | cut -f2 -d ' '); do - ${pkgs.utillinux}/bin/ipcrm -s $i + for i in $(${pkgs.util-linux}/bin/ipcs -s | grep ' ${cfg.user} ' | cut -f2 -d ' '); do + ${pkgs.util-linux}/bin/ipcrm -s $i done ''; diff --git a/nixos/modules/services/x11/terminal-server.nix b/nixos/modules/services/x11/terminal-server.nix index 503c14c9b6245..e6b50c21a9526 100644 --- a/nixos/modules/services/x11/terminal-server.nix +++ b/nixos/modules/services/x11/terminal-server.nix @@ -32,7 +32,7 @@ with lib; path = [ pkgs.xorg.xorgserver.out pkgs.gawk pkgs.which pkgs.openssl pkgs.xorg.xauth - pkgs.nettools pkgs.shadow pkgs.procps pkgs.utillinux pkgs.bash + pkgs.nettools pkgs.shadow pkgs.procps pkgs.util-linux pkgs.bash ]; environment.FD_GEOM = "1024x786x24"; diff --git a/nixos/modules/services/x11/window-managers/evilwm.nix b/nixos/modules/services/x11/window-managers/evilwm.nix index 6e19e3572c79d..6f1db2110f879 100644 --- a/nixos/modules/services/x11/window-managers/evilwm.nix +++ b/nixos/modules/services/x11/window-managers/evilwm.nix @@ -16,8 +16,8 @@ in services.xserver.windowManager.session = singleton { name = "evilwm"; start = '' - ${pkgs.evilwm}/bin/evilwm & - waitPID=$! + ${pkgs.evilwm}/bin/evilwm & + waitPID=$! ''; }; environment.systemPackages = [ pkgs.evilwm ]; diff --git a/nixos/modules/system/activation/activation-script.nix b/nixos/modules/system/activation/activation-script.nix index 18c77948cb90b..3a6930314b1af 100644 --- a/nixos/modules/system/activation/activation-script.nix +++ b/nixos/modules/system/activation/activation-script.nix @@ -25,7 +25,7 @@ let stdenv.cc.libc # nscd in update-users-groups.pl shadow nettools # needed for hostname - utillinux # needed for mount and mountpoint + util-linux # needed for mount and mountpoint ]; scriptType = with types; diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix index 2724d9f9cb6f1..03d7e7493230b 100644 --- a/nixos/modules/system/activation/top-level.nix +++ b/nixos/modules/system/activation/top-level.nix @@ -97,10 +97,11 @@ let allowSubstitutes = false; buildCommand = systemBuilder; - inherit (pkgs) utillinux coreutils; + inherit (pkgs) coreutils; systemd = config.systemd.package; shell = "${pkgs.bash}/bin/sh"; su = "${pkgs.shadow.su}/bin/su"; + utillinux = pkgs.util-linux; kernelParams = config.boot.kernelParams; installBootLoader = diff --git a/nixos/modules/system/boot/grow-partition.nix b/nixos/modules/system/boot/grow-partition.nix index be70c4ad9c8de..87c981b24cec9 100644 --- a/nixos/modules/system/boot/grow-partition.nix +++ b/nixos/modules/system/boot/grow-partition.nix @@ -20,8 +20,8 @@ with lib; boot.initrd.extraUtilsCommands = '' copy_bin_and_libs ${pkgs.gawk}/bin/gawk copy_bin_and_libs ${pkgs.gnused}/bin/sed - copy_bin_and_libs ${pkgs.utillinux}/sbin/sfdisk - copy_bin_and_libs ${pkgs.utillinux}/sbin/lsblk + copy_bin_and_libs ${pkgs.util-linux}/sbin/sfdisk + copy_bin_and_libs ${pkgs.util-linux}/sbin/lsblk substitute "${pkgs.cloud-utils.guest}/bin/.growpart-wrapped" "$out/bin/growpart" \ --replace "${pkgs.bash}/bin/sh" "/bin/sh" \ diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix index 20e39628eabbc..09f7641dc9d9d 100644 --- a/nixos/modules/system/boot/loader/grub/grub.nix +++ b/nixos/modules/system/boot/loader/grub/grub.nix @@ -66,7 +66,7 @@ let extraEntriesBeforeNixOS extraPrepareConfig configurationLimit copyKernels default fsIdentifier efiSupport efiInstallAsRemovable gfxmodeEfi gfxmodeBios gfxpayloadEfi gfxpayloadBios; path = with pkgs; makeBinPath ( - [ coreutils gnused gnugrep findutils diffutils btrfs-progs utillinux mdadm ] + [ coreutils gnused gnugrep findutils diffutils btrfs-progs util-linux mdadm ] ++ optional (cfg.efiSupport && (cfg.version == 2)) efibootmgr ++ optionals cfg.useOSProber [ busybox os-prober ]); font = if cfg.font == null then "" @@ -705,7 +705,7 @@ in let install-grub-pl = pkgs.substituteAll { src = ./install-grub.pl; - inherit (pkgs) utillinux; + utillinux = pkgs.util-linux; btrfsprogs = pkgs.btrfs-progs; }; in pkgs.writeScript "install-grub.sh" ('' diff --git a/nixos/modules/system/boot/shutdown.nix b/nixos/modules/system/boot/shutdown.nix index 11041066e07c1..8cda7b3aabe8c 100644 --- a/nixos/modules/system/boot/shutdown.nix +++ b/nixos/modules/system/boot/shutdown.nix @@ -18,7 +18,7 @@ with lib; serviceConfig = { Type = "oneshot"; - ExecStart = "${pkgs.utillinux}/sbin/hwclock --systohc ${if config.time.hardwareClockInLocalTime then "--localtime" else "--utc"}"; + ExecStart = "${pkgs.util-linux}/sbin/hwclock --systohc ${if config.time.hardwareClockInLocalTime then "--localtime" else "--utc"}"; }; }; diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh index e5cafe237cd53..abc1a0af48a63 100644 --- a/nixos/modules/system/boot/stage-1-init.sh +++ b/nixos/modules/system/boot/stage-1-init.sh @@ -219,6 +219,9 @@ done @preDeviceCommands@ echo "running udev..." ln -sfn /proc/self/fd /dev/fd +ln -sfn /proc/self/fd/0 /dev/stdin +ln -sfn /proc/self/fd/1 /dev/stdout +ln -sfn /proc/self/fd/2 /dev/stderr mkdir -p /etc/systemd ln -sfn @linkUnits@ /etc/systemd/network mkdir -p /etc/udev diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix index 6823e12847c2f..0f5787a192102 100644 --- a/nixos/modules/system/boot/stage-1.nix +++ b/nixos/modules/system/boot/stage-1.nix @@ -107,8 +107,8 @@ let copy_bin_and_libs $BIN done - # Copy some utillinux stuff. - copy_bin_and_libs ${pkgs.utillinux}/sbin/blkid + # Copy some util-linux stuff. + copy_bin_and_libs ${pkgs.util-linux}/sbin/blkid # Copy dmsetup and lvm. copy_bin_and_libs ${getBin pkgs.lvm2}/bin/dmsetup @@ -235,7 +235,7 @@ let --replace scsi_id ${extraUtils}/bin/scsi_id \ --replace cdrom_id ${extraUtils}/bin/cdrom_id \ --replace ${pkgs.coreutils}/bin/basename ${extraUtils}/bin/basename \ - --replace ${pkgs.utillinux}/bin/blkid ${extraUtils}/bin/blkid \ + --replace ${pkgs.util-linux}/bin/blkid ${extraUtils}/bin/blkid \ --replace ${getBin pkgs.lvm2}/bin ${extraUtils}/bin \ --replace ${pkgs.mdadm}/sbin ${extraUtils}/sbin \ --replace ${pkgs.bash}/bin/sh ${extraUtils}/bin/sh \ diff --git a/nixos/modules/system/boot/stage-2.nix b/nixos/modules/system/boot/stage-2.nix index dd6d83ee00947..94bc34fea0db3 100644 --- a/nixos/modules/system/boot/stage-2.nix +++ b/nixos/modules/system/boot/stage-2.nix @@ -17,7 +17,7 @@ let inherit (config.system.build) earlyMountScript; path = lib.makeBinPath ([ pkgs.coreutils - pkgs.utillinux + pkgs.util-linux ] ++ lib.optional useHostResolvConf pkgs.openresolv); fsPackagesPath = lib.makeBinPath config.system.fsPackages; postBootCommands = pkgs.writeText "local-cmds" diff --git a/nixos/modules/tasks/auto-upgrade.nix b/nixos/modules/tasks/auto-upgrade.nix index 69385e5f2fe01..b19b688a1fb8a 100644 --- a/nixos/modules/tasks/auto-upgrade.nix +++ b/nixos/modules/tasks/auto-upgrade.nix @@ -109,9 +109,8 @@ in { ''; }]; - system.autoUpgrade.flags = [ "--no-build-output" ] - ++ (if cfg.flake == null then - (if cfg.channel == null then + system.autoUpgrade.flags = (if cfg.flake == null then + [ "--no-build-output" ] ++ (if cfg.channel == null then [ "--upgrade" ] else [ "-I" diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix index 3ea67dac7146d..a055072f9c967 100644 --- a/nixos/modules/tasks/filesystems.nix +++ b/nixos/modules/tasks/filesystems.nix @@ -286,7 +286,7 @@ in before = [ mountPoint' "systemd-fsck@${device'}.service" ]; requires = [ device'' ]; after = [ device'' ]; - path = [ pkgs.utillinux ] ++ config.system.fsPackages; + path = [ pkgs.util-linux ] ++ config.system.fsPackages; script = '' if ! [ -e "${fs.device}" ]; then exit 1; fi diff --git a/nixos/modules/tasks/filesystems/nfs.nix b/nixos/modules/tasks/filesystems/nfs.nix index ddcc0ed8f5a43..fd35c35d32adc 100644 --- a/nixos/modules/tasks/filesystems/nfs.nix +++ b/nixos/modules/tasks/filesystems/nfs.nix @@ -10,20 +10,9 @@ let rpcMountpoint = "${nfsStateDir}/rpc_pipefs"; - idmapdConfFile = pkgs.writeText "idmapd.conf" '' - [General] - Pipefs-Directory = ${rpcMountpoint} - ${optionalString (config.networking.domain != null) - "Domain = ${config.networking.domain}"} - - [Mapping] - Nobody-User = nobody - Nobody-Group = nogroup - - [Translation] - Method = nsswitch - ''; + format = pkgs.formats.ini {}; + idmapdConfFile = format.generate "idmapd.conf" cfg.idmapd.settings; nfsConfFile = pkgs.writeText "nfs.conf" cfg.extraConfig; requestKeyConfFile = pkgs.writeText "request-key.conf" '' create id_resolver * * ${pkgs.nfs-utils}/bin/nfsidmap -t 600 %k %d @@ -38,6 +27,25 @@ in options = { services.nfs = { + idmapd.settings = mkOption { + type = format.type; + default = {}; + description = '' + libnfsidmap configuration. Refer to + <link xlink:href="https://linux.die.net/man/5/idmapd.conf"/> + for details. + ''; + example = literalExample '' + { + Translation = { + GSS-Methods = "static,nsswitch"; + }; + Static = { + "root/hostname.domain.com@REALM.COM" = "root"; + }; + } + ''; + }; extraConfig = mkOption { type = types.lines; default = ""; @@ -54,6 +62,20 @@ in services.rpcbind.enable = true; + services.nfs.idmapd.settings = { + General = mkMerge [ + { Pipefs-Directory = rpcMountpoint; } + (mkIf (config.networking.domain != null) { Domain = config.networking.domain; }) + ]; + Mapping = { + Nobody-User = "nobody"; + Nobody-Group = "nogroup"; + }; + Translation = { + Method = "nsswitch"; + }; + }; + system.fsPackages = [ pkgs.nfs-utils ]; boot.initrd.kernelModules = mkIf inInitrd [ "nfs" ]; diff --git a/nixos/modules/tasks/filesystems/unionfs-fuse.nix b/nixos/modules/tasks/filesystems/unionfs-fuse.nix index 1dcc4c87e3cec..f54f3559c3411 100644 --- a/nixos/modules/tasks/filesystems/unionfs-fuse.nix +++ b/nixos/modules/tasks/filesystems/unionfs-fuse.nix @@ -18,9 +18,9 @@ boot.initrd.postDeviceCommands = '' # Hacky!!! fuse hard-codes the path to mount - mkdir -p /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${pkgs.utillinux.name}-bin/bin - ln -s $(which mount) /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${pkgs.utillinux.name}-bin/bin - ln -s $(which umount) /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${pkgs.utillinux.name}-bin/bin + 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 ''; }) diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix index 9ca7c6fb3431b..6becc69627356 100644 --- a/nixos/modules/tasks/filesystems/zfs.nix +++ b/nixos/modules/tasks/filesystems/zfs.nix @@ -175,14 +175,10 @@ in forceImportAll = mkOption { type = types.bool; - default = true; + default = false; description = '' Forcibly import all ZFS pool(s). - This is enabled by default for backwards compatibility purposes, but it is highly - recommended to disable this option, as it bypasses some of the safeguards ZFS uses - to protect your ZFS pools. - If you set this option to <literal>false</literal> and NixOS subsequently fails to import your non-root ZFS pool(s), you should manually import each pool with "zpool import -f <pool-name>", and then reboot. You should only need to do @@ -444,7 +440,7 @@ in pkgs.gnugrep pkgs.gnused pkgs.nettools - pkgs.utillinux + pkgs.util-linux ]; }; @@ -507,6 +503,7 @@ in Type = "oneshot"; RemainAfterExit = true; }; + environment.ZFS_FORCE = optionalString cfgZfs.forceImportAll "-f"; script = (importLib { # See comments at importLib definition. zpoolCmd="${packages.zfsUser}/sbin/zpool"; diff --git a/nixos/modules/tasks/lvm.nix b/nixos/modules/tasks/lvm.nix index 2c3cc4c5467dc..98a0e2ddef900 100644 --- a/nixos/modules/tasks/lvm.nix +++ b/nixos/modules/tasks/lvm.nix @@ -21,6 +21,10 @@ in { }; config = mkMerge [ + ({ + # minimal configuration file to make lvmconfig/lvm2-activation-generator happy + environment.etc."lvm/lvm.conf".text = "config {}"; + }) (mkIf (!config.boot.isContainer) { systemd.tmpfiles.packages = [ cfg.package.out ]; environment.systemPackages = [ cfg.package ]; diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix index e5bd577536833..afb9c5404169f 100644 --- a/nixos/modules/tasks/network-interfaces.nix +++ b/nixos/modules/tasks/network-interfaces.nix @@ -1062,7 +1062,6 @@ in ]; boot.kernelModules = [ ] - ++ optional cfg.enableIPv6 "ipv6" ++ optional hasVirtuals "tun" ++ optional hasSits "sit" ++ optional hasBonds "bonding"; @@ -1247,7 +1246,7 @@ in ''; # Udev attributes for systemd to name the device and to create a .device target. - systemdAttrs = n: ''NAME:="${n}", ENV{INTERFACE}:="${n}", ENV{SYSTEMD_ALIAS}:="/sys/subsystem/net/devices/${n}", TAG+="systemd"''; + systemdAttrs = n: ''NAME:="${n}", ENV{INTERFACE}="${n}", ENV{SYSTEMD_ALIAS}="/sys/subsystem/net/devices/${n}", TAG+="systemd"''; in flip (concatMapStringsSep "\n") (attrNames wlanDeviceInterfaces) (device: let diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix index 44cb60809452c..26297a7d0f1f7 100644 --- a/nixos/modules/virtualisation/amazon-image.nix +++ b/nixos/modules/virtualisation/amazon-image.nix @@ -11,6 +11,7 @@ with lib; let cfg = config.ec2; metadataFetcher = import ./ec2-metadata-fetcher.nix { + inherit (pkgs) curl; targetRoot = "$targetRoot/"; wgetExtraOptions = "-q"; }; @@ -123,7 +124,7 @@ in boot.initrd.extraUtilsCommands = '' # We need swapon in the initrd. - copy_bin_and_libs ${pkgs.utillinux}/sbin/swapon + copy_bin_and_libs ${pkgs.util-linux}/sbin/swapon ''; # Don't put old configurations in the GRUB menu. The user has no diff --git a/nixos/modules/virtualisation/azure-agent.nix b/nixos/modules/virtualisation/azure-agent.nix index e85482af8392e..81413792eda0a 100644 --- a/nixos/modules/virtualisation/azure-agent.nix +++ b/nixos/modules/virtualisation/azure-agent.nix @@ -22,7 +22,7 @@ let nettools # for hostname procps # for pidof shadow # for useradd, usermod - utillinux # for (u)mount, fdisk, sfdisk, mkswap + util-linux # for (u)mount, fdisk, sfdisk, mkswap parted ]; pythonPath = [ pythonPackages.pyasn1 ]; diff --git a/nixos/modules/virtualisation/brightbox-image.nix b/nixos/modules/virtualisation/brightbox-image.nix index d0efbcc808aa1..4498e3a736185 100644 --- a/nixos/modules/virtualisation/brightbox-image.nix +++ b/nixos/modules/virtualisation/brightbox-image.nix @@ -27,7 +27,7 @@ in popd ''; diskImageBase = "nixos-image-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}.raw"; - buildInputs = [ pkgs.utillinux pkgs.perl ]; + buildInputs = [ pkgs.util-linux pkgs.perl ]; exportReferencesGraph = [ "closure" config.system.build.toplevel ]; } diff --git a/nixos/modules/virtualisation/ec2-metadata-fetcher.nix b/nixos/modules/virtualisation/ec2-metadata-fetcher.nix index b531787c31a29..dca5c2abd4e0c 100644 --- a/nixos/modules/virtualisation/ec2-metadata-fetcher.nix +++ b/nixos/modules/virtualisation/ec2-metadata-fetcher.nix @@ -1,23 +1,77 @@ -{ targetRoot, wgetExtraOptions }: +{ curl, targetRoot, wgetExtraOptions }: +# Note: be very cautious about dependencies, each dependency grows +# the closure of the initrd. Ideally we would not even require curl, +# but there is no reasonable way to send an HTTP PUT request without +# it. Note: do not be fooled: the wget referenced in this script +# is busybox's wget, not the fully featured one with --method support. +# +# Make sure that every package you depend on here is already listed as +# a channel blocker for both the full-sized and small channels. +# Otherwise, we risk breaking user deploys in released channels. +# +# Also note: OpenStack's metadata service for its instances aims to be +# compatible with the EC2 IMDS. Where possible, try to keep the set of +# fetched metadata in sync with ./openstack-metadata-fetcher.nix . '' metaDir=${targetRoot}etc/ec2-metadata mkdir -m 0755 -p "$metaDir" + rm -f "$metaDir/*" - echo "getting EC2 instance metadata..." + get_imds_token() { + # retry-delay of 1 selected to give the system a second to get going, + # but not add a lot to the bootup time + ${curl}/bin/curl \ + -v \ + --retry 3 \ + --retry-delay 1 \ + --fail \ + -X PUT \ + --connect-timeout 1 \ + -H "X-aws-ec2-metadata-token-ttl-seconds: 600" \ + http://169.254.169.254/latest/api/token + } - if ! [ -e "$metaDir/ami-manifest-path" ]; then - wget ${wgetExtraOptions} -O "$metaDir/ami-manifest-path" http://169.254.169.254/1.0/meta-data/ami-manifest-path - fi + preflight_imds_token() { + # retry-delay of 1 selected to give the system a second to get going, + # but not add a lot to the bootup time + ${curl}/bin/curl \ + -v \ + --retry 3 \ + --retry-delay 1 \ + --fail \ + --connect-timeout 1 \ + -H "X-aws-ec2-metadata-token: $IMDS_TOKEN" \ + http://169.254.169.254/1.0/meta-data/instance-id + } - if ! [ -e "$metaDir/user-data" ]; then - wget ${wgetExtraOptions} -O "$metaDir/user-data" http://169.254.169.254/1.0/user-data && chmod 600 "$metaDir/user-data" - fi + try=1 + while [ $try -le 3 ]; do + echo "(attempt $try/3) getting an EC2 instance metadata service v2 token..." + IMDS_TOKEN=$(get_imds_token) && break + try=$((try + 1)) + sleep 1 + done - if ! [ -e "$metaDir/hostname" ]; then - wget ${wgetExtraOptions} -O "$metaDir/hostname" http://169.254.169.254/1.0/meta-data/hostname + if [ "x$IMDS_TOKEN" == "x" ]; then + echo "failed to fetch an IMDS2v token." fi - if ! [ -e "$metaDir/public-keys-0-openssh-key" ]; then - wget ${wgetExtraOptions} -O "$metaDir/public-keys-0-openssh-key" http://169.254.169.254/1.0/meta-data/public-keys/0/openssh-key - fi + try=1 + while [ $try -le 10 ]; do + echo "(attempt $try/10) validating the EC2 instance metadata service v2 token..." + preflight_imds_token && break + try=$((try + 1)) + sleep 1 + done + + echo "getting EC2 instance metadata..." + + wget_imds() { + wget ${wgetExtraOptions} --header "X-aws-ec2-metadata-token: $IMDS_TOKEN" "$@"; + } + + wget_imds -O "$metaDir/ami-manifest-path" http://169.254.169.254/1.0/meta-data/ami-manifest-path + wget_imds -O "$metaDir/user-data" http://169.254.169.254/1.0/user-data && chmod 600 "$metaDir/user-data" + wget_imds -O "$metaDir/hostname" http://169.254.169.254/1.0/meta-data/hostname + wget_imds -O "$metaDir/public-keys-0-openssh-key" http://169.254.169.254/1.0/meta-data/public-keys/0/openssh-key '' diff --git a/nixos/modules/virtualisation/nixos-containers.nix b/nixos/modules/virtualisation/nixos-containers.nix index 8fbb4efd20196..26398afb3cf51 100644 --- a/nixos/modules/virtualisation/nixos-containers.nix +++ b/nixos/modules/virtualisation/nixos-containers.nix @@ -614,17 +614,17 @@ in ''; }; - timeoutStartSec = mkOption { - type = types.str; - default = "1min"; - description = '' - Time for the container to start. In case of a timeout, - the container processes get killed. - See <citerefentry><refentrytitle>systemd.time</refentrytitle> - <manvolnum>7</manvolnum></citerefentry> - for more information about the format. - ''; - }; + timeoutStartSec = mkOption { + type = types.str; + default = "1min"; + description = '' + Time for the container to start. In case of a timeout, + the container processes get killed. + See <citerefentry><refentrytitle>systemd.time</refentrytitle> + <manvolnum>7</manvolnum></citerefentry> + for more information about the format. + ''; + }; bindMounts = mkOption { type = with types; attrsOf (submodule bindMountOpts); diff --git a/nixos/modules/virtualisation/openstack-config.nix b/nixos/modules/virtualisation/openstack-config.nix index c2da5d0d2301e..d01e0f23aba17 100644 --- a/nixos/modules/virtualisation/openstack-config.nix +++ b/nixos/modules/virtualisation/openstack-config.nix @@ -3,7 +3,7 @@ with lib; let - metadataFetcher = import ./ec2-metadata-fetcher.nix { + metadataFetcher = import ./openstack-metadata-fetcher.nix { targetRoot = "/"; wgetExtraOptions = "--retry-connrefused"; }; diff --git a/nixos/modules/virtualisation/openstack-metadata-fetcher.nix b/nixos/modules/virtualisation/openstack-metadata-fetcher.nix new file mode 100644 index 0000000000000..8c191397cf9a5 --- /dev/null +++ b/nixos/modules/virtualisation/openstack-metadata-fetcher.nix @@ -0,0 +1,21 @@ +{ targetRoot, wgetExtraOptions }: + +# OpenStack's metadata service aims to be EC2-compatible. Where +# possible, try to keep the set of fetched metadata in sync with +# ./ec2-metadata-fetcher.nix . +'' + metaDir=${targetRoot}etc/ec2-metadata + mkdir -m 0755 -p "$metaDir" + rm -f "$metaDir/*" + + echo "getting instance metadata..." + + wget_imds() { + wget ${wgetExtraOptions} "$@" + } + + wget_imds -O "$metaDir/ami-manifest-path" http://169.254.169.254/1.0/meta-data/ami-manifest-path + wget_imds -O "$metaDir/user-data" http://169.254.169.254/1.0/user-data && chmod 600 "$metaDir/user-data" + wget_imds -O "$metaDir/hostname" http://169.254.169.254/1.0/meta-data/hostname + wget_imds -O "$metaDir/public-keys-0-openssh-key" http://169.254.169.254/1.0/meta-data/public-keys/0/openssh-key +'' diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix index 191d7c758c0dc..447d1f091c8c9 100644 --- a/nixos/modules/virtualisation/qemu-vm.nix +++ b/nixos/modules/virtualisation/qemu-vm.nix @@ -190,7 +190,7 @@ let '' else '' ''} ''; - buildInputs = [ pkgs.utillinux ]; + buildInputs = [ pkgs.util-linux ]; QEMU_OPTS = "-nographic -serial stdio -monitor none" + lib.optionalString cfg.useEFIBoot ( " -drive if=pflash,format=raw,unit=0,readonly=on,file=${efiFirmware}" @@ -744,16 +744,19 @@ in (isEnabled "VIRTIO_PCI") (isEnabled "VIRTIO_NET") (isEnabled "EXT4_FS") + (isEnabled "NET_9P_VIRTIO") + (isEnabled "9P_FS") (isYes "BLK_DEV") (isYes "PCI") - (isYes "EXPERIMENTAL") (isYes "NETDEVICES") (isYes "NET_CORE") (isYes "INET") (isYes "NETWORK_FILESYSTEMS") - ] ++ optional (!cfg.graphics) [ + ] ++ optionals (!cfg.graphics) [ (isYes "SERIAL_8250_CONSOLE") (isYes "SERIAL_8250") + ] ++ optionals (cfg.writableStore) [ + (isEnabled "OVERLAY_FS") ]; }; diff --git a/nixos/modules/virtualisation/xen-dom0.nix b/nixos/modules/virtualisation/xen-dom0.nix index 7b2a66c43489c..5ad647769bbd9 100644 --- a/nixos/modules/virtualisation/xen-dom0.nix +++ b/nixos/modules/virtualisation/xen-dom0.nix @@ -201,8 +201,8 @@ in '' if [ -d /proc/xen ]; then ${pkgs.kmod}/bin/modprobe xenfs 2> /dev/null - ${pkgs.utillinux}/bin/mountpoint -q /proc/xen || \ - ${pkgs.utillinux}/bin/mount -t xenfs none /proc/xen + ${pkgs.util-linux}/bin/mountpoint -q /proc/xen || \ + ${pkgs.util-linux}/bin/mount -t xenfs none /proc/xen fi ''; diff --git a/nixos/release-combined.nix b/nixos/release-combined.nix index 384ae5765b8c3..5f8a64702a82a 100644 --- a/nixos/release-combined.nix +++ b/nixos/release-combined.nix @@ -49,6 +49,7 @@ in rec { [ "nixos.channel" ] (onFullSupported "nixos.dummy") (onAllSupported "nixos.iso_minimal") + (onSystems ["x86_64-linux" "aarch64-linux"] "nixos.amazonImage") (onSystems ["x86_64-linux"] "nixos.iso_plasma5") (onSystems ["x86_64-linux"] "nixos.iso_gnome") (onFullSupported "nixos.manual") @@ -97,6 +98,7 @@ in rec { (onFullSupported "nixos.tests.login") (onFullSupported "nixos.tests.misc") (onFullSupported "nixos.tests.mutableUsers") + (onFullSupported "nixos.tests.nano") (onFullSupported "nixos.tests.nat.firewall-conntrack") (onFullSupported "nixos.tests.nat.firewall") (onFullSupported "nixos.tests.nat.standalone") diff --git a/nixos/release-small.nix b/nixos/release-small.nix index 6da2c59cedd49..996db54c9a402 100644 --- a/nixos/release-small.nix +++ b/nixos/release-small.nix @@ -28,7 +28,7 @@ let in rec { nixos = { - inherit (nixos') channel manual options iso_minimal dummy; + inherit (nixos') channel manual options iso_minimal amazonImage dummy; tests = { inherit (nixos'.tests) containers-imperative @@ -92,6 +92,7 @@ in rec { [ "nixos.channel" "nixos.dummy.x86_64-linux" "nixos.iso_minimal.x86_64-linux" + "nixos.amazonImage.x86_64-linux" "nixos.manual.x86_64-linux" "nixos.tests.boot.biosCdrom.x86_64-linux" "nixos.tests.containers-imperative.x86_64-linux" diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index d4aff486225d4..d746105ea643f 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -28,7 +28,9 @@ in atd = handleTest ./atd.nix {}; avahi = handleTest ./avahi.nix {}; avahi-with-resolved = handleTest ./avahi.nix { networkd = true; }; + awscli = handleTest ./awscli.nix { }; babeld = handleTest ./babeld.nix {}; + bat = handleTest ./bat.nix {}; bazarr = handleTest ./bazarr.nix {}; bcachefs = handleTestOn ["x86_64-linux"] ./bcachefs.nix {}; # linux-4.18.2018.10.12 is unsupported on aarch64 beanstalkd = handleTest ./beanstalkd.nix {}; @@ -103,6 +105,7 @@ in etcd = handleTestOn ["x86_64-linux"] ./etcd.nix {}; etcd-cluster = handleTestOn ["x86_64-linux"] ./etcd-cluster.nix {}; fancontrol = handleTest ./fancontrol.nix {}; + fcitx = handleTest ./fcitx {}; ferm = handleTest ./ferm.nix {}; firefox = handleTest ./firefox.nix {}; firefox-esr = handleTest ./firefox.nix { esr = true; }; @@ -169,6 +172,7 @@ in jenkins = handleTest ./jenkins.nix {}; jirafeau = handleTest ./jirafeau.nix {}; jitsi-meet = handleTest ./jitsi-meet.nix {}; + jq = handleTest ./jq.nix {}; k3s = handleTest ./k3s.nix {}; kafka = handleTest ./kafka.nix {}; keepalived = handleTest ./keepalived.nix {}; @@ -192,6 +196,7 @@ in limesurvey = handleTest ./limesurvey.nix {}; login = handleTest ./login.nix {}; loki = handleTest ./loki.nix {}; + lsd = handleTest ./lsd.nix {}; lxd = handleTest ./lxd.nix {}; lxd-nftables = handleTest ./lxd-nftables.nix {}; #logstash = handleTest ./logstash.nix {}; @@ -206,6 +211,8 @@ in mediawiki = handleTest ./mediawiki.nix {}; memcached = handleTest ./memcached.nix {}; metabase = handleTest ./metabase.nix {}; + minecraft = handleTest ./minecraft.nix {}; + minecraft-server = handleTest ./minecraft-server.nix {}; miniflux = handleTest ./miniflux.nix {}; minio = handleTest ./minio.nix {}; minidlna = handleTest ./minidlna.nix {}; @@ -225,6 +232,7 @@ in mysql-backup = handleTest ./mysql/mysql-backup.nix {}; mysql-replication = handleTest ./mysql/mysql-replication.nix {}; nagios = handleTest ./nagios.nix {}; + nano = handleTest ./nano.nix {}; nar-serve = handleTest ./nar-serve.nix {}; nat.firewall = handleTest ./nat.nix { withFirewall = true; }; nat.firewall-conntrack = handleTest ./nat.nix { withFirewall = true; withConntrackHelpers = true; }; @@ -313,8 +321,10 @@ in runInMachine = handleTest ./run-in-machine.nix {}; rxe = handleTest ./rxe.nix {}; samba = handleTest ./samba.nix {}; + samba-wsdd = handleTest ./samba-wsdd.nix {}; sanoid = handleTest ./sanoid.nix {}; sbt = handleTest ./sbt.nix {}; + sbt-extras = handleTest ./sbt-extras.nix {}; scala = handleTest ./scala.nix {}; sddm = handleTest ./sddm.nix {}; service-runner = handleTest ./service-runner.nix {}; @@ -387,6 +397,7 @@ in xmonad = handleTest ./xmonad.nix {}; xrdp = handleTest ./xrdp.nix {}; xss-lock = handleTest ./xss-lock.nix {}; + xterm = handleTest ./xterm.nix {}; yabar = handleTest ./yabar.nix {}; yggdrasil = handleTest ./yggdrasil.nix {}; zfs = handleTest ./zfs.nix {}; diff --git a/nixos/tests/awscli.nix b/nixos/tests/awscli.nix new file mode 100644 index 0000000000000..35bdd6d99b1a0 --- /dev/null +++ b/nixos/tests/awscli.nix @@ -0,0 +1,17 @@ +import ./make-test-python.nix ({ pkgs, ...} : { + name = "awscli"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ nequissimus ]; + }; + + machine = { pkgs, ... }: + { + environment.systemPackages = [ pkgs.awscli ]; + }; + + testScript = + '' + assert "${pkgs.python3Packages.botocore.version}" in machine.succeed("aws --version") + assert "${pkgs.awscli.version}" in machine.succeed("aws --version") + ''; +}) diff --git a/nixos/tests/bat.nix b/nixos/tests/bat.nix new file mode 100644 index 0000000000000..8e65e235d94f4 --- /dev/null +++ b/nixos/tests/bat.nix @@ -0,0 +1,12 @@ +import ./make-test-python.nix ({ pkgs, ... }: { + name = "bat"; + meta = with pkgs.stdenv.lib.maintainers; { maintainers = [ nequissimus ]; }; + + machine = { pkgs, ... }: { environment.systemPackages = [ pkgs.bat ]; }; + + testScript = '' + machine.succeed("echo 'Foobar\n\n\n42' > /tmp/foo") + assert "Foobar" in machine.succeed("bat -p /tmp/foo") + assert "42" in machine.succeed("bat -p /tmp/foo -r 4:4") + ''; +}) diff --git a/nixos/tests/caddy.nix b/nixos/tests/caddy.nix index f2de34ff2da28..a21dbec248ab2 100644 --- a/nixos/tests/caddy.nix +++ b/nixos/tests/caddy.nix @@ -1,7 +1,7 @@ import ./make-test-python.nix ({ pkgs, ... }: { name = "caddy"; meta = with pkgs.stdenv.lib.maintainers; { - maintainers = [ xfix filalex77 ]; + maintainers = [ xfix Br1ght0ne ]; }; nodes = { diff --git a/nixos/tests/docker-tools.nix b/nixos/tests/docker-tools.nix index c1c41b0fc1100..8e0e82d64cc7c 100644 --- a/nixos/tests/docker-tools.nix +++ b/nixos/tests/docker-tools.nix @@ -234,5 +234,17 @@ import ./make-test-python.nix ({ pkgs, ... }: { "docker run --rm file-in-store nix-store --verify --check-contents", "docker run --rm file-in-store |& grep 'some data'", ) + + with subtest("Ensure cross compiled image can be loaded and has correct arch."): + docker.succeed( + "docker load --input='${pkgs.dockerTools.examples.cross}'", + ) + assert ( + docker.succeed( + "docker inspect ${pkgs.dockerTools.examples.cross.imageName} " + + "| ${pkgs.jq}/bin/jq -r .[].Architecture" + ).strip() + == "${if pkgs.system == "aarch64-linux" then "amd64" else "arm64v8"}" + ) ''; }) diff --git a/nixos/tests/fcitx/config b/nixos/tests/fcitx/config new file mode 100644 index 0000000000000..169768994e280 --- /dev/null +++ b/nixos/tests/fcitx/config @@ -0,0 +1,12 @@ +[Hotkey] +SwitchKey=Disabled +IMSwitchHotkey=ALT_SHIFT +TimeInterval=240 + +[Program] +DelayStart=5 + +[Output] + +[Appearance] + diff --git a/nixos/tests/fcitx/default.nix b/nixos/tests/fcitx/default.nix new file mode 100644 index 0000000000000..cbeb95d33b0cb --- /dev/null +++ b/nixos/tests/fcitx/default.nix @@ -0,0 +1,142 @@ +import ../make-test-python.nix ( + { + pkgs, ... + }: + # copy_from_host works only for store paths + rec { + name = "fcitx"; + machine = + { + pkgs, + ... + }: + { + virtualisation.memorySize = 1024; + + imports = [ + ../common/user-account.nix + ]; + + environment.systemPackages = [ + # To avoid clashing with xfce4-terminal + pkgs.alacritty + ]; + + + services.xserver = + { + enable = true; + + displayManager = { + lightdm.enable = true; + autoLogin = { + enable = true; + user = "alice"; + }; + }; + + desktopManager.xfce.enable = true; + }; + + i18n = { + inputMethod = { + enabled = "fcitx"; + fcitx.engines = [ + pkgs.fcitx-engines.m17n + pkgs.fcitx-engines.table-extra + ]; + }; + }; + } + ; + + testScript = { nodes, ... }: + let + user = nodes.machine.config.users.users.alice; + userName = user.name; + userHome = user.home; + xauth = "${userHome}/.Xauthority"; + fcitx_confdir = "${userHome}/.config/fcitx"; + in + '' + # We need config files before login session + # So copy first thing + + # Point and click would be expensive, + # So configure using files + machine.copy_from_host( + "${./profile}", + "${fcitx_confdir}/profile", + ) + machine.copy_from_host( + "${./config}", + "${fcitx_confdir}/config", + ) + + start_all() + + machine.wait_for_file("${xauth}") + machine.succeed("xauth merge ${xauth}") + + machine.sleep(5) + + machine.succeed("su - ${userName} -c 'alacritty&'") + machine.succeed("su - ${userName} -c 'fcitx&'") + machine.sleep(10) + + ### Type on terminal + machine.send_chars("echo ") + machine.sleep(1) + + ### Start fcitx Unicode input + machine.send_key("ctrl-alt-shift-u") + machine.sleep(5) + machine.sleep(1) + + ### Search for smiling face + machine.send_chars("smil") + machine.sleep(1) + + ### Navigate to the second one + machine.send_key("tab") + machine.sleep(1) + + ### Choose it + machine.send_key("\n") + machine.sleep(1) + + ### Start fcitx language input + machine.send_key("ctrl-spc") + machine.sleep(1) + + ### Default zhengma, enter 一下 + machine.send_chars("a2") + machine.sleep(1) + + ### Switch to Harvard Kyoto + machine.send_key("alt-shift") + machine.sleep(1) + + ### Enter क + machine.send_chars("ka ") + machine.sleep(1) + + machine.send_key("alt-shift") + machine.sleep(1) + + ### Turn off Fcitx + machine.send_key("ctrl-spc") + machine.sleep(1) + + ### Redirect typed characters to a file + machine.send_chars(" > fcitx_test.out\n") + machine.sleep(1) + machine.screenshot("terminal_chars") + + ### Verify that file contents are as expected + file_content = machine.succeed("cat ${userHome}/fcitx_test.out") + assert file_content == "☺一下क\n" + '' + ; + } +) diff --git a/nixos/tests/fcitx/profile b/nixos/tests/fcitx/profile new file mode 100644 index 0000000000000..77497a1496bd1 --- /dev/null +++ b/nixos/tests/fcitx/profile @@ -0,0 +1,4 @@ +[Profile] +IMName=zhengma-large +EnabledIMList=fcitx-keyboard-us:True,zhengma-large:True,m17n_sa_harvard-kyoto:True +PreeditStringInClientWindow=False diff --git a/nixos/tests/gitlab.nix b/nixos/tests/gitlab.nix index 7e4e8bcef92dc..1214cddd09370 100644 --- a/nixos/tests/gitlab.nix +++ b/nixos/tests/gitlab.nix @@ -33,9 +33,9 @@ import ./make-test-python.nix ({ pkgs, lib, ...} : with lib; { initialRootPasswordFile = pkgs.writeText "rootPassword" initialRootPassword; smtp.enable = true; secrets = { - secretFile = pkgs.writeText "secret" "Aig5zaic"; - otpFile = pkgs.writeText "otpsecret" "Riew9mue"; - dbFile = pkgs.writeText "dbsecret" "we2quaeZ"; + secretFile = pkgs.writeText "secret" "r8X9keSKynU7p4aKlh4GO1Bo77g5a7vj"; + otpFile = pkgs.writeText "otpsecret" "Zu5hGx3YvQx40DvI8WoZJQpX2paSDOlG"; + dbFile = pkgs.writeText "dbsecret" "lsGltKWTejOf6JxCVa7nLDenzkO9wPLR"; jwsFile = pkgs.runCommand "oidcKeyBase" {} "${pkgs.openssl}/bin/openssl genrsa 2048 > $out"; }; }; diff --git a/nixos/tests/jq.nix b/nixos/tests/jq.nix new file mode 100644 index 0000000000000..20b67522ee6e6 --- /dev/null +++ b/nixos/tests/jq.nix @@ -0,0 +1,10 @@ +import ./make-test-python.nix ({ pkgs, ... }: { + name = "jq"; + meta = with pkgs.stdenv.lib.maintainers; { maintainers = [ nequissimus ]; }; + + nodes.jq = { pkgs, ... }: { environment.systemPackages = [ pkgs.jq ]; }; + + testScript = '' + assert "world" in jq.succeed('echo \'{"values":["hello","world"]}\'| jq \'.values[1]\''') + ''; +}) diff --git a/nixos/tests/lsd.nix b/nixos/tests/lsd.nix new file mode 100644 index 0000000000000..fee8e95e14ffb --- /dev/null +++ b/nixos/tests/lsd.nix @@ -0,0 +1,12 @@ +import ./make-test-python.nix ({ pkgs, ... }: { + name = "lsd"; + meta = with pkgs.stdenv.lib.maintainers; { maintainers = [ nequissimus ]; }; + + nodes.lsd = { pkgs, ... }: { environment.systemPackages = [ pkgs.lsd ]; }; + + testScript = '' + lsd.succeed('echo "abc" > /tmp/foo') + assert "4 B /tmp/foo" in lsd.succeed('lsd --classic --blocks "size,name" /tmp/foo') + assert "lsd ${pkgs.lsd.version}" in lsd.succeed("lsd --version") + ''; +}) diff --git a/nixos/tests/minecraft-server.nix b/nixos/tests/minecraft-server.nix new file mode 100644 index 0000000000000..53780e4636ca8 --- /dev/null +++ b/nixos/tests/minecraft-server.nix @@ -0,0 +1,37 @@ +let + seed = "2151901553968352745"; + rcon-pass = "foobar"; + rcon-port = 43000; +in import ./make-test-python.nix ({ pkgs, ... }: { + name = "minecraft-server"; + meta = with pkgs.stdenv.lib.maintainers; { maintainers = [ nequissimus ]; }; + + nodes.server = { ... }: { + environment.systemPackages = [ pkgs.mcrcon ]; + + nixpkgs.config.allowUnfree = true; + + services.minecraft-server = { + declarative = true; + enable = true; + eula = true; + serverProperties = { + enable-rcon = true; + level-seed = seed; + online-mode = false; + "rcon.password" = rcon-pass; + "rcon.port" = rcon-port; + }; + }; + + virtualisation.memorySize = 2048; + }; + + testScript = '' + server.wait_for_unit("minecraft-server") + server.wait_for_open_port(${toString rcon-port}) + assert "${seed}" in server.succeed( + "mcrcon -H localhost -P ${toString rcon-port} -p '${rcon-pass}' -c 'seed'" + ) + ''; +}) diff --git a/nixos/tests/minecraft.nix b/nixos/tests/minecraft.nix new file mode 100644 index 0000000000000..e0c35f2d27695 --- /dev/null +++ b/nixos/tests/minecraft.nix @@ -0,0 +1,28 @@ +import ./make-test-python.nix ({ pkgs, lib, ... }: { + name = "minecraft"; + meta = with lib.maintainers; { maintainers = [ nequissimus ]; }; + + nodes.client = { nodes, ... }: + let user = nodes.client.config.users.users.alice; + in { + imports = [ ./common/user-account.nix ./common/x11.nix ]; + + environment.systemPackages = [ pkgs.minecraft ]; + + nixpkgs.config.allowUnfree = true; + + test-support.displayManager.auto.user = user.name; + }; + + enableOCR = true; + + testScript = { nodes, ... }: + let user = nodes.client.config.users.users.alice; + in '' + client.wait_for_x() + client.execute("su - alice -c minecraft-launcher &") + client.wait_for_text("CONTINUE WITHOUT LOGIN") + client.sleep(10) + client.screenshot("launcher") + ''; +}) diff --git a/nixos/tests/morty.nix b/nixos/tests/morty.nix index ff30b7c072bb1..924dce2717e3b 100644 --- a/nixos/tests/morty.nix +++ b/nixos/tests/morty.nix @@ -12,9 +12,9 @@ import ./make-test-python.nix ({ pkgs, ... }: { ... }: { services.morty = { enable = true; - key = "78a9cd0cfee20c672f78427efb2a2a96036027f0"; - port = 3001; - }; + key = "78a9cd0cfee20c672f78427efb2a2a96036027f0"; + port = 3001; + }; }; }; diff --git a/nixos/tests/nano.nix b/nixos/tests/nano.nix new file mode 100644 index 0000000000000..9e0a9e147f2c5 --- /dev/null +++ b/nixos/tests/nano.nix @@ -0,0 +1,44 @@ +import ./make-test-python.nix ({ pkgs, ...} : { + name = "nano"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ nequissimus ]; + }; + + machine = { lib, ... }: { + environment.systemPackages = [ pkgs.nano ]; + }; + + testScript = { ... }: '' + start_all() + + with subtest("Create user and log in"): + machine.wait_for_unit("multi-user.target") + machine.wait_until_succeeds("pgrep -f 'agetty.*tty1'") + machine.succeed("useradd -m alice") + machine.succeed("(echo foobar; echo foobar) | passwd alice") + machine.wait_until_tty_matches(1, "login: ") + machine.send_chars("alice\n") + machine.wait_until_tty_matches(1, "login: alice") + machine.wait_until_succeeds("pgrep login") + machine.wait_until_tty_matches(1, "Password: ") + machine.send_chars("foobar\n") + machine.wait_until_succeeds("pgrep -u alice bash") + machine.screenshot("prompt") + + with subtest("Use nano"): + machine.send_chars("nano /tmp/foo") + machine.send_key("ret") + machine.sleep(2) + machine.send_chars("42") + machine.sleep(1) + machine.send_key("ctrl-x") + machine.sleep(1) + machine.send_key("y") + machine.sleep(1) + machine.screenshot("nano") + machine.sleep(1) + machine.send_key("ret") + machine.wait_for_file("/tmp/foo") + assert "42" in machine.succeed("cat /tmp/foo") + ''; +}) diff --git a/nixos/tests/networking.nix b/nixos/tests/networking.nix index 83d4f6465b686..4fc5d48e0e173 100644 --- a/nixos/tests/networking.nix +++ b/nixos/tests/networking.nix @@ -499,8 +499,8 @@ let list, targetList ) with subtest("Test MTU and MAC Address are configured"): - assert "mtu 1342" in machine.succeed("ip link show dev tap0") - assert "mtu 1343" in machine.succeed("ip link show dev tun0") + machine.wait_until_succeeds("ip link show dev tap0 | grep 'mtu 1342'") + machine.wait_until_succeeds("ip link show dev tun0 | grep 'mtu 1343'") assert "02:de:ad:be:ef:01" in machine.succeed("ip link show dev tap0") '' # network-addresses-* only exist in scripted networking + optionalString (!networkd) '' diff --git a/nixos/tests/openldap.nix b/nixos/tests/openldap.nix index f8321a2c522dc..392fae243467b 100644 --- a/nixos/tests/openldap.nix +++ b/nixos/tests/openldap.nix @@ -1,33 +1,125 @@ -import ./make-test-python.nix { - name = "openldap"; - - machine = { pkgs, ... }: { - services.openldap = { - enable = true; - suffix = "dc=example"; - rootdn = "cn=root,dc=example"; - rootpw = "notapassword"; - database = "bdb"; - extraDatabaseConfig = '' - directory /var/db/openldap - ''; - declarativeContents = '' - dn: dc=example - objectClass: domain - dc: example - - dn: ou=users,dc=example - objectClass: organizationalUnit - ou: users - ''; - }; - }; +{ pkgs, system ? builtins.currentSystem, ... }: let + dbContents = '' + dn: dc=example + objectClass: domain + dc: example + dn: ou=users,dc=example + objectClass: organizationalUnit + ou: users + ''; testScript = '' machine.wait_for_unit("openldap.service") machine.succeed( - "systemctl status openldap.service", 'ldapsearch -LLL -D "cn=root,dc=example" -w notapassword -b "dc=example"', ) ''; +in { + # New-style configuration + current = import ./make-test-python.nix { + inherit testScript; + name = "openldap"; + + machine = { pkgs, ... }: { + environment.etc."openldap/root_password".text = "notapassword"; + services.openldap = { + enable = true; + settings = { + children = { + "cn=schema".includes = [ + "${pkgs.openldap}/etc/schema/core.ldif" + "${pkgs.openldap}/etc/schema/cosine.ldif" + "${pkgs.openldap}/etc/schema/inetorgperson.ldif" + "${pkgs.openldap}/etc/schema/nis.ldif" + ]; + "olcDatabase={1}mdb" = { + # This tests string, base64 and path values, as well as lists of string values + attrs = { + objectClass = [ "olcDatabaseConfig" "olcMdbConfig" ]; + olcDatabase = "{1}mdb"; + olcDbDirectory = "/var/db/openldap"; + olcSuffix = "dc=example"; + olcRootDN = { + # cn=root,dc=example + base64 = "Y249cm9vdCxkYz1leGFtcGxl"; + }; + olcRootPW = { + path = "/etc/openldap/root_password"; + }; + }; + }; + }; + }; + declarativeContents."dc=example" = dbContents; + }; + }; + }; + + # Old-style configuration + oldOptions = import ./make-test-python.nix { + inherit testScript; + name = "openldap"; + + machine = { pkgs, ... }: { + services.openldap = { + enable = true; + logLevel = "stats acl"; + defaultSchemas = true; + database = "mdb"; + suffix = "dc=example"; + rootdn = "cn=root,dc=example"; + rootpw = "notapassword"; + declarativeContents."dc=example" = dbContents; + }; + }; + }; + + # Manually managed configDir, for example if dynamic config is essential + manualConfigDir = import ./make-test-python.nix { + name = "openldap"; + + machine = { pkgs, ... }: { + services.openldap = { + enable = true; + configDir = "/var/db/slapd.d"; + }; + }; + + testScript = let + contents = pkgs.writeText "data.ldif" dbContents; + config = pkgs.writeText "config.ldif" '' + dn: cn=config + cn: config + objectClass: olcGlobal + olcLogLevel: stats + olcPidFile: /run/slapd/slapd.pid + + dn: cn=schema,cn=config + cn: schema + objectClass: olcSchemaConfig + + include: file://${pkgs.openldap}/etc/schema/core.ldif + include: file://${pkgs.openldap}/etc/schema/cosine.ldif + include: file://${pkgs.openldap}/etc/schema/inetorgperson.ldif + + dn: olcDatabase={1}mdb,cn=config + objectClass: olcDatabaseConfig + objectClass: olcMdbConfig + olcDatabase: {1}mdb + olcDbDirectory: /var/db/openldap + olcDbIndex: objectClass eq + olcSuffix: dc=example + olcRootDN: cn=root,dc=example + olcRootPW: notapassword + ''; + in '' + machine.succeed( + "mkdir -p /var/db/slapd.d /var/db/openldap", + "slapadd -F /var/db/slapd.d -n0 -l ${config}", + "slapadd -F /var/db/slapd.d -n1 -l ${contents}", + "chown -R openldap:openldap /var/db/slapd.d /var/db/openldap", + "systemctl restart openldap", + ) + '' + testScript; + }; } diff --git a/nixos/tests/os-prober.nix b/nixos/tests/os-prober.nix index be0235a417536..f778d30bdc06c 100644 --- a/nixos/tests/os-prober.nix +++ b/nixos/tests/os-prober.nix @@ -9,7 +9,7 @@ let ${parted}/sbin/parted --script /dev/vda -- mkpart primary ext2 1M -1s mkdir /mnt ${e2fsprogs}/bin/mkfs.ext4 /dev/vda1 - ${utillinux}/bin/mount -t ext4 /dev/vda1 /mnt + ${util-linux}/bin/mount -t ext4 /dev/vda1 /mnt if test -e /mnt/.debug; then exec ${bash}/bin/sh diff --git a/nixos/tests/postfix.nix b/nixos/tests/postfix.nix index 37ae76afec107..6d22b4edba0a2 100644 --- a/nixos/tests/postfix.nix +++ b/nixos/tests/postfix.nix @@ -11,9 +11,9 @@ import ./make-test-python.nix { enable = true; enableSubmission = true; enableSubmissions = true; - sslCACert = certs.ca.cert; - sslCert = certs.${domain}.cert; - sslKey = certs.${domain}.key; + tlsTrustedAuthorities = "${certs.ca.cert}"; + sslCert = "${certs.${domain}.cert}"; + sslKey = "${certs.${domain}.key}"; submissionsOptions = { smtpd_sasl_auth_enable = "yes"; smtpd_client_restrictions = "permit"; diff --git a/nixos/tests/quorum.nix b/nixos/tests/quorum.nix index 846d2a9301889..d5906806a0a2b 100644 --- a/nixos/tests/quorum.nix +++ b/nixos/tests/quorum.nix @@ -55,7 +55,7 @@ import ./make-test-python.nix ({ pkgs, ... }: { parentHash = "0x0000000000000000000000000000000000000000000000000000000000000000"; timestamp = "0x5cffc201"; - }; + }; }; }; }; diff --git a/nixos/tests/riak.nix b/nixos/tests/riak.nix index 6915779e7e9c2..3dd4e333d6691 100644 --- a/nixos/tests/riak.nix +++ b/nixos/tests/riak.nix @@ -1,7 +1,7 @@ import ./make-test-python.nix ({ lib, pkgs, ... }: { name = "riak"; meta = with lib.maintainers; { - maintainers = [ filalex77 ]; + maintainers = [ Br1ght0ne ]; }; machine = { diff --git a/nixos/tests/rspamd.nix b/nixos/tests/rspamd.nix index bf3f0de620445..6eaa02ef42917 100644 --- a/nixos/tests/rspamd.nix +++ b/nixos/tests/rspamd.nix @@ -209,7 +209,7 @@ in return false end, score = 5.0, - description = 'Allow no cows', + description = 'Allow no cows', group = "cows", } rspamd_logger.infox(rspamd_config, 'Work dammit!!!') diff --git a/nixos/tests/samba-wsdd.nix b/nixos/tests/samba-wsdd.nix new file mode 100644 index 0000000000000..1edef6c0056de --- /dev/null +++ b/nixos/tests/samba-wsdd.nix @@ -0,0 +1,44 @@ +import ./make-test-python.nix ({ pkgs, ... }: + +{ + name = "samba-wsdd"; + meta.maintainers = with pkgs.stdenv.lib.maintainers; [ izorkin ]; + + nodes = { + client_wsdd = { pkgs, ... }: { + services.samba-wsdd = { + enable = true; + interface = "eth1"; + workgroup = "WORKGROUP"; + hostname = "CLIENT-WSDD"; + discovery = true; + extraOptions = [ "--no-host" ]; + }; + networking.firewall.allowedTCPPorts = [ 5357 ]; + networking.firewall.allowedUDPPorts = [ 3702 ]; + }; + + server_wsdd = { ... }: { + services.samba-wsdd = { + enable = true; + interface = "eth1"; + workgroup = "WORKGROUP"; + hostname = "SERVER-WSDD"; + }; + networking.firewall.allowedTCPPorts = [ 5357 ]; + networking.firewall.allowedUDPPorts = [ 3702 ]; + }; + }; + + testScript = '' + client_wsdd.start() + client_wsdd.wait_for_unit("samba-wsdd") + + server_wsdd.start() + server_wsdd.wait_for_unit("samba-wsdd") + + client_wsdd.wait_until_succeeds( + "echo list | ${pkgs.libressl.nc}/bin/nc -U /run/wsdd/wsdd.sock | grep -i SERVER-WSDD" + ) + ''; +}) diff --git a/nixos/tests/sbt-extras.nix b/nixos/tests/sbt-extras.nix new file mode 100644 index 0000000000000..d63113f943e4e --- /dev/null +++ b/nixos/tests/sbt-extras.nix @@ -0,0 +1,16 @@ +import ./make-test-python.nix ({ pkgs, ...} : { + name = "sbt-extras"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ nequissimus ]; + }; + + machine = { pkgs, ... }: + { + environment.systemPackages = [ pkgs.sbt-extras ]; + }; + + testScript = + '' + machine.succeed("(sbt -h)") + ''; +}) diff --git a/nixos/tests/sssd-ldap.nix b/nixos/tests/sssd-ldap.nix index b68403a0102a8..4831eaa4ba20b 100644 --- a/nixos/tests/sssd-ldap.nix +++ b/nixos/tests/sssd-ldap.nix @@ -1,4 +1,4 @@ -import ./make-test-python.nix ({ pkgs, ... }: +({ pkgs, ... }: let dbDomain = "example.org"; dbSuffix = "dc=example,dc=org"; @@ -7,8 +7,7 @@ import ./make-test-python.nix ({ pkgs, ... }: ldapRootPassword = "foobar"; testUser = "alice"; - in - { + in import ./make-test-python.nix { name = "sssd-ldap"; meta = with pkgs.stdenv.lib.maintainers; { @@ -18,34 +17,53 @@ import ./make-test-python.nix ({ pkgs, ... }: machine = { pkgs, ... }: { services.openldap = { enable = true; - rootdn = "cn=${ldapRootUser},${dbSuffix}"; - rootpw = ldapRootPassword; - suffix = dbSuffix; - declarativeContents = '' - dn: ${dbSuffix} - objectClass: top - objectClass: dcObject - objectClass: organization - o: ${dbDomain} + settings = { + children = { + "cn=schema".includes = [ + "${pkgs.openldap}/etc/schema/core.ldif" + "${pkgs.openldap}/etc/schema/cosine.ldif" + "${pkgs.openldap}/etc/schema/inetorgperson.ldif" + "${pkgs.openldap}/etc/schema/nis.ldif" + ]; + "olcDatabase={1}mdb" = { + attrs = { + objectClass = [ "olcDatabaseConfig" "olcMdbConfig" ]; + olcDatabase = "{1}mdb"; + olcDbDirectory = "/var/db/openldap"; + olcSuffix = dbSuffix; + olcRootDN = "cn=${ldapRootUser},${dbSuffix}"; + olcRootPW = ldapRootPassword; + }; + }; + }; + }; + declarativeContents = { + ${dbSuffix} = '' + dn: ${dbSuffix} + objectClass: top + objectClass: dcObject + objectClass: organization + o: ${dbDomain} - dn: ou=posix,${dbSuffix} - objectClass: top - objectClass: organizationalUnit + dn: ou=posix,${dbSuffix} + objectClass: top + objectClass: organizationalUnit - dn: ou=accounts,ou=posix,${dbSuffix} - objectClass: top - objectClass: organizationalUnit + dn: ou=accounts,ou=posix,${dbSuffix} + objectClass: top + objectClass: organizationalUnit - dn: uid=${testUser},ou=accounts,ou=posix,${dbSuffix} - objectClass: person - objectClass: posixAccount - # userPassword: somePasswordHash - homeDirectory: /home/${testUser} - uidNumber: 1234 - gidNumber: 1234 - cn: "" - sn: "" - ''; + dn: uid=${testUser},ou=accounts,ou=posix,${dbSuffix} + objectClass: person + objectClass: posixAccount + # userPassword: somePasswordHash + homeDirectory: /home/${testUser} + uidNumber: 1234 + gidNumber: 1234 + cn: "" + sn: "" + ''; + }; }; services.sssd = { diff --git a/nixos/tests/systemd.nix b/nixos/tests/systemd.nix index dfa16eecfad21..0fc788f860f74 100644 --- a/nixos/tests/systemd.nix +++ b/nixos/tests/systemd.nix @@ -26,7 +26,7 @@ import ./make-test-python.nix ({ pkgs, ... }: { systemd.shutdown.test = pkgs.writeScript "test.shutdown" '' #!${pkgs.runtimeShell} - PATH=${lib.makeBinPath (with pkgs; [ utillinux coreutils ])} + PATH=${lib.makeBinPath (with pkgs; [ util-linux coreutils ])} mount -t 9p shared -o trans=virtio,version=9p2000.L /tmp/shared touch /tmp/shared/shutdown-test umount /tmp/shared diff --git a/nixos/tests/telegraf.nix b/nixos/tests/telegraf.nix index 73f741b113574..7f4b367525821 100644 --- a/nixos/tests/telegraf.nix +++ b/nixos/tests/telegraf.nix @@ -6,12 +6,15 @@ import ./make-test-python.nix ({ pkgs, ...} : { machine = { ... }: { services.telegraf.enable = true; + services.telegraf.environmentFiles = [(pkgs.writeText "secrets" '' + SECRET=example + '')]; services.telegraf.extraConfig = { agent.interval = "1s"; agent.flush_interval = "1s"; inputs.exec = { commands = [ - "${pkgs.runtimeShell} -c 'echo example,tag=a i=42i'" + "${pkgs.runtimeShell} -c 'echo $SECRET,tag=a i=42i'" ]; timeout = "5s"; data_format = "influx"; diff --git a/nixos/tests/virtualbox.nix b/nixos/tests/virtualbox.nix index 0d9eafa4a20f3..900ee610a70b9 100644 --- a/nixos/tests/virtualbox.nix +++ b/nixos/tests/virtualbox.nix @@ -24,7 +24,7 @@ let miniInit = '' #!${pkgs.runtimeShell} -xe - export PATH="${lib.makeBinPath [ pkgs.coreutils pkgs.utillinux ]}" + export PATH="${lib.makeBinPath [ pkgs.coreutils pkgs.util-linux ]}" mkdir -p /run/dbus cat > /etc/passwd <<EOF @@ -72,7 +72,7 @@ let boot.initrd.extraUtilsCommands = '' copy_bin_and_libs "${guestAdditions}/bin/mount.vboxsf" - copy_bin_and_libs "${pkgs.utillinux}/bin/unshare" + copy_bin_and_libs "${pkgs.util-linux}/bin/unshare" ${(attrs.extraUtilsCommands or (const "")) pkgs} ''; @@ -122,7 +122,7 @@ let "$diskImage" "$out/disk.vdi" ''; - buildInputs = [ pkgs.utillinux pkgs.perl ]; + buildInputs = [ pkgs.util-linux pkgs.perl ]; } '' ${pkgs.parted}/sbin/parted --script /dev/vda mklabel msdos ${pkgs.parted}/sbin/parted --script /dev/vda -- mkpart primary ext2 1M -1s diff --git a/nixos/tests/xterm.nix b/nixos/tests/xterm.nix new file mode 100644 index 0000000000000..9f30543bf3859 --- /dev/null +++ b/nixos/tests/xterm.nix @@ -0,0 +1,23 @@ +import ./make-test-python.nix ({ pkgs, ...} : { + name = "xterm"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ nequissimus ]; + }; + + machine = { pkgs, ... }: + { + imports = [ ./common/x11.nix ]; + services.xserver.desktopManager.xterm.enable = false; + }; + + testScript = + '' + machine.wait_for_x() + machine.succeed("DISPLAY=:0 xterm -title testterm -class testterm -fullscreen &") + machine.sleep(2) + machine.send_chars("echo $XTERM_VERSION >> /tmp/xterm_version\n") + machine.wait_for_file("/tmp/xterm_version") + assert "${pkgs.xterm.version}" in machine.succeed("cat /tmp/xterm_version") + machine.screenshot("window") + ''; +}) diff --git a/nixos/tests/zfs.nix b/nixos/tests/zfs.nix index 87e6c900c98e0..e05cd540227a6 100644 --- a/nixos/tests/zfs.nix +++ b/nixos/tests/zfs.nix @@ -18,7 +18,7 @@ let maintainers = [ adisbladis ]; }; - machine = { pkgs, ... }: { + machine = { pkgs, lib, ... }: { virtualisation.emptyDiskImages = [ 4096 ]; networking.hostId = "deadbeef"; boot.kernelPackages = kernelPackage; @@ -26,6 +26,24 @@ let boot.zfs.enableUnstable = enableUnstable; environment.systemPackages = [ pkgs.parted ]; + + # Setup regular fileSystems machinery to ensure forceImportAll can be + # tested via the regular service units. + fileSystems = lib.mkVMOverride { + "/forcepool" = { + device = "forcepool"; + fsType = "zfs"; + options = [ "noauto" ]; + }; + }; + + # forcepool doesn't exist at first boot, and we need to manually test + # the import after tweaking the hostId. + systemd.services.zfs-import-forcepool.wantedBy = lib.mkVMOverride []; + systemd.targets.zfs.wantedBy = lib.mkVMOverride []; + boot.zfs.forceImportAll = true; + # /dev/disk/by-id doesn't get populated in the NixOS test framework + boot.zfs.devNodes = "/dev/disk/by-uuid"; }; testScript = '' @@ -57,6 +75,21 @@ let "zpool destroy rpool", "udevadm settle", ) + + with subtest("boot.zfs.forceImportAll works"): + machine.succeed( + "rm /etc/hostid", + "zgenhostid deadcafe", + "zpool create forcepool /dev/vdb1 -O mountpoint=legacy", + ) + machine.shutdown() + machine.start() + machine.succeed("udevadm settle") + machine.fail("zpool import forcepool") + machine.succeed( + "systemctl start zfs-import-forcepool.service", + "mount -t zfs forcepool /tmp/mnt", + ) '' + extraTest; }; |