diff options
author | Parnell Springmeyer <parnell@digitalmentat.com> | 2018-01-10 10:13:49 -0800 |
---|---|---|
committer | Parnell Springmeyer <parnell@digitalmentat.com> | 2018-01-10 10:13:49 -0800 |
commit | e4ec980e9ced7dbea0fb1310f831207bbc7175b0 (patch) | |
tree | 0c9ec3233fc73958db0637d409a44c527f0984eb /nixos | |
parent | a6cdf0aaa17530773f1de918c88a1f3245fd2612 (diff) | |
parent | 80cb0c39de929f7e8e65d587cb22af777db98bea (diff) | |
download | nixlib-e4ec980e9ced7dbea0fb1310f831207bbc7175b0.tar nixlib-e4ec980e9ced7dbea0fb1310f831207bbc7175b0.tar.gz nixlib-e4ec980e9ced7dbea0fb1310f831207bbc7175b0.tar.bz2 nixlib-e4ec980e9ced7dbea0fb1310f831207bbc7175b0.tar.lz nixlib-e4ec980e9ced7dbea0fb1310f831207bbc7175b0.tar.xz nixlib-e4ec980e9ced7dbea0fb1310f831207bbc7175b0.tar.zst nixlib-e4ec980e9ced7dbea0fb1310f831207bbc7175b0.zip |
Merge remote-tracking branch 'upstream/master' into parnell/fetchdocker
Diffstat (limited to 'nixos')
127 files changed, 3200 insertions, 1511 deletions
diff --git a/nixos/doc/manual/configuration/firewall.xml b/nixos/doc/manual/configuration/firewall.xml index 87406c28c2f7..75cccef95b38 100644 --- a/nixos/doc/manual/configuration/firewall.xml +++ b/nixos/doc/manual/configuration/firewall.xml @@ -23,10 +23,23 @@ networking.firewall.allowedTCPPorts = [ 80 443 ]; </programlisting> Note that TCP port 22 (ssh) is opened automatically if the SSH daemon -is enabled (<option>services.openssh.enable = true</option>). UDP +is enabled (<option>services.openssh.enable = true</option>). UDP ports can be opened through -<option>networking.firewall.allowedUDPPorts</option>. Also of -interest is +<option>networking.firewall.allowedUDPPorts</option>.</para> + +<para>To open ranges of TCP ports: + +<programlisting> +networking.firewall.allowedTCPPortRanges = [ + { from = 4000; to = 4007; } + { from = 8000; to = 8010; } +]; +</programlisting> + +Similarly, UDP port ranges can be opened through +<option>networking.firewall.allowedUDPPortRanges</option>.</para> + +<para>Also of interest is <programlisting> networking.firewall.allowPing = true; diff --git a/nixos/doc/manual/configuration/x-windows.xml b/nixos/doc/manual/configuration/x-windows.xml index fc6082ce3afd..9c2c59006f15 100644 --- a/nixos/doc/manual/configuration/x-windows.xml +++ b/nixos/doc/manual/configuration/x-windows.xml @@ -115,13 +115,14 @@ hardware.opengl.driSupport32Bit = true; <para>Support for Synaptics touchpads (found in many laptops such as the Dell Latitude series) can be enabled as follows: <programlisting> -services.xserver.synaptics.enable = true; +services.xserver.libinput.enable = true; </programlisting> The driver has many options (see <xref linkend="ch-options"/>). For -instance, the following enables two-finger scrolling: +instance, the following disables tap-to-click behavior: <programlisting> -services.xserver.synaptics.twoFingerScroll = true; +services.xserver.libinput.tapping = false; </programlisting> +Note: the use of <literal>services.xserver.synaptics</literal> is deprecated since NixOS 17.09. </para> </simplesect> @@ -129,7 +130,7 @@ services.xserver.synaptics.twoFingerScroll = true; <simplesect><title>GTK/Qt themes</title> <para>GTK themes can be installed either to user profile or system-wide (via -<literal>system.environmentPackages</literal>). To make Qt 5 applications look similar +<literal>environment.systemPackages</literal>). To make Qt 5 applications look similar to GTK2 ones, you can install <literal>qt5.qtbase.gtk</literal> package into your system environment. It should work for all Qt 5 library versions. </para> diff --git a/nixos/doc/manual/development/option-declarations.xml b/nixos/doc/manual/development/option-declarations.xml index be793152f9ef..ed718c89eb77 100644 --- a/nixos/doc/manual/development/option-declarations.xml +++ b/nixos/doc/manual/development/option-declarations.xml @@ -22,6 +22,15 @@ options = { }; </programlisting> +The attribute names within the <replaceable>name</replaceable> +attribute path must be camel cased in general but should, as an +exception, match the +<link +xlink:href="https://nixos.org/nixpkgs/manual/#sec-package-naming"> +package attribute name</link> when referencing a Nixpkgs package. For +example, the option <varname>services.nix-serve.bindAddress</varname> +references the <varname>nix-serve</varname> Nixpkgs package. + </para> <para>The function <varname>mkOption</varname> accepts the following arguments. diff --git a/nixos/doc/manual/development/option-types.xml b/nixos/doc/manual/development/option-types.xml index 83dcf0232d9d..ec940d5d2b86 100644 --- a/nixos/doc/manual/development/option-types.xml +++ b/nixos/doc/manual/development/option-types.xml @@ -110,6 +110,12 @@ <listitem><para>A string. Multiple definitions are concatenated with a collon <literal>":"</literal>.</para></listitem> </varlistentry> + <varlistentry> + <term><varname>types.strMatching</varname></term> + <listitem><para>A string matching a specific regular expression. Multiple + definitions cannot be merged. The regular expression is processed using + <literal>builtins.match</literal>.</para></listitem> + </varlistentry> </variablelist> </section> diff --git a/nixos/doc/manual/development/writing-nixos-tests.xml b/nixos/doc/manual/development/writing-nixos-tests.xml index 7b25a39e83b8..a8f6aa00858e 100644 --- a/nixos/doc/manual/development/writing-nixos-tests.xml +++ b/nixos/doc/manual/development/writing-nixos-tests.xml @@ -272,8 +272,37 @@ startAll; </listitem> </varlistentry> + <varlistentry> + <term><methodname>systemctl</methodname></term> + <listitem> + <para>Runs <literal>systemctl</literal> commands with optional support for + <literal>systemctl --user</literal></para> + <para> + <programlisting> + $machine->systemctl("list-jobs --no-pager"); // runs `systemctl list-jobs --no-pager` + $machine->systemctl("list-jobs --no-pager", "any-user"); // spawns a shell for `any-user` and runs `systemctl --user list-jobs --no-pager` + </programlisting> + </para> + </listitem> + </varlistentry> + </variablelist> </para> +<para> + To test user units declared by <literal>systemd.user.services</literal> the optional <literal>$user</literal> + argument can be used: + + <programlisting> + $machine->start; + $machine->waitForX; + $machine->waitForUnit("xautolock.service", "x-session-user"); + </programlisting> + + This applies to <literal>systemctl</literal>, <literal>getUnitInfo</literal>, + <literal>waitForUnit</literal>, <literal>startJob</literal> + and <literal>stopJob</literal>. +</para> + </section> diff --git a/nixos/doc/manual/installation/installing-uefi.xml b/nixos/doc/manual/installation/installing-uefi.xml deleted file mode 100644 index 0d3eaa8bb1fb..000000000000 --- a/nixos/doc/manual/installation/installing-uefi.xml +++ /dev/null @@ -1,48 +0,0 @@ -<section xmlns="http://docbook.org/ns/docbook" - xmlns:xlink="http://www.w3.org/1999/xlink" - xmlns:xi="http://www.w3.org/2001/XInclude" - version="5.0" - xml:id="sec-uefi-installation"> - -<title>UEFI Installation</title> - -<para>NixOS can also be installed on UEFI systems. The procedure -is by and large the same as a BIOS installation, with the following -changes: - -<itemizedlist> - <listitem> - <para>You should boot the live CD in UEFI mode (consult your - specific hardware's documentation for instructions). You may find - the <link - xlink:href="http://www.rodsbooks.com/refind">rEFInd - boot manager</link> useful.</para> - </listitem> - <listitem> - <para>Instead of <command>fdisk</command>, you should use - <command>gdisk</command> to partition your disks. You will need to - have a separate partition for <filename>/boot</filename> with - partition code EF00, and it should be formatted as a - <literal>vfat</literal> filesystem.</para> - </listitem> - <listitem> - <para>Instead of <option>boot.loader.grub.device</option>, - you must set <option>boot.loader.systemd-boot.enable</option> to - <literal>true</literal>. <command>nixos-generate-config</command> - should do this automatically for new configurations when booted in - UEFI mode.</para> - </listitem> - <listitem> - <para>After having mounted your installation partition to - <code>/mnt</code>, you must mount the <code>boot</code> partition - to <code>/mnt/boot</code>.</para> - </listitem> - <listitem> - <para>You may want to look at the options starting with - <option>boot.loader.efi</option> and <option>boot.loader.systemd-boot</option> - as well.</para> - </listitem> -</itemizedlist> -</para> - -</section> diff --git a/nixos/doc/manual/installation/installing-usb.xml b/nixos/doc/manual/installation/installing-usb.xml index 31d51816e39b..122a4745f194 100644 --- a/nixos/doc/manual/installation/installing-usb.xml +++ b/nixos/doc/manual/installation/installing-usb.xml @@ -11,10 +11,24 @@ a USB stick. You can use the <command>dd</command> utility to write the image: <command>dd if=<replaceable>path-to-image</replaceable> of=<replaceable>/dev/sdb</replaceable></command>. Be careful about specifying the correct drive; you can use the <command>lsblk</command> command to get a list of -block devices. If you're on macOS you can run <command>diskutil list</command> -to see the list of devices; the device you'll use for the USB must be ejected -before writing the image.</para> +block devices.</para> +<para>On macOS: +<programlisting> +$ diskutil list +[..] +/dev/diskN (external, physical): + #: TYPE NAME SIZE IDENTIFIER +[..] +$ diskutil unmountDisk diskN +Unmount of all volumes on diskN was successful +$ sudo dd bs=1m if=nix.iso of=/dev/rdiskN +</programlisting> +Using the 'raw' <command>rdiskN</command> device instead of <command>diskN</command> +completes in minutes instead of hours. After <command>dd</command> completes, a GUI +dialog "The disk you inserted was not readable by this computer" will pop up, which +can be ignored.</para> + <para>The <command>dd</command> utility will write the image verbatim to the drive, making it the recommended option for both UEFI and non-UEFI installations. For non-UEFI installations, you can alternatively use diff --git a/nixos/doc/manual/installation/installing.xml b/nixos/doc/manual/installation/installing.xml index b0674307a563..ab9108c30a71 100644 --- a/nixos/doc/manual/installation/installing.xml +++ b/nixos/doc/manual/installation/installing.xml @@ -6,9 +6,18 @@ <title>Installing NixOS</title> +<para>NixOS can be installed on BIOS or UEFI systems. The procedure +for a UEFI installation is by and large the same as a BIOS installation. The differences are mentioned in the steps that follow.</para> + <orderedlist> - <listitem><para>Boot from the CD.</para></listitem> + <listitem><para>Boot from the CD.</para> + <variablelist> + <varlistentry><term>UEFI systems</term> + <listitem><para>You should boot the live CD in UEFI mode + (consult your specific hardware's documentation for instructions). + You may find the <link xlink:href="http://www.rodsbooks.com/refind">rEFInd boot + manager</link> useful.</para></listitem></varlistentry></variablelist></listitem> <listitem><para>The CD contains a basic NixOS installation. (It also contains Memtest86+, useful if you want to test new hardware). @@ -50,7 +59,31 @@ <itemizedlist> <listitem><para>For partitioning: - <command>fdisk</command>.</para></listitem> + <command>fdisk</command>. +<screen> +# fdisk /dev/sda # <lineannotation>(or whatever device you want to install on)</lineannotation> +-- for UEFI systems only +> n # <lineannotation>(create a new partition for /boot)</lineannotation> +> 3 # <lineannotation>(make it a partition number 3)</lineannotation> +> # <lineannotation>(press enter to accept the default)</lineannotation> +> +512M # <lineannotation>(the size of the UEFI boot partition)</lineannotation> +> t # <lineannotation>(change the partition type ...)</lineannotation> +> 3 # <lineannotation>(... of the boot partition ...)</lineannotation> +> 1 # <lineannotation>(... to 'UEFI System')</lineannotation> +-- for BIOS or UEFI systems +> n # <lineannotation>(create a new partition for /swap)</lineannotation> +> 2 # <lineannotation>(make it a partition number 2)</lineannotation> +> # <lineannotation>(press enter to accept the default)</lineannotation> +> +8G # <lineannotation>(the size of the swap partition, set to whatever you like)</lineannotation> +> n # <lineannotation>(create a new partition for /)</lineannotation> +> 1 # <lineannotation>(make it a partition number 1)</lineannotation> +> # <lineannotation>(press enter to accept the default)</lineannotation> +> # <lineannotation>(press enter to accept the default and use the rest of the remaining space)</lineannotation> +> a # <lineannotation>(make the partition bootable)</lineannotation> +> x # <lineannotation>(enter expert mode)</lineannotation> +> f # <lineannotation>(fix up the partition ordering)</lineannotation> +> r # <lineannotation>(exit expert mode)</lineannotation> +> w # <lineannotation>(write the partition table to disk and exit)</lineannotation></screen></para></listitem> <listitem><para>For initialising Ext4 partitions: <command>mkfs.ext4</command>. It is recommended that you assign a @@ -67,7 +100,25 @@ <listitem><para>For creating swap partitions: <command>mkswap</command>. Again it’s recommended to assign a label to the swap partition: <option>-L - <replaceable>label</replaceable></option>.</para></listitem> + <replaceable>label</replaceable></option>. For example: + +<screen> +# mkswap -L swap /dev/sda2</screen> + + </para></listitem> + + <listitem> + <variablelist> + <varlistentry><term>UEFI systems</term> + <listitem><para>For creating boot partitions: + <command>mkfs.fat</command>. Again it’s recommended to assign a + label to the boot partition: <option>-L + <replaceable>label</replaceable></option>. For example: + +<screen> +# mkfs.fat -F 32 -L boot /dev/sda3</screen> + + </para></listitem></varlistentry></variablelist></listitem> <listitem><para>For creating LVM volumes, the LVM commands, e.g., @@ -95,11 +146,27 @@ </para></listitem> + <listitem> + <variablelist> + <varlistentry><term>UEFI systems</term> + <listitem><para>Mount the boot file system on <filename>/mnt/boot</filename>, e.g. + +<screen> +# mount /dev/disk/by-label/boot /mnt/boot +</screen> + + </para></listitem></varlistentry></variablelist></listitem> + <listitem><para>If your machine has a limited amount of memory, you may want to activate swap devices now (<command>swapon <replaceable>device</replaceable></command>). The installer (or rather, the build actions that it may spawn) may need quite a bit of - RAM, depending on your configuration.</para></listitem> + RAM, depending on your configuration. + +<screen> +# swapon /dev/sda2</screen> + + </para></listitem> <listitem> @@ -135,10 +202,25 @@ install Emacs by running <literal>nix-env -i emacs</literal>.</para> - <para>You <emphasis>must</emphasis> set the option + <variablelist> + + <varlistentry><term>BIOS systems</term> + <listitem><para>You <emphasis>must</emphasis> set the option <option>boot.loader.grub.device</option> to specify on which disk the GRUB boot loader is to be installed. Without it, NixOS cannot - boot.</para> + boot.</para></listitem></varlistentry> + + <varlistentry><term>UEFI systems</term> + <listitem><para>You <emphasis>must</emphasis> set the option + <option>boot.loader.systemd-boot.enable</option> to <literal>true</literal>. + <command>nixos-generate-config</command> should do this automatically for new + configurations when booted in + UEFI mode.</para> + <para>You may want to look at the options starting with + <option>boot.loader.efi</option> and <option>boot.loader.systemd-boot</option> + as well.</para></listitem></varlistentry> + + </variablelist> <para>If there are other operating systems running on the machine before installing NixOS, the @@ -247,10 +329,34 @@ drive (here <filename>/dev/sda</filename>). <xref linkend="ex-config" <example xml:id='ex-install-sequence'><title>Commands for Installing NixOS on <filename>/dev/sda</filename></title> <screen> # fdisk /dev/sda # <lineannotation>(or whatever device you want to install on)</lineannotation> +-- for UEFI systems only +> n # <lineannotation>(create a new partition for /boot)</lineannotation> +> 3 # <lineannotation>(make it a partition number 3)</lineannotation> +> # <lineannotation>(press enter to accept the default)</lineannotation> +> +512M # <lineannotation>(the size of the UEFI boot partition)</lineannotation> +> t # <lineannotation>(change the partition type ...)</lineannotation> +> 3 # <lineannotation>(... of the boot partition ...)</lineannotation> +> 1 # <lineannotation>(... to 'UEFI System')</lineannotation> +-- for BIOS or UEFI systems +> n # <lineannotation>(create a new partition for /swap)</lineannotation> +> 2 # <lineannotation>(make it a partition number 2)</lineannotation> +> # <lineannotation>(press enter to accept the default)</lineannotation> +> +8G # <lineannotation>(the size of the swap partition)</lineannotation> +> n # <lineannotation>(create a new partition for /)</lineannotation> +> 1 # <lineannotation>(make it a partition number 1)</lineannotation> +> # <lineannotation>(press enter to accept the default)</lineannotation> +> # <lineannotation>(press enter to accept the default and use the rest of the remaining space)</lineannotation> +> a # <lineannotation>(make the partition bootable)</lineannotation> +> x # <lineannotation>(enter expert mode)</lineannotation> +> f # <lineannotation>(fix up the partition ordering)</lineannotation> +> r # <lineannotation>(exit expert mode)</lineannotation> +> w # <lineannotation>(write the partition table to disk and exit)</lineannotation> # mkfs.ext4 -L nixos /dev/sda1 # mkswap -L swap /dev/sda2 # swapon /dev/sda2 +# mkfs.fat -F 32 -L boot /dev/sda3 # <lineannotation>(for UEFI systems only)</lineannotation> # mount /dev/disk/by-label/nixos /mnt +# mount /dev/disk/by-label/boot /mnt/boot # <lineannotation>(for UEFI systems only)</lineannotation> # nixos-generate-config --root /mnt # nano /mnt/etc/nixos/configuration.nix # nixos-install @@ -267,7 +373,8 @@ drive (here <filename>/dev/sda</filename>). <xref linkend="ex-config" ./hardware-configuration.nix ]; - boot.loader.grub.device = "/dev/sda"; + boot.loader.grub.device = "/dev/sda"; # <lineannotation>(for BIOS systems only)</lineannotation> + boot.loader.systemd-boot.enable = true; # <lineannotation>(for UEFI systems only)</lineannotation> # Note: setting fileSystems is generally not # necessary, since nixos-generate-config figures them out @@ -279,7 +386,6 @@ drive (here <filename>/dev/sda</filename>). <xref linkend="ex-config" }</screen> </example> -<xi:include href="installing-uefi.xml" /> <xi:include href="installing-usb.xml" /> <xi:include href="installing-pxe.xml" /> <xi:include href="installing-virtualbox-guest.xml" /> diff --git a/nixos/doc/manual/installation/obtaining.xml b/nixos/doc/manual/installation/obtaining.xml index 20a4838be880..9b2b474c60ce 100644 --- a/nixos/doc/manual/installation/obtaining.xml +++ b/nixos/doc/manual/installation/obtaining.xml @@ -12,11 +12,10 @@ download page</link>. There are a number of installation options. If you happen to have an optical drive and a spare CD, burning the image to CD and booting from that is probably the easiest option. Most people will need to prepare a USB stick to boot from. -Unetbootin is recommended and the process is described in brief below. -Note that systems which use UEFI require some additional manual steps. -If you run into difficulty a number of alternative methods are presented -in the <link -xlink:href="https://nixos.org/wiki/Installing_NixOS_from_a_USB_stick">NixOS +<xref linkend="sec-booting-from-usb"/> describes the preferred method +to prepare a USB stick. +A number of alternative methods are presented in the <link +xlink:href="https://nixos.wiki/wiki/NixOS_Installation_Guide#Making_the_installation_media">NixOS Wiki</link>.</para> <para>As an alternative to installing NixOS yourself, you can get a diff --git a/nixos/doc/manual/release-notes/rl-1404.xml b/nixos/doc/manual/release-notes/rl-1404.xml index 36f67ed88b0b..137caf14cba2 100644 --- a/nixos/doc/manual/release-notes/rl-1404.xml +++ b/nixos/doc/manual/release-notes/rl-1404.xml @@ -13,7 +13,7 @@ the following highlights: <itemizedlist> <listitem><para>Installation on UEFI systems is now supported. See - <xref linkend="sec-uefi-installation"/> for + <xref linkend="sec-installation"/> for details.</para></listitem> <listitem><para>Systemd has been updated to version 212, which has diff --git a/nixos/doc/manual/release-notes/rl-1803.xml b/nixos/doc/manual/release-notes/rl-1803.xml index b0e29182127e..12ff2e39a1bf 100644 --- a/nixos/doc/manual/release-notes/rl-1803.xml +++ b/nixos/doc/manual/release-notes/rl-1803.xml @@ -20,6 +20,22 @@ has the following highlights: </para> <itemizedlist> <listitem> <para> + MariaDB 10.2, updated from 10.1, is now the default MySQL implementation. While upgrading a few changes + have been made to the infrastructure involved: + <itemizedlist> + <listitem> + <para> + <literal>libmysql</literal> has been deprecated, please use <literal>mysql.connector-c</literal> + instead, a compatibility passthru has been added to the MySQL packages. + </para> + </listitem> + <listitem> + <para> + The <literal>mysql57</literal> package has a new <literal>static</literal> output containing + the static libraries including <literal>libmysqld.a</literal> + </para> + </listitem> + </itemizedlist> </para> </listitem> </itemizedlist> @@ -95,6 +111,34 @@ following incompatible changes:</para> <link xlink:href="https://search.nix.gsc.io/?q=stateVersion">here</link>. </para> </listitem> + <listitem> + <para> + <literal>cc-wrapper</literal>has been split in two; there is now also a <literal>bintools-wrapper</literal>. + The most commonly used files in <filename>nix-support</filename> are now split between the two wrappers. + Some commonly used ones, like <filename>nix-support/dynamic-linker</filename>, are duplicated for backwards compatability, even though they rightly belong only in <literal>bintools-wrapper</literal>. + Other more obscure ones are just moved. + </para> + </listitem> + <listitem> + <para> + The propagation logic has been changed. + The new logic, along with new types of dependencies that go with, is thoroughly documented in the "Specifying dependencies" section of the "Standard Environment" chapter of the nixpkgs manual. + <!-- That's <xref linkend="ssec-stdenv-attributes"> were we to merge the manuals. --> + The old logic isn't but is easy to describe: dependencies were propagated as the same type of dependency no matter what. + In practice, that means that many <function>propagatedNativeBuildInputs</function> should instead be <function>propagatedBuildInputs</function>. + Thankfully, that was and is the least used type of dependency. + Also, it means that some <function>propagatedBuildInputs</function> should instead be <function>depsTargetTargetPropagated</function>. + Other types dependencies should be unaffected. + </para> + </listitem> + <listitem> + <para> + The <literal>memcached</literal> service no longer accept dynamic socket + paths via <option>services.memcached.socket</option>. Unix sockets can be + still enabled by <option>services.memcached.enableUnixSocket</option> and + will be accessible at <literal>/run/memcached/memcached.sock</literal>. + </para> + </listitem> </itemizedlist> </section> @@ -131,6 +175,72 @@ following incompatible changes:</para> must be set to true. </para> </listitem> + <listitem> + <para> + The option <option>services.logstash.listenAddress</option> is now <literal>127.0.0.1</literal> by default. + Previously the default behaviour was to listen on all interfaces. + </para> + </listitem> + <listitem> + <para> + <literal>services.btrfs.autoScrub</literal> has been added, to + periodically check btrfs filesystems for data corruption. + If there's a correct copy available, it will automatically repair + corrupted blocks. + </para> + </listitem> + <listitem> + <para> + <literal>displayManager.lightdm.greeters.gtk.clock-format.</literal> + has been added, the clock format string (as expected by + strftime, e.g. <literal>%H:%M</literal>) to use with the lightdm + gtk greeter panel. + </para> + <para> + If set to null the default clock format is used. + </para> + </listitem> + <listitem> + <para> + <literal>displayManager.lightdm.greeters.gtk.indicators</literal> + has been added, a list of allowed indicator modules to use with + the lightdm gtk greeter panel. + </para> + <para> + Built-in indicators include <literal>~a11y</literal>, + <literal>~language</literal>, <literal>~session</literal>, + <literal>~power</literal>, <literal>~clock</literal>, + <literal>~host</literal>, <literal>~spacer</literal>. Unity + indicators can be represented by short name + (e.g. <literal>sound</literal>, <literal>power</literal>), + service file name, or absolute path. + </para> + <para> + If set to <literal>null</literal> the default indicators are + used. + </para> + <para> + In order to have the previous default configuration add +<programlisting> + services.xserver.displayManager.lightdm.greeters.gtk.indicators = [ + "~host" "~spacer" + "~clock" "~spacer" + "~session" + "~language" + "~a11y" + "~power" + ]; +</programlisting> + to your <literal>configuration.nix</literal>. + </para> + </listitem> + <listitem> + <para> + The NixOS test driver supports user services declared by <literal>systemd.user.services</literal>. + The methods <literal>waitForUnit</literal>, <literal>getUnitInfo</literal>, <literal>startJob</literal> + and <literal>stopJob</literal> provide an optional <literal>$user</literal> argument for that purpose. + </para> + </listitem> </itemizedlist> </section> diff --git a/nixos/lib/make-disk-image.nix b/nixos/lib/make-disk-image.nix index bf25e0cab259..636d0223fb77 100644 --- a/nixos/lib/make-disk-image.nix +++ b/nixos/lib/make-disk-image.nix @@ -129,6 +129,9 @@ let format' = format; in let # TODO: Nix really likes to chown things it creates to its current user... fakeroot nixos-prepare-root $root ${channelSources} ${config.system.build.toplevel} closure + # fakeroot seems to always give the owner write permissions, which we do not want + find $root/nix/store -mindepth 1 -maxdepth 1 -type f -o -type d | xargs chmod -R a-w + echo "copying staging root to image..." cptofs ${optionalString partitioned "-P 1"} -t ${fsType} -i $diskImage $root/* / ''; @@ -150,8 +153,6 @@ in pkgs.vmTools.runInLinuxVM ( } '' ${if partitioned then '' - . /sys/class/block/vda1/uevent - mknod /dev/vda1 b $MAJOR $MINOR rootDisk=/dev/vda1 '' else '' rootDisk=/dev/vda diff --git a/nixos/lib/make-ext4-fs.nix b/nixos/lib/make-ext4-fs.nix index f06649e1991a..21c69ed560a3 100644 --- a/nixos/lib/make-ext4-fs.nix +++ b/nixos/lib/make-ext4-fs.nix @@ -10,7 +10,7 @@ pkgs.stdenv.mkDerivation { name = "ext4-fs.img"; - buildInputs = with pkgs; [e2fsprogs libfaketime perl]; + nativeBuildInputs = with pkgs; [e2fsprogs libfaketime perl]; # For obtaining the closure of `storePaths'. exportReferencesGraph = diff --git a/nixos/lib/make-squashfs.nix b/nixos/lib/make-squashfs.nix index 4100af27becb..9d47a3222cc2 100644 --- a/nixos/lib/make-squashfs.nix +++ b/nixos/lib/make-squashfs.nix @@ -8,7 +8,7 @@ stdenv.mkDerivation { name = "squashfs.img"; - buildInputs = [perl squashfsTools]; + nativeBuildInputs = [perl squashfsTools]; # For obtaining the closure of `storeContents'. exportReferencesGraph = @@ -19,6 +19,33 @@ stdenv.mkDerivation { # Add the closures of the top-level store objects. storePaths=$(perl ${pathsFromGraph} closure-*) + # If a Hydra slave happens to have store paths with bad permissions/mtime, + # abort now so that they don't end up in ISO images in the channel. + # https://github.com/NixOS/nixpkgs/issues/32242 + hasBadPaths="" + for path in $storePaths; do + if [ -h "$path" ]; then + continue + fi + + mtime=$(stat -c %Y "$path") + mode=$(stat -c %a "$path") + + if [ "$mtime" != 1 ]; then + echo "Store path '$path' has an invalid mtime." + hasBadPaths=1 + fi + if [ "$mode" != 444 ] && [ "$mode" != 555 ]; then + echo "Store path '$path' has invalid permissions ($mode)." + hasBadPaths=1 + fi + done + + if [ -n "$hasBadPaths" ]; then + echo "You have bad paths in your store, please fix them." + exit 1 + fi + # Also include a manifest of the closures in a format suitable # for nix-store --load-db. printRegistration=1 perl ${pathsFromGraph} closure-* > nix-path-registration diff --git a/nixos/lib/test-driver/Machine.pm b/nixos/lib/test-driver/Machine.pm index a01c3c336a1b..78598b3efb4b 100644 --- a/nixos/lib/test-driver/Machine.pm +++ b/nixos/lib/test-driver/Machine.pm @@ -362,8 +362,8 @@ sub mustFail { sub getUnitInfo { - my ($self, $unit) = @_; - my ($status, $lines) = $self->execute("systemctl --no-pager show '$unit'"); + my ($self, $unit, $user) = @_; + my ($status, $lines) = $self->systemctl("--no-pager show \"$unit\"", $user); return undef if $status != 0; my $info = {}; foreach my $line (split '\n', $lines) { @@ -373,6 +373,16 @@ sub getUnitInfo { return $info; } +sub systemctl { + my ($self, $q, $user) = @_; + if ($user) { + $q =~ s/'/\\'/g; + return $self->execute("su -l $user -c \$'XDG_RUNTIME_DIR=/run/user/`id -u` systemctl --user $q'"); + } + + return $self->execute("systemctl $q"); +} + # Fail if the given systemd unit is not in the "active" state. sub requireActiveUnit { my ($self, $unit) = @_; @@ -387,16 +397,16 @@ sub requireActiveUnit { # Wait for a systemd unit to reach the "active" state. sub waitForUnit { - my ($self, $unit) = @_; + my ($self, $unit, $user) = @_; $self->nest("waiting for unit ‘$unit’", sub { retry sub { - my $info = $self->getUnitInfo($unit); + my $info = $self->getUnitInfo($unit, $user); my $state = $info->{ActiveState}; die "unit ‘$unit’ reached state ‘$state’\n" if $state eq "failed"; if ($state eq "inactive") { # If there are no pending jobs, then assume this unit # will never reach active state. - my ($status, $jobs) = $self->execute("systemctl list-jobs --full 2>&1"); + my ($status, $jobs) = $self->systemctl("list-jobs --full 2>&1", $user); if ($jobs =~ /No jobs/) { # FIXME: fragile # Handle the case where the unit may have started # between the previous getUnitInfo() and @@ -430,14 +440,14 @@ sub waitForFile { } sub startJob { - my ($self, $jobName) = @_; - $self->execute("systemctl start $jobName"); + my ($self, $jobName, $user) = @_; + $self->systemctl("start $jobName", $user); # FIXME: check result } sub stopJob { - my ($self, $jobName) = @_; - $self->execute("systemctl stop $jobName"); + my ($self, $jobName, $user) = @_; + $self->systemctl("stop $jobName", $user); } diff --git a/nixos/maintainers/scripts/ec2/create-amis.sh b/nixos/maintainers/scripts/ec2/create-amis.sh index dfc0f8d11465..347e6b9c6e0d 100755 --- a/nixos/maintainers/scripts/ec2/create-amis.sh +++ b/nixos/maintainers/scripts/ec2/create-amis.sh @@ -18,7 +18,7 @@ rm -f ec2-amis.nix types="hvm" stores="ebs" -regions="eu-west-1 eu-west-2 eu-central-1 us-east-1 us-east-2 us-west-1 us-west-2 ca-central-1 ap-southeast-1 ap-southeast-2 ap-northeast-1 ap-northeast-2 sa-east-1 ap-south-1" +regions="eu-west-1 eu-west-2 eu-west-3 eu-central-1 us-east-1 us-east-2 us-west-1 us-west-2 ca-central-1 ap-southeast-1 ap-southeast-2 ap-northeast-1 ap-northeast-2 sa-east-1 ap-south-1" for type in $types; do link=$stateDir/$type diff --git a/nixos/modules/config/networking.nix b/nixos/modules/config/networking.nix index 619f36cd5150..4101ef82f3e1 100644 --- a/nixos/modules/config/networking.nix +++ b/nixos/modules/config/networking.nix @@ -290,8 +290,8 @@ in ln -s /run/systemd/resolve/resolv.conf /run/resolvconf/interfaces/systemd ''} - # Make sure resolv.conf is up to date if not managed by systemd - ${optionalString (!config.services.resolved.enable) '' + # Make sure resolv.conf is up to date if not managed manually or by systemd + ${optionalString (!config.environment.etc?"resolv.conf") '' ${pkgs.openresolv}/bin/resolvconf -u ''} ''; diff --git a/nixos/modules/config/no-x-libs.nix b/nixos/modules/config/no-x-libs.nix index ae3e17ac27b6..e1c4d0d602af 100644 --- a/nixos/modules/config/no-x-libs.nix +++ b/nixos/modules/config/no-x-libs.nix @@ -35,7 +35,7 @@ with lib; networkmanager_pptp = pkgs.networkmanager_pptp.override { withGnome = false; }; networkmanager_vpnc = pkgs.networkmanager_vpnc.override { withGnome = false; }; networkmanager_iodine = pkgs.networkmanager_iodine.override { withGnome = false; }; - pinentry = pkgs.pinentry.override { gtk2 = null; qt4 = null; }; + pinentry = pkgs.pinentry_ncurses; }; }; } diff --git a/nixos/modules/installer/netboot/netboot.nix b/nixos/modules/installer/netboot/netboot.nix index 0f6046339b37..52239b619126 100644 --- a/nixos/modules/installer/netboot/netboot.nix +++ b/nixos/modules/installer/netboot/netboot.nix @@ -18,17 +18,17 @@ with lib; }; - config = { - - boot.loader.grub.version = 2; - + config = rec { # Don't build the GRUB menu builder script, since we don't need it # here and it causes a cyclic dependency. boot.loader.grub.enable = false; # !!! Hack - attributes expected by other modules. - system.boot.loader.kernelFile = "bzImage"; - environment.systemPackages = [ pkgs.grub2 pkgs.grub2_efi pkgs.syslinux ]; + environment.systemPackages = [ pkgs.grub2_efi ] + ++ (if pkgs.stdenv.system == "aarch64-linux" + then [] + else [ pkgs.grub2 pkgs.syslinux ]); + system.boot.loader.kernelFile = pkgs.stdenv.platform.kernelTarget; fileSystems."/" = { fsType = "tmpfs"; @@ -84,7 +84,12 @@ with lib; ]; }; - system.build.netbootIpxeScript = pkgs.writeTextDir "netboot.ipxe" "#!ipxe\nkernel bzImage init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}\ninitrd initrd\nboot"; + system.build.netbootIpxeScript = pkgs.writeTextDir "netboot.ipxe" '' + #!ipxe + kernel ${pkgs.stdenv.platform.kernelTarget} init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} + initrd initrd + boot + ''; boot.loader.timeout = 10; diff --git a/nixos/modules/installer/tools/nix-fallback-paths.nix b/nixos/modules/installer/tools/nix-fallback-paths.nix index 321fb9a2030a..131c779b1ab1 100644 --- a/nixos/modules/installer/tools/nix-fallback-paths.nix +++ b/nixos/modules/installer/tools/nix-fallback-paths.nix @@ -1,5 +1,6 @@ { - x86_64-linux = "/nix/store/b4s1gxiis1ryvybnjhdjvgc5sr1nq0ys-nix-1.11.15"; - i686-linux = "/nix/store/kgb5hs7qw13bvb6icramv1ry9dard3h9-nix-1.11.15"; - x86_64-darwin = "/nix/store/dgwz3dxdzs2wwd7pg7cdhvl8rv0qpnbj-nix-1.11.15"; + x86_64-linux = "/nix/store/gy4yv67gv3j6in0lalw37j353zdmfcwm-nix-1.11.16"; + i686-linux = "/nix/store/ifmyq5ryfxhhrzh62hiq65xyz1fwffga-nix-1.11.16"; + aarch64-linux = "/nix/store/y9mfv3sx75mbfibf1zna1kq9v98fk2nb-nix-1.11.16"; + x86_64-darwin = "/nix/store/hwpp7kia2f0in5ns2hiw41q38k30jpj2-nix-1.11.16"; } diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index c10b5a0ec932..c6440dd906fd 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -65,7 +65,7 @@ foldingathome = 37; sabnzbd = 38; #kdm = 39; # dropped in 17.03 - ghostone = 40; + #ghostone = 40; # dropped in 18.03 git = 41; fourstore = 42; fourstorehttp = 43; @@ -197,10 +197,10 @@ #input = 174; # unused sddm = 175; tss = 176; - memcached = 177; + #memcached = 177; removed 2018-01-03 ntp = 179; zabbix = 180; - redis = 181; + #redis = 181; removed 2018-01-03 unifi = 183; uptimed = 184; zope2 = 185; @@ -281,8 +281,8 @@ stanchion = 262; riak-cs = 263; infinoted = 264; - keystone = 265; - glance = 266; + # keystone = 265; # unused, removed 2017-12-13 + # glance = 266; # unused, removed 2017-12-13 couchpotato = 267; gogs = 268; pdns-recursor = 269; @@ -348,7 +348,7 @@ #foldingathome = 37; # unused #sabnzd = 38; # unused #kdm = 39; # unused, even before 17.03 - ghostone = 40; + #ghostone = 40; # dropped in 18.03 git = 41; fourstore = 42; fourstorehttp = 43; @@ -475,10 +475,10 @@ input = 174; sddm = 175; tss = 176; - #memcached = 177; # unused + #memcached = 177; # unused, removed 2018-01-03 #ntp = 179; # unused #zabbix = 180; # unused - #redis = 181; # unused + #redis = 181; # unused, removed 2018-01-03 #unifi = 183; # unused #uptimed = 184; # unused #zope2 = 185; # unused @@ -551,8 +551,8 @@ stanchion = 262; riak-cs = 263; infinoted = 264; - keystone = 265; - glance = 266; + # keystone = 265; # unused, removed 2017-12-13 + # glance = 266; # unused, removed 2017-12-13 couchpotato = 267; gogs = 268; kresd = 270; diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 5e2161aacb66..8d329b5b4b25 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -71,6 +71,7 @@ ./programs/bcc.nix ./programs/blcr.nix ./programs/browserpass.nix + ./programs/ccache.nix ./programs/cdemu.nix ./programs/chromium.nix ./programs/command-not-found/command-not-found.nix @@ -91,6 +92,7 @@ ./programs/npm.nix ./programs/oblogout.nix ./programs/qt5ct.nix + ./programs/rootston.nix ./programs/screen.nix ./programs/slock.nix ./programs/shadow.nix @@ -104,6 +106,7 @@ ./programs/tmux.nix ./programs/venus.nix ./programs/vim.nix + ./programs/way-cooler.nix ./programs/wireshark.nix ./programs/xfs_quota.nix ./programs/xonsh.nix @@ -217,7 +220,6 @@ ./services/editors/emacs.nix ./services/editors/infinoted.nix ./services/games/factorio.nix - ./services/games/ghost-one.nix ./services/games/minecraft-server.nix ./services/games/minetest-server.nix ./services/games/terraria.nix @@ -239,9 +241,11 @@ ./services/hardware/tlp.nix ./services/hardware/thinkfan.nix ./services/hardware/trezord.nix + ./services/hardware/u2f.nix ./services/hardware/udev.nix ./services/hardware/udisks2.nix ./services/hardware/upower.nix + ./services/hardware/usbmuxd.nix ./services/hardware/thermald.nix ./services/logging/SystemdJournal2Gelf.nix ./services/logging/awstats.nix @@ -257,6 +261,8 @@ ./services/logging/rsyslogd.nix ./services/logging/syslog-ng.nix ./services/logging/syslogd.nix + ./services/mail/clamsmtp.nix + ./services/mail/dkimproxy-out.nix ./services/mail/dovecot.nix ./services/mail/dspam.nix ./services/mail/exim.nix @@ -328,6 +334,7 @@ ./services/misc/nix-ssh-serve.nix ./services/misc/nzbget.nix ./services/misc/octoprint.nix + ./services/misc/osrm.nix ./services/misc/packagekit.nix ./services/misc/parsoid.nix ./services/misc/phd.nix @@ -352,6 +359,7 @@ ./services/misc/taskserver ./services/misc/tzupdate.nix ./services/misc/uhub.nix + ./services/misc/xmr-stak.nix ./services/misc/zookeeper.nix ./services/monitoring/apcupsd.nix ./services/monitoring/arbtt.nix @@ -398,7 +406,9 @@ ./services/monitoring/vnstat.nix ./services/monitoring/zabbix-agent.nix ./services/monitoring/zabbix-server.nix + ./services/network-filesystems/beegfs.nix ./services/network-filesystems/cachefilesd.nix + ./services/network-filesystems/davfs2.nix ./services/network-filesystems/drbd.nix ./services/network-filesystems/glusterfs.nix ./services/network-filesystems/kbfs.nix @@ -588,6 +598,7 @@ ./services/system/cloud-init.nix ./services/system/dbus.nix ./services/system/earlyoom.nix + ./services/system/localtime.nix ./services/system/kerberos.nix ./services/system/nscd.nix ./services/system/saslauthd.nix @@ -671,6 +682,7 @@ ./system/activation/top-level.nix ./system/boot/coredump.nix ./system/boot/emergency-mode.nix + ./system/boot/grow-partition.nix ./system/boot/initrd-network.nix ./system/boot/initrd-ssh.nix ./system/boot/kernel.nix @@ -737,6 +749,7 @@ ./virtualisation/lxcfs.nix ./virtualisation/lxd.nix ./virtualisation/amazon-options.nix + ./virtualisation/hyperv-guest.nix ./virtualisation/openvswitch.nix ./virtualisation/parallels-guest.nix ./virtualisation/rkt.nix @@ -745,6 +758,4 @@ ./virtualisation/vmware-guest.nix ./virtualisation/xen-dom0.nix ./virtualisation/xe-guest-utilities.nix - ./virtualisation/openstack/keystone.nix - ./virtualisation/openstack/glance.nix ] diff --git a/nixos/modules/profiles/all-hardware.nix b/nixos/modules/profiles/all-hardware.nix index 3c7e516c497f..f56640f19782 100644 --- a/nixos/modules/profiles/all-hardware.nix +++ b/nixos/modules/profiles/all-hardware.nix @@ -19,13 +19,12 @@ "sata_sil" "sata_sil24" "sata_sis" "sata_svw" "sata_sx4" "sata_uli" "sata_via" "sata_vsc" - "pata_ali" "pata_amd" "pata_artop" "pata_atiixp" - "pata_cs5520" "pata_cs5530" "pata_cs5535" "pata_efar" + "pata_ali" "pata_amd" "pata_artop" "pata_atiixp" "pata_efar" "pata_hpt366" "pata_hpt37x" "pata_hpt3x2n" "pata_hpt3x3" "pata_it8213" "pata_it821x" "pata_jmicron" "pata_marvell" "pata_mpiix" "pata_netcell" "pata_ns87410" "pata_oldpiix" "pata_pcmcia" "pata_pdc2027x" "pata_qdi" "pata_rz1000" - "pata_sc1200" "pata_serverworks" "pata_sil680" "pata_sis" + "pata_serverworks" "pata_sil680" "pata_sis" "pata_sl82c105" "pata_triflex" "pata_via" "pata_winbond" diff --git a/nixos/modules/programs/bash/bash.nix b/nixos/modules/programs/bash/bash.nix index ef1acdfe66e6..1abdb4973a44 100644 --- a/nixos/modules/programs/bash/bash.nix +++ b/nixos/modules/programs/bash/bash.nix @@ -14,13 +14,16 @@ let bashCompletion = optionalString cfg.enableCompletion '' # Check whether we're running a version of Bash that has support for # programmable completion. If we do, enable all modules installed in - # the system (and user profile). + # the system and user profile in obsolete /etc/bash_completion.d/ + # directories. Bash loads completions in all + # $XDG_DATA_DIRS/share/bash-completion/completions/ + # on demand, so they do not need to be sourced here. if shopt -q progcomp &>/dev/null; then . "${pkgs.bash-completion}/etc/profile.d/bash_completion.sh" nullglobStatus=$(shopt -p nullglob) shopt -s nullglob for p in $NIX_PROFILES; do - for m in "$p/etc/bash_completion.d/"* "$p/share/bash-completion/completions/"*; do + for m in "$p/etc/bash_completion.d/"*; do . $m done done diff --git a/nixos/modules/programs/ccache.nix b/nixos/modules/programs/ccache.nix new file mode 100644 index 000000000000..874774c72b47 --- /dev/null +++ b/nixos/modules/programs/ccache.nix @@ -0,0 +1,83 @@ +{ config, pkgs, lib, ... }: + +with lib; +let + cfg = config.programs.ccache; +in { + options.programs.ccache = { + # host configuration + enable = mkEnableOption "CCache"; + cacheDir = mkOption { + type = types.path; + description = "CCache directory"; + default = "/var/cache/ccache"; + }; + # target configuration + packageNames = mkOption { + type = types.listOf types.str; + description = "Nix top-level packages to be compiled using CCache"; + default = []; + example = [ "wxGTK30" "qt48" "ffmpeg_3_3" "libav_all" ]; + }; + }; + + config = mkMerge [ + # host configuration + (mkIf cfg.enable { + systemd.tmpfiles.rules = [ "d ${cfg.cacheDir} 0770 root nixbld -" ]; + + # "nix-ccache --show-stats" and "nix-ccache --clear" + security.wrappers.nix-ccache = { + group = "nixbld"; + setgid = true; + source = pkgs.writeScript "nix-ccache.pl" '' + #!${pkgs.perl}/bin/perl + + %ENV=( CCACHE_DIR => '${cfg.cacheDir}' ); + sub untaint { + my $v = shift; + return '-C' if $v eq '-C' || $v eq '--clear'; + return '-V' if $v eq '-V' || $v eq '--version'; + return '-s' if $v eq '-s' || $v eq '--show-stats'; + return '-z' if $v eq '-z' || $v eq '--zero-stats'; + exec('${pkgs.ccache}/bin/ccache', '-h'); + } + exec('${pkgs.ccache}/bin/ccache', map { untaint $_ } @ARGV); + ''; + }; + }) + + # target configuration + (mkIf (cfg.packageNames != []) { + nixpkgs.overlays = [ + (self: super: genAttrs cfg.packageNames (pn: super.${pn}.override { stdenv = builtins.trace "with ccache: ${pn}" self.ccacheStdenv; })) + + (self: super: { + ccacheWrapper = super.ccacheWrapper.override { + extraConfig = '' + export CCACHE_COMPRESS=1 + export CCACHE_DIR="${cfg.cacheDir}" + export CCACHE_UMASK=007 + if [ ! -d "$CCACHE_DIR" ]; then + echo "=====" + echo "Directory '$CCACHE_DIR' does not exist" + echo "Please create it with:" + echo " sudo mkdir -m0770 '$CCACHE_DIR'" + echo " sudo chown root:nixbld '$CCACHE_DIR'" + echo "=====" + exit 1 + fi + if [ ! -w "$CCACHE_DIR" ]; then + echo "=====" + echo "Directory '$CCACHE_DIR' is not accessible for user $(whoami)" + echo "Please verify its access permissions" + echo "=====" + exit 1 + fi + ''; + }; + }) + ]; + }) + ]; +} \ No newline at end of file diff --git a/nixos/modules/programs/dconf.nix b/nixos/modules/programs/dconf.nix index 1b7e20799819..27bfdf022e7d 100644 --- a/nixos/modules/programs/dconf.nix +++ b/nixos/modules/programs/dconf.nix @@ -1,7 +1,8 @@ -{ config, lib, ... }: +{ config, lib, pkgs, ... }: + +with lib; let - inherit (lib) mkOption mkIf types mapAttrsToList; cfg = config.programs.dconf; mkDconfProfile = name: path: @@ -13,6 +14,7 @@ in options = { programs.dconf = { + enable = mkEnableOption "dconf"; profiles = mkOption { type = types.attrsOf types.path; @@ -26,9 +28,15 @@ in ###### implementation - config = mkIf (cfg.profiles != {}) { - environment.etc = + config = mkIf (cfg.profiles != {} || cfg.enable) { + environment.etc = optionals (cfg.profiles != {}) (mapAttrsToList mkDconfProfile cfg.profiles); + + environment.variables.GIO_EXTRA_MODULES = optional cfg.enable + "${pkgs.gnome3.dconf.lib}/lib/gio/modules"; + # https://github.com/NixOS/nixpkgs/pull/31891 + #environment.variables.XDG_DATA_DIRS = optional cfg.enable + # "$(echo ${pkgs.gnome3.gsettings_desktop_schemas}/share/gsettings-schemas/gsettings-desktop-schemas-*)"; }; } diff --git a/nixos/modules/programs/rootston.nix b/nixos/modules/programs/rootston.nix new file mode 100644 index 000000000000..1946b1db657b --- /dev/null +++ b/nixos/modules/programs/rootston.nix @@ -0,0 +1,103 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.programs.rootston; + + rootstonWrapped = pkgs.writeScriptBin "rootston" '' + #! ${pkgs.stdenv.shell} + if [[ "$#" -ge 1 ]]; then + exec ${pkgs.rootston}/bin/rootston "$@" + else + ${cfg.extraSessionCommands} + exec ${pkgs.rootston}/bin/rootston -C ${cfg.configFile} + fi + ''; +in { + options.programs.rootston = { + enable = mkEnableOption '' + rootston, the reference compositor for wlroots. The purpose of rootston + is to test and demonstrate the features of wlroots (if you want a real + Wayland compositor you should e.g. use Sway instead). You can manually + start the compositor by running "rootston" from a terminal''; + + extraSessionCommands = mkOption { + type = types.lines; + default = ""; + example = '' + # Define a keymap (US QWERTY is the default) + export XKB_DEFAULT_LAYOUT=de,us + export XKB_DEFAULT_VARIANT=nodeadkeys + export XKB_DEFAULT_OPTIONS=grp:alt_shift_toggle,caps:escape + ''; + description = '' + Shell commands executed just before rootston is started. + ''; + }; + + extraPackages = mkOption { + type = with types; listOf package; + default = with pkgs; [ + westonLite xwayland rofi + ]; + defaultText = literalExample '' + with pkgs; [ + westonLite xwayland rofi + ] + ''; + example = literalExample "[ ]"; + description = '' + Extra packages to be installed system wide. + ''; + }; + + config = mkOption { + type = types.str; + default = '' + [keyboard] + meta-key = Logo + + # Sway/i3 like Keybindings + # Maps key combinations with commands to execute + # Commands include: + # - "exit" to stop the compositor + # - "exec" to execute a shell command + # - "close" to close the current view + # - "next_window" to cycle through windows + [bindings] + Logo+Shift+e = exit + Logo+q = close + Logo+m = maximize + Alt+Tab = next_window + Logo+Return = exec weston-terminal + Logo+d = exec rofi -show run + ''; + description = '' + Default configuration for rootston (used when called without any + parameters). + ''; + }; + + configFile = mkOption { + type = types.path; + default = "/etc/rootston.ini"; + example = literalExample "${pkgs.rootston}/etc/rootston.ini"; + description = '' + Path to the default rootston configuration file (the "config" option + will have no effect if you change the path). + ''; + }; + }; + + config = mkIf cfg.enable { + environment.etc."rootston.ini".text = cfg.config; + environment.systemPackages = [ rootstonWrapped ] ++ cfg.extraPackages; + + hardware.opengl.enable = mkDefault true; + fonts.enableDefaultFonts = mkDefault true; + programs.dconf.enable = mkDefault true; + }; + + meta.maintainers = with lib.maintainers; [ primeos gnidorah ]; +} diff --git a/nixos/modules/programs/sway.nix b/nixos/modules/programs/sway.nix index 5d13b90daace..d9503d6004ff 100644 --- a/nixos/modules/programs/sway.nix +++ b/nixos/modules/programs/sway.nix @@ -4,36 +4,42 @@ with lib; let cfg = config.programs.sway; - sway = pkgs.sway; + swayPackage = pkgs.sway; - swayWrapped = pkgs.writeScriptBin "sway" '' - #! ${pkgs.stdenv.shell} - if [ "$1" != "" ]; then - sway-setcap "$@" - exit + swayWrapped = pkgs.writeShellScriptBin "sway" '' + if [[ "$#" -ge 1 ]]; then + exec sway-setcap "$@" + else + ${cfg.extraSessionCommands} + exec ${pkgs.dbus.dbus-launch} --exit-with-session sway-setcap fi - ${cfg.extraSessionCommands} - exec ${pkgs.dbus.dbus-launch} --exit-with-session sway-setcap ''; swayJoined = pkgs.symlinkJoin { - name = "sway-wrapped"; - paths = [ swayWrapped sway ]; + name = "sway-joined"; + paths = [ swayWrapped swayPackage ]; }; -in -{ +in { options.programs.sway = { - enable = mkEnableOption "sway"; + enable = mkEnableOption '' + the tiling Wayland compositor Sway. After adding yourself to the "sway" + group you can manually launch Sway by executing "sway" from a terminal. + If you call "sway" with any parameters the extraSessionCommands won't be + executed and Sway won't be launched with dbus-launch''; extraSessionCommands = mkOption { - default = ""; - type = types.lines; + type = types.lines; + default = ""; example = '' - export XKB_DEFAULT_LAYOUT=us,de - export XKB_DEFAULT_VARIANT=,nodeadkeys - export XKB_DEFAULT_OPTIONS=grp:alt_shift_toggle, + # Define a keymap (US QWERTY is the default) + export XKB_DEFAULT_LAYOUT=de,us + export XKB_DEFAULT_VARIANT=nodeadkeys + export XKB_DEFAULT_OPTIONS=grp:alt_shift_toggle,caps:escape + # Change the Keyboard repeat delay and rate + export WLC_REPEAT_DELAY=660 + export WLC_REPEAT_RATE=25 ''; description = '' - Shell commands executed just before sway is started. + Shell commands executed just before Sway is started. ''; }; @@ -42,9 +48,12 @@ in default = with pkgs; [ i3status xwayland rxvt_unicode dmenu ]; + defaultText = literalExample '' + with pkgs; [ i3status xwayland rxvt_unicode dmenu ]; + ''; example = literalExample '' with pkgs; [ - i3status xwayland rxvt_unicode dmenu + i3lock light termite ] ''; description = '' @@ -57,7 +66,7 @@ in environment.systemPackages = [ swayJoined ] ++ cfg.extraPackages; security.wrappers.sway = { program = "sway-setcap"; - source = "${sway}/bin/sway"; + source = "${swayPackage}/bin/sway"; capabilities = "cap_sys_ptrace,cap_sys_tty_config=eip"; owner = "root"; group = "sway"; @@ -65,8 +74,12 @@ in }; users.extraGroups.sway = {}; + security.pam.services.swaylock = {}; hardware.opengl.enable = mkDefault true; fonts.enableDefaultFonts = mkDefault true; + programs.dconf.enable = mkDefault true; }; + + meta.maintainers = with lib.maintainers; [ gnidorah primeos ]; } diff --git a/nixos/modules/programs/tmux.nix b/nixos/modules/programs/tmux.nix index ed1d88a420a2..1eb6fa6bf2fa 100644 --- a/nixos/modules/programs/tmux.nix +++ b/nixos/modules/programs/tmux.nix @@ -151,6 +151,15 @@ in { type = types.str; description = "Set the $TERM variable."; }; + + secureSocket = mkOption { + default = true; + type = types.bool; + description = '' + Store tmux socket under /run, which is more secure than /tmp, but as a + downside it doesn't survive user logout. + ''; + }; }; }; @@ -163,7 +172,7 @@ in { systemPackages = [ pkgs.tmux ]; variables = { - TMUX_TMPDIR = ''''${XDG_RUNTIME_DIR:-"/run/user/\$(id -u)"}''; + TMUX_TMPDIR = lib.optional cfg.secureSocket ''''${XDG_RUNTIME_DIR:-"/run/user/\$(id -u)"}''; }; }; }; diff --git a/nixos/modules/programs/way-cooler.nix b/nixos/modules/programs/way-cooler.nix new file mode 100644 index 000000000000..633e959be9f3 --- /dev/null +++ b/nixos/modules/programs/way-cooler.nix @@ -0,0 +1,78 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.programs.way-cooler; + way-cooler = pkgs.way-cooler; + + wcWrapped = pkgs.writeShellScriptBin "way-cooler" '' + ${cfg.extraSessionCommands} + exec ${pkgs.dbus.dbus-launch} --exit-with-session ${way-cooler}/bin/way-cooler + ''; + wcJoined = pkgs.symlinkJoin { + name = "way-cooler-wrapped"; + paths = [ wcWrapped way-cooler ]; + }; + configFile = readFile "${way-cooler}/etc/way-cooler/init.lua"; + spawnBar = '' + util.program.spawn_at_startup("lemonbar"); + ''; +in +{ + options.programs.way-cooler = { + enable = mkEnableOption "way-cooler"; + + extraSessionCommands = mkOption { + default = ""; + type = types.lines; + example = '' + export XKB_DEFAULT_LAYOUT=us,de + export XKB_DEFAULT_VARIANT=,nodeadkeys + export XKB_DEFAULT_OPTIONS=grp:caps_toggle, + ''; + description = '' + Shell commands executed just before way-cooler is started. + ''; + }; + + extraPackages = mkOption { + type = with types; listOf package; + default = with pkgs; [ + westonLite xwayland dmenu + ]; + example = literalExample '' + with pkgs; [ + westonLite xwayland dmenu + ] + ''; + description = '' + Extra packages to be installed system wide. + ''; + }; + + enableBar = mkOption { + type = types.bool; + default = true; + description = '' + Whether to enable an unofficial bar. + ''; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ wcJoined ] ++ cfg.extraPackages; + + security.pam.services.wc-lock = {}; + environment.etc."way-cooler/init.lua".text = '' + ${configFile} + ${optionalString cfg.enableBar spawnBar} + ''; + + hardware.opengl.enable = mkDefault true; + fonts.enableDefaultFonts = mkDefault true; + programs.dconf.enable = mkDefault true; + }; + + meta.maintainers = with maintainers; [ gnidorah ]; +} diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix index eb10d4f428be..562be13a3f64 100644 --- a/nixos/modules/rename.nix +++ b/nixos/modules/rename.nix @@ -82,6 +82,10 @@ with lib; (mkRenamedOptionModule [ "services" "virtualboxHost" "addNetworkInterface" ] [ "virtualisation" "virtualbox" "host" "addNetworkInterface" ]) (mkRenamedOptionModule [ "services" "virtualboxHost" "enableHardening" ] [ "virtualisation" "virtualbox" "host" "enableHardening" ]) + # libvirtd + (mkRemovedOptionModule [ "virtualisation" "libvirtd" "enableKVM" ] + "Set the option `virtualisation.libvirtd.qemuPackage' instead.") + # Tarsnap (mkRenamedOptionModule [ "services" "tarsnap" "config" ] [ "services" "tarsnap" "archives" ]) @@ -182,6 +186,9 @@ with lib; (mkRenamedOptionModule [ "config" "fonts" "fontconfig" "ultimate" "forceAutohint" ] [ "config" "fonts" "fontconfig" "forceAutohint" ]) (mkRenamedOptionModule [ "config" "fonts" "fontconfig" "ultimate" "renderMonoTTFAsBitmap" ] [ "config" "fonts" "fontconfig" "renderMonoTTFAsBitmap" ]) + # Profile splitting + (mkRenamedOptionModule [ "virtualization" "growPartition" ] [ "boot" "growPartition" ]) + # Options that are obsolete and have no replacement. (mkRemovedOptionModule [ "boot" "initrd" "luks" "enable" ] "") (mkRemovedOptionModule [ "programs" "bash" "enable" ] "") diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix index 2d6713311a45..3fff9e78aa19 100644 --- a/nixos/modules/security/pam.nix +++ b/nixos/modules/security/pam.nix @@ -223,6 +223,17 @@ let ''; }; + enableGnomeKeyring = mkOption { + default = false; + type = types.bool; + description = '' + If enabled, pam_gnome_keyring will attempt to automatically unlock the + user's default Gnome keyring upon login. If the user login password does + not match their keyring password, Gnome Keyring will prompt separately + after login. + ''; + }; + text = mkOption { type = types.nullOr types.lines; description = "Contents of the PAM service file."; @@ -273,7 +284,7 @@ let # prompts the user for password so we run it once with 'required' at an # earlier point and it will run again with 'sufficient' further down. # We use try_first_pass the second time to avoid prompting password twice - (optionalString (cfg.unixAuth && (config.security.pam.enableEcryptfs || cfg.pamMount || cfg.enableKwallet)) '' + (optionalString (cfg.unixAuth && (config.security.pam.enableEcryptfs || cfg.pamMount || cfg.enableKwallet || cfg.enableGnomeKeyring)) '' auth required pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} likeauth ${optionalString config.security.pam.enableEcryptfs "auth optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so unwrap"} @@ -282,6 +293,8 @@ let ${optionalString cfg.enableKwallet ("auth optional ${pkgs.plasma5.kwallet-pam}/lib/security/pam_kwallet5.so" + " kwalletd=${pkgs.libsForQt5.kwallet.bin}/bin/kwalletd5")} + ${optionalString cfg.enableGnomeKeyring + ("auth optional ${pkgs.gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so")} '') + '' ${optionalString cfg.unixAuth "auth sufficient pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} likeauth try_first_pass"} @@ -351,6 +364,10 @@ let ${optionalString (cfg.enableKwallet) ("session optional ${pkgs.plasma5.kwallet-pam}/lib/security/pam_kwallet5.so" + " kwalletd=${pkgs.libsForQt5.kwallet.bin}/bin/kwalletd5")} + ${optionalString (cfg.enableGnomeKeyring) + "session optional ${pkgs.gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so auto_start"} + ${optionalString (config.virtualisation.lxc.lxcfs.enable) + "session optional ${pkgs.lxcfs}/lib/security/pam_cgfs.so -c freezer,memory,name=systemd,unified,cpuset"} ''); }; @@ -519,7 +536,6 @@ in ftp = {}; i3lock = {}; i3lock-color = {}; - swaylock = {}; screen = {}; vlock = {}; xlock = {}; diff --git a/nixos/modules/security/wrappers/default.nix b/nixos/modules/security/wrappers/default.nix index 1f64213accd4..77e4b2a616d8 100644 --- a/nixos/modules/security/wrappers/default.nix +++ b/nixos/modules/security/wrappers/default.nix @@ -17,7 +17,7 @@ let hardeningEnable = [ "pie" ]; installPhase = '' mkdir -p $out/bin - gcc -Wall -O2 -DWRAPPER_DIR=\"${parentWrapperDir}\" \ + $CC -Wall -O2 -DWRAPPER_DIR=\"${parentWrapperDir}\" \ -lcap-ng -lcap ${./wrapper.c} -o $out/bin/security-wrapper ''; }; @@ -79,7 +79,7 @@ let ({ owner = "root"; group = "root"; } // s) - else if + else if (s ? "setuid" && s.setuid) || (s ? "setgid" && s.setgid) || (s ? "permissions") diff --git a/nixos/modules/services/audio/mopidy.nix b/nixos/modules/services/audio/mopidy.nix index c0a0f0374294..52613d450b51 100644 --- a/nixos/modules/services/audio/mopidy.nix +++ b/nixos/modules/services/audio/mopidy.nix @@ -4,17 +4,22 @@ with pkgs; with lib; let - uid = config.ids.uids.mopidy; gid = config.ids.gids.mopidy; cfg = config.services.mopidy; mopidyConf = writeText "mopidy.conf" cfg.configuration; - mopidyEnv = python.buildEnv.override { - extraLibs = [ mopidy ] ++ cfg.extensionPackages; + mopidyEnv = buildEnv { + name = "mopidy-with-extensions-${mopidy.version}"; + paths = closePropagation cfg.extensionPackages; + pathsToLink = [ "/${python.sitePackages}" ]; + buildInputs = [ makeWrapper ]; + postBuild = '' + makeWrapper ${mopidy}/bin/mopidy $out/bin/mopidy \ + --prefix PYTHONPATH : $out/${python.sitePackages} + ''; }; - in { options = { @@ -61,7 +66,6 @@ in { }; - ###### implementation config = mkIf cfg.enable { diff --git a/nixos/modules/services/backup/tarsnap.nix b/nixos/modules/services/backup/tarsnap.nix index 7c9dedb67ad2..59e9d122fb50 100644 --- a/nixos/modules/services/backup/tarsnap.nix +++ b/nixos/modules/services/backup/tarsnap.nix @@ -115,7 +115,7 @@ in description = '' Print global archive statistics upon completion. The output is available via - <command>systemctl status tarsnap@archive-name</command>. + <command>systemctl status tarsnap-archive-name</command>. ''; }; diff --git a/nixos/modules/services/backup/znapzend.nix b/nixos/modules/services/backup/znapzend.nix index baf99930e3eb..762bb4b38675 100644 --- a/nixos/modules/services/backup/znapzend.nix +++ b/nixos/modules/services/backup/znapzend.nix @@ -1,39 +1,372 @@ { config, lib, pkgs, ... }: with lib; +with types; let + + # Converts a plan like + # { "1d" = "1h"; "1w" = "1d"; } + # into + # "1d=>1h,1w=>1d" + attrToPlan = attrs: concatStringsSep "," (builtins.attrValues ( + mapAttrs (n: v: "${n}=>${v}") attrs)); + + planDescription = '' + The znapzend backup plan to use for the source. + </para> + <para> + The plan specifies how often to backup and for how long to keep the + backups. It consists of a series of retention periodes to interval + associations: + </para> + <para> + <literal> + retA=>intA,retB=>intB,... + </literal> + </para> + <para> + Both intervals and retention periods are expressed in standard units + of time or multiples of them. You can use both the full name or a + shortcut according to the following listing: + </para> + <para> + <literal> + second|sec|s, minute|min, hour|h, day|d, week|w, month|mon|m, year|y + </literal> + </para> + <para> + See <citerefentry><refentrytitle>znapzendzetup</refentrytitle><manvolnum>1</manvolnum></citerefentry> for more info. + ''; + planExample = "1h=>10min,1d=>1h,1w=>1d,1m=>1w,1y=>1m"; + + # A type for a string of the form number{b|k|M|G} + mbufferSizeType = str // { + check = x: str.check x && builtins.isList (builtins.match "^[0-9]+[bkMG]$" x); + description = "string of the form number{b|k|M|G}"; + }; + + # Type for a string that must contain certain other strings (the list parameter). + # Note that these would need regex escaping. + stringContainingStrings = list: let + matching = s: map (str: builtins.match ".*${str}.*" s) list; + in str // { + check = x: str.check x && all isList (matching x); + description = "string containing all of the characters ${concatStringsSep ", " list}"; + }; + + timestampType = stringContainingStrings [ "%Y" "%m" "%d" "%H" "%M" "%S" ]; + + destType = srcConfig: submodule ({ name, ... }: { + options = { + + label = mkOption { + type = str; + description = "Label for this destination. Defaults to the attribute name."; + }; + + plan = mkOption { + type = str; + description = planDescription; + example = planExample; + }; + + dataset = mkOption { + type = str; + description = "Dataset name to send snapshots to."; + example = "tank/main"; + }; + + host = mkOption { + type = nullOr str; + description = '' + Host to use for the destination dataset. Can be prefixed with + <literal>user@</literal> to specify the ssh user. + ''; + default = null; + example = "john@example.com"; + }; + + presend = mkOption { + type = nullOr str; + description = '' + Command to run before sending the snapshot to the destination. + Intended to run a remote script via <command>ssh</command> on the + destination, e.g. to bring up a backup disk or server or to put a + zpool online/offline. See also <option>postsend</option>. + ''; + default = null; + example = "ssh root@bserv zpool import -Nf tank"; + }; + + postsend = mkOption { + type = nullOr str; + description = '' + Command to run after sending the snapshot to the destination. + Intended to run a remote script via <command>ssh</command> on the + destination, e.g. to bring up a backup disk or server or to put a + zpool online/offline. See also <option>presend</option>. + ''; + default = null; + example = "ssh root@bserv zpool export tank"; + }; + }; + + config = { + label = mkDefault name; + plan = mkDefault srcConfig.plan; + }; + }); + + + + srcType = submodule ({ name, config, ... }: { + options = { + + enable = mkOption { + type = bool; + description = "Whether to enable this source."; + default = true; + }; + + recursive = mkOption { + type = bool; + description = "Whether to do recursive snapshots."; + default = false; + }; + + mbuffer = { + enable = mkOption { + type = bool; + description = "Whether to use <command>mbuffer</command>."; + default = false; + }; + + port = mkOption { + type = nullOr ints.u16; + description = '' + Port to use for <command>mbuffer</command>. + </para> + <para> + If this is null, it will run <command>mbuffer</command> through + ssh. + </para> + <para> + If this is not null, it will run <command>mbuffer</command> + directly through TCP, which is not encrypted but faster. In that + case the given port needs to be open on the destination host. + ''; + default = null; + }; + + size = mkOption { + type = mbufferSizeType; + description = '' + The size for <command>mbuffer</command>. + Supports the units b, k, M, G. + ''; + default = "1G"; + example = "128M"; + }; + }; + + presnap = mkOption { + type = nullOr str; + description = '' + Command to run before snapshots are taken on the source dataset, + e.g. for database locking/flushing. See also + <option>postsnap</option>. + ''; + default = null; + example = literalExample '' + ''${pkgs.mariadb}/bin/mysql -e "set autocommit=0;flush tables with read lock;\\! ''${pkgs.coreutils}/bin/sleep 600" & ''${pkgs.coreutils}/bin/echo $! > /tmp/mariadblock.pid ; sleep 10 + ''; + }; + + postsnap = mkOption { + type = nullOr str; + description = '' + Command to run after snapshots are taken on the source dataset, + e.g. for database unlocking. See also <option>presnap</option>. + ''; + default = null; + example = literalExample '' + ''${pkgs.coreutils}/bin/kill `''${pkgs.coreutils}/bin/cat /tmp/mariadblock.pid`;''${pkgs.coreutils}/bin/rm /tmp/mariadblock.pid + ''; + }; + + timestampFormat = mkOption { + type = timestampType; + description = '' + The timestamp format to use for constructing snapshot names. + The syntax is <literal>strftime</literal>-like. The string must + consist of the mandatory <literal>%Y %m %d %H %M %S</literal>. + Optionally <literal>- _ . :</literal> characters as well as any + alphanumeric character are allowed. If suffixed by a + <literal>Z</literal>, times will be in UTC. + ''; + default = "%Y-%m-%d-%H%M%S"; + example = "znapzend-%m.%d.%Y-%H%M%SZ"; + }; + + sendDelay = mkOption { + type = int; + description = '' + Specify delay (in seconds) before sending snaps to the destination. + May be useful if you want to control sending time. + ''; + default = 0; + example = 60; + }; + + plan = mkOption { + type = str; + description = planDescription; + example = planExample; + }; + + dataset = mkOption { + type = str; + description = "The dataset to use for this source."; + example = "tank/home"; + }; + + destinations = mkOption { + type = loaOf (destType config); + description = "Additional destinations."; + default = {}; + example = literalExample '' + { + local = { + dataset = "btank/backup"; + presend = "zpool import -N btank"; + postsend = "zpool export btank"; + }; + remote = { + host = "john@example.com"; + dataset = "tank/john"; + }; + }; + ''; + }; + }; + + config = { + dataset = mkDefault name; + }; + + }); + + ### Generating the configuration from here + cfg = config.services.znapzend; + + onOff = b: if b then "on" else "off"; + nullOff = b: if isNull b then "off" else toString b; + stripSlashes = replaceStrings [ "/" ] [ "." ]; + + attrsToFile = config: concatStringsSep "\n" (builtins.attrValues ( + mapAttrs (n: v: "${n}=${v}") config)); + + mkDestAttrs = dst: with dst; + mapAttrs' (n: v: nameValuePair "dst_${label}${n}" v) ({ + "" = optionalString (! isNull host) "${host}:" + dataset; + _plan = plan; + } // optionalAttrs (presend != null) { + _precmd = presend; + } // optionalAttrs (postsend != null) { + _pstcmd = postsend; + }); + + mkSrcAttrs = srcCfg: with srcCfg; { + enabled = onOff enable; + mbuffer = with mbuffer; if enable then "${pkgs.mbuffer}/bin/mbuffer" + + optionalString (port != null) ":${toString port}" else "off"; + mbuffer_size = mbuffer.size; + post_znap_cmd = nullOff postsnap; + pre_znap_cmd = nullOff presnap; + recursive = onOff recursive; + src = dataset; + src_plan = plan; + tsformat = timestampFormat; + zend_delay = toString sendDelay; + } // fold (a: b: a // b) {} ( + map mkDestAttrs (builtins.attrValues destinations) + ); + + files = mapAttrs' (n: srcCfg: let + fileText = attrsToFile (mkSrcAttrs srcCfg); + in { + name = srcCfg.dataset; + value = pkgs.writeText (stripSlashes srcCfg.dataset) fileText; + }) cfg.zetup; + in { options = { services.znapzend = { - enable = mkEnableOption "ZnapZend daemon"; + enable = mkEnableOption "ZnapZend ZFS backup daemon"; logLevel = mkOption { default = "debug"; example = "warning"; - type = lib.types.enum ["debug" "info" "warning" "err" "alert"]; - description = "The log level when logging to file. Any of debug, info, warning, err, alert. Default in daemonized form is debug."; + type = enum ["debug" "info" "warning" "err" "alert"]; + description = '' + The log level when logging to file. Any of debug, info, warning, err, + alert. Default in daemonized form is debug. + ''; }; logTo = mkOption { - type = types.str; + type = str; default = "syslog::daemon"; example = "/var/log/znapzend.log"; - description = "Where to log to (syslog::<facility> or <filepath>)."; + description = '' + Where to log to (syslog::<facility> or <filepath>). + ''; }; noDestroy = mkOption { - type = types.bool; + type = bool; default = false; description = "Does all changes to the filesystem except destroy."; }; autoCreation = mkOption { - type = types.bool; + type = bool; + default = false; + description = "Automatically create the destination dataset if it does not exists."; + }; + + zetup = mkOption { + type = loaOf srcType; + description = "Znapzend configuration."; + default = {}; + example = literalExample '' + { + "tank/home" = { + # Make snapshots of tank/home every hour, keep those for 1 day, + # keep every days snapshot for 1 month, etc. + plan = "1d=>1h,1m=>1d,1y=>1m"; + recursive = true; + # Send all those snapshots to john@example.com:rtank/john as well + destinations.remote = { + host = "john@example.com"; + dataset = "rtank/john"; + }; + }; + }; + ''; + }; + + pure = mkOption { + type = bool; + description = '' + Do not persist any stateful znapzend setups. If this option is + enabled, your previously set znapzend setups will be cleared and only + the ones defined with this module will be applied. + ''; default = false; - description = "Automatically create the dataset on dest if it does not exists."; }; }; }; @@ -49,12 +382,30 @@ in path = with pkgs; [ zfs mbuffer openssh ]; + preStart = optionalString cfg.pure '' + echo Resetting znapzend zetups + ${pkgs.znapzend}/bin/znapzendzetup list \ + | grep -oP '(?<=\*\*\* backup plan: ).*(?= \*\*\*)' \ + | xargs ${pkgs.znapzend}/bin/znapzendzetup delete + '' + concatStringsSep "\n" (mapAttrsToList (dataset: config: '' + echo Importing znapzend zetup ${config} for dataset ${dataset} + ${pkgs.znapzend}/bin/znapzendzetup import --write ${dataset} ${config} + '') files); + serviceConfig = { - ExecStart = "${pkgs.znapzend}/bin/znapzend --logto=${cfg.logTo} --loglevel=${cfg.logLevel} ${optionalString cfg.noDestroy "--nodestroy"} ${optionalString cfg.autoCreation "--autoCreation"}"; + ExecStart = let + args = concatStringsSep " " [ + "--logto=${cfg.logTo}" + "--loglevel=${cfg.logLevel}" + (optionalString cfg.noDestroy "--nodestroy") + (optionalString cfg.autoCreation "--autoCreation") + ]; in "${pkgs.znapzend}/bin/znapzend ${args}"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; Restart = "on-failure"; }; }; }; }; + + meta.maintainers = with maintainers; [ infinisil ]; } diff --git a/nixos/modules/services/continuous-integration/buildkite-agent.nix b/nixos/modules/services/continuous-integration/buildkite-agent.nix index dcc5e7174601..1b0198ac93fe 100644 --- a/nixos/modules/services/continuous-integration/buildkite-agent.nix +++ b/nixos/modules/services/continuous-integration/buildkite-agent.nix @@ -48,6 +48,15 @@ in ''; }; + hooksPath = mkOption { + type = types.path; + default = "${pkgs.buildkite-agent}/share/hooks"; + defaultText = "${pkgs.buildkite-agent}/share/hooks"; + description = '' + Path to the directory storing the hooks. + ''; + }; + meta-data = mkOption { type = types.str; default = ""; @@ -114,8 +123,8 @@ in token="$(cat ${toString cfg.tokenPath})" name="${cfg.name}" meta-data="${cfg.meta-data}" - hooks-path="${pkgs.buildkite-agent}/share/hooks" build-path="${cfg.dataDir}/builds" + hooks-path="${cfg.hooksPath}" bootstrap-script="${pkgs.buildkite-agent}/share/bootstrap.sh" EOF ''; diff --git a/nixos/modules/services/databases/memcached.nix b/nixos/modules/services/databases/memcached.nix index c6875af506d3..46bc6fc5c132 100644 --- a/nixos/modules/services/databases/memcached.nix +++ b/nixos/modules/services/databases/memcached.nix @@ -40,11 +40,7 @@ in description = "The port to bind to"; }; - socket = mkOption { - default = ""; - description = "Unix socket path to listen on. Setting this will disable network support"; - example = "/var/run/memcached"; - }; + enableUnixSocket = mkEnableOption "unix socket at /run/memcached/memcached.sock"; maxMemory = mkOption { default = 64; @@ -68,31 +64,40 @@ in config = mkIf config.services.memcached.enable { - users.extraUsers.memcached = - { name = cfg.user; - uid = config.ids.uids.memcached; - description = "Memcached server user"; - }; + users.extraUsers = optional (cfg.user == "memcached") { + name = "memcached"; + description = "Memcached server user"; + }; environment.systemPackages = [ memcached ]; - systemd.services.memcached = - { description = "Memcached server"; - - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - - serviceConfig = { - ExecStart = - let - networking = if cfg.socket != "" - then "-s ${cfg.socket}" - else "-l ${cfg.listen} -p ${toString cfg.port}"; - in "${memcached}/bin/memcached ${networking} -m ${toString cfg.maxMemory} -c ${toString cfg.maxConnections} ${concatStringsSep " " cfg.extraOptions}"; - - User = cfg.user; - }; + systemd.services.memcached = { + description = "Memcached server"; + + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + serviceConfig = { + PermissionsStartOnly = true; + ExecStartPre = optionals cfg.enableUnixSocket [ + "${pkgs.coreutils}/bin/install -d -o ${cfg.user} /run/memcached/" + "${pkgs.coreutils}/bin/chown -R ${cfg.user} /run/memcached/" + ]; + ExecStart = + let + networking = if cfg.enableUnixSocket + then "-s /run/memcached/memcached.sock" + else "-l ${cfg.listen} -p ${toString cfg.port}"; + in "${memcached}/bin/memcached ${networking} -m ${toString cfg.maxMemory} -c ${toString cfg.maxConnections} ${concatStringsSep " " cfg.extraOptions}"; + + User = cfg.user; }; + }; }; + imports = [ + (mkRemovedOptionModule ["services" "memcached" "socket"] '' + This option was replaced by a fixed unix socket path at /run/memcached/memcached.sock enabled using services.memached.enableUnixSocket. + '') + ]; } diff --git a/nixos/modules/services/databases/mysql.nix b/nixos/modules/services/databases/mysql.nix index a3bf4f9ba925..36d5340a306f 100644 --- a/nixos/modules/services/databases/mysql.nix +++ b/nixos/modules/services/databases/mysql.nix @@ -7,14 +7,12 @@ let cfg = config.services.mysql; mysql = cfg.package; - - isMariaDB = + + isMariaDB = let pName = _p: (builtins.parseDrvName (_p.name)).name; in pName mysql == pName pkgs.mariadb; - atLeast55 = versionAtLeast mysql.mysqlVersion "5.5"; - pidFile = "${cfg.pidDir}/mysqld.pid"; mysqldOptions = @@ -28,13 +26,6 @@ let ${optionalString (cfg.bind != null) "bind-address = ${cfg.bind}" } ${optionalString (cfg.replication.role == "master" || cfg.replication.role == "slave") "log-bin=mysql-bin"} ${optionalString (cfg.replication.role == "master" || cfg.replication.role == "slave") "server-id = ${toString cfg.replication.serverId}"} - ${optionalString (cfg.replication.role == "slave" && !atLeast55) - '' - master-host = ${cfg.replication.masterHost} - master-user = ${cfg.replication.masterUser} - master-password = ${cfg.replication.masterPassword} - master-port = ${toString cfg.replication.masterPort} - ''} ${optionalString (cfg.ensureUsers != []) '' plugin-load-add = auth_socket.so @@ -315,7 +306,7 @@ in fi '') cfg.initialDatabases} - ${optionalString (cfg.replication.role == "master" && atLeast55) + ${optionalString (cfg.replication.role == "master") '' # Set up the replication master @@ -326,7 +317,7 @@ in ) | ${mysql}/bin/mysql -u root -N ''} - ${optionalString (cfg.replication.role == "slave" && atLeast55) + ${optionalString (cfg.replication.role == "slave") '' # Set up the replication slave diff --git a/nixos/modules/services/databases/redis.nix b/nixos/modules/services/databases/redis.nix index a039ad138f6f..e4e38a4364a0 100644 --- a/nixos/modules/services/databases/redis.nix +++ b/nixos/modules/services/databases/redis.nix @@ -219,7 +219,6 @@ in users.extraUsers.redis = { name = cfg.user; - uid = config.ids.uids.redis; description = "Redis database user"; }; diff --git a/nixos/modules/services/desktops/gnome3/at-spi2-core.nix b/nixos/modules/services/desktops/gnome3/at-spi2-core.nix index 55ed2d9ee21b..9e382241348b 100644 --- a/nixos/modules/services/desktops/gnome3/at-spi2-core.nix +++ b/nixos/modules/services/desktops/gnome3/at-spi2-core.nix @@ -28,14 +28,15 @@ with lib; ###### implementation - config = mkIf config.services.gnome3.at-spi2-core.enable { - - environment.systemPackages = [ pkgs.at_spi2_core ]; - - services.dbus.packages = [ pkgs.at_spi2_core ]; - - systemd.packages = [ pkgs.at_spi2_core ]; - - }; - + config = mkMerge [ + (mkIf config.services.gnome3.at-spi2-core.enable { + environment.systemPackages = [ pkgs.at_spi2_core ]; + services.dbus.packages = [ pkgs.at_spi2_core ]; + systemd.packages = [ pkgs.at_spi2_core ]; + }) + + (mkIf (!config.services.gnome3.at-spi2-core.enable) { + environment.variables.NO_AT_BRIDGE = "1"; + }) + ]; } diff --git a/nixos/modules/services/games/ghost-one.nix b/nixos/modules/services/games/ghost-one.nix deleted file mode 100644 index 71ff6bb2f3f0..000000000000 --- a/nixos/modules/services/games/ghost-one.nix +++ /dev/null @@ -1,105 +0,0 @@ -{ config, lib, pkgs, ... }: -with lib; -let - - cfg = config.services.ghostOne; - ghostUser = "ghostone"; - stateDir = "/var/lib/ghost-one"; - -in -{ - - ###### interface - - options = { - services.ghostOne = { - - enable = mkOption { - default = false; - description = "Enable Ghost-One Warcraft3 game hosting server."; - }; - - language = mkOption { - default = "English"; - type = types.enum [ "English" "Spanish" "Russian" "Serbian" "Turkish" ]; - description = "The language of bot messages: English, Spanish, Russian, Serbian or Turkish."; - }; - - war3path = mkOption { - default = ""; - description = '' - The path to your local Warcraft III directory, which must contain war3.exe, storm.dll, and game.dll. - ''; - }; - - mappath = mkOption { - default = ""; - description = '' - The path to the directory where you keep your map files. GHost One doesn't require - map files but if it has access to them it can send them to players and automatically - calculate most map config values. GHost One will search [bot_mappath + map_localpath] - for the map file (map_localpath is set in each map's config file). - ''; - }; - - config = mkOption { - default = ""; - description = "Extra configuration options."; - }; - - }; - }; - - ###### implementation - - config = mkIf cfg.enable { - - users.extraUsers = singleton - { name = ghostUser; - uid = config.ids.uids.ghostone; - description = "Ghost One game server user"; - home = stateDir; - }; - - users.extraGroups = singleton - { name = ghostUser; - gid = config.ids.gids.ghostone; - }; - - services.ghostOne.config = '' -# bot_log = /dev/stderr - bot_language = ${pkgs.ghostOne}/share/ghost-one/languages/${cfg.language}.cfg - bot_war3path = ${cfg.war3path} - - bot_mapcfgpath = mapcfgs - bot_savegamepath = savegames - bot_mappath = ${cfg.mappath} - bot_replaypath = replays - ''; - - systemd.services."ghost-one" = { - wantedBy = [ "multi-user.target" ]; - script = '' - mkdir -p ${stateDir} - cd ${stateDir} - chown ${ghostUser}:${ghostUser} . - - mkdir -p mapcfgs - chown ${ghostUser}:${ghostUser} mapcfgs - - mkdir -p replays - chown ${ghostUser}:${ghostUser} replays - - mkdir -p savegames - chown ${ghostUser}:${ghostUser} savegames - - ln -sf ${pkgs.writeText "ghost.cfg" cfg.config} ghost.cfg - ln -sf ${pkgs.ghostOne}/share/ghost-one/ip-to-country.csv - ${pkgs.su}/bin/su -s ${pkgs.stdenv.shell} ${ghostUser} \ - -c "LANG=C ${pkgs.ghostOne}/bin/ghost++" - ''; - }; - - }; - -} diff --git a/nixos/modules/services/hardware/80-net-setup-link.rules b/nixos/modules/services/hardware/80-net-setup-link.rules deleted file mode 100644 index 18547f170a3f..000000000000 --- a/nixos/modules/services/hardware/80-net-setup-link.rules +++ /dev/null @@ -1,13 +0,0 @@ -# Copied from systemd 203. -ACTION=="remove", GOTO="net_name_slot_end" -SUBSYSTEM!="net", GOTO="net_name_slot_end" -NAME!="", GOTO="net_name_slot_end" - -IMPORT{cmdline}="net.ifnames" -ENV{net.ifnames}=="0", GOTO="net_name_slot_end" - -NAME=="", ENV{ID_NET_NAME_ONBOARD}!="", NAME="$env{ID_NET_NAME_ONBOARD}" -NAME=="", ENV{ID_NET_NAME_SLOT}!="", NAME="$env{ID_NET_NAME_SLOT}" -NAME=="", ENV{ID_NET_NAME_PATH}!="", NAME="$env{ID_NET_NAME_PATH}" - -LABEL="net_name_slot_end" diff --git a/nixos/modules/services/hardware/thinkfan.nix b/nixos/modules/services/hardware/thinkfan.nix index 018e82e58a3d..5a898631e090 100644 --- a/nixos/modules/services/hardware/thinkfan.nix +++ b/nixos/modules/services/hardware/thinkfan.nix @@ -55,7 +55,7 @@ in { enable = mkOption { default = false; description = '' - Whether to enable thinkfan, fan controller for ibm/lenovo thinkpads. + Whether to enable thinkfan, fan controller for IBM/Lenovo ThinkPads. ''; }; diff --git a/nixos/modules/services/hardware/u2f.nix b/nixos/modules/services/hardware/u2f.nix new file mode 100644 index 000000000000..bb4b2f05f890 --- /dev/null +++ b/nixos/modules/services/hardware/u2f.nix @@ -0,0 +1,23 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.hardware.u2f; +in { + options = { + hardware.u2f = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Enable U2F hardware support. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + services.udev.packages = [ pkgs.libu2f-host ]; + }; +} + diff --git a/nixos/modules/services/hardware/udev.nix b/nixos/modules/services/hardware/udev.nix index 9f42f9e59ad5..730e538e72f6 100644 --- a/nixos/modules/services/hardware/udev.nix +++ b/nixos/modules/services/hardware/udev.nix @@ -119,7 +119,7 @@ let fi ${optionalString config.networking.usePredictableInterfaceNames '' - cp ${./80-net-setup-link.rules} $out/80-net-setup-link.rules + cp ${udev}/lib/udev/rules.d/80-net-setup-link.rules $out/80-net-setup-link.rules ''} # If auto-configuration is disabled, then remove diff --git a/nixos/modules/services/hardware/usbmuxd.nix b/nixos/modules/services/hardware/usbmuxd.nix new file mode 100644 index 000000000000..7ebd49fa01c2 --- /dev/null +++ b/nixos/modules/services/hardware/usbmuxd.nix @@ -0,0 +1,74 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + defaultUserGroup = "usbmux"; + apple = "05ac"; + + cfg = config.services.usbmuxd; + +in + +{ + options.services.usbmuxd = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Enable the usbmuxd ("USB multiplexing daemon") service. This daemon is + in charge of multiplexing connections over USB to an iOS device. This is + needed for transferring data from and to iOS devices (see ifuse). Also + this may enable plug-n-play tethering for iPhones. + ''; + }; + + user = mkOption { + type = types.str; + default = defaultUserGroup; + description = '' + The user usbmuxd should use to run after startup. + ''; + }; + + group = mkOption { + type = types.str; + default = defaultUserGroup; + description = '' + The group usbmuxd should use to run after startup. + ''; + }; + }; + + config = mkIf cfg.enable { + + users.extraUsers = optional (cfg.user == defaultUserGroup) { + name = cfg.user; + description = "usbmuxd user"; + group = cfg.group; + }; + + users.extraGroups = optional (cfg.group == defaultUserGroup) { + name = cfg.group; + }; + + # Give usbmuxd permission for Apple devices + services.udev.extraRules = '' + SUBSYSTEM=="usb", ATTR{idVendor}=="${apple}", GROUP="${cfg.group}" + ''; + + systemd.services.usbmuxd = { + description = "usbmuxd"; + wantedBy = [ "multi-user.target" ]; + unitConfig.Documentation = "man:usbmuxd(8)"; + serviceConfig = { + # Trigger the udev rule manually. This doesn't require replugging the + # device when first enabling the option to get it to work + ExecStartPre = "${pkgs.libudev}/bin/udevadm trigger -s usb -a idVendor=${apple}"; + ExecStart = "${pkgs.usbmuxd}/bin/usbmuxd -U ${cfg.user} -f"; + }; + }; + + }; +} diff --git a/nixos/modules/services/logging/logcheck.nix b/nixos/modules/services/logging/logcheck.nix index 2a8ac414720b..a4cab0c94cdc 100644 --- a/nixos/modules/services/logging/logcheck.nix +++ b/nixos/modules/services/logging/logcheck.nix @@ -8,7 +8,7 @@ let defaultRules = pkgs.runCommand "logcheck-default-rules" {} '' cp -prd ${pkgs.logcheck}/etc/logcheck $out chmod u+w $out - rm $out/logcheck.* + rm -r $out/logcheck.* ''; rulesDir = pkgs.symlinkJoin diff --git a/nixos/modules/services/logging/logstash.nix b/nixos/modules/services/logging/logstash.nix index b4abd2cd7e5e..28d89a7463ab 100644 --- a/nixos/modules/services/logging/logstash.nix +++ b/nixos/modules/services/logging/logstash.nix @@ -103,7 +103,7 @@ in listenAddress = mkOption { type = types.str; - default = "0.0.0.0"; + default = "127.0.0.1"; description = "Address on which to start webserver."; }; diff --git a/nixos/modules/services/mail/clamsmtp.nix b/nixos/modules/services/mail/clamsmtp.nix new file mode 100644 index 000000000000..8f4f39aa7288 --- /dev/null +++ b/nixos/modules/services/mail/clamsmtp.nix @@ -0,0 +1,179 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.services.clamsmtp; + clamdSocket = "/run/clamav/clamd.ctl"; # See services/security/clamav.nix +in +{ + ##### interface + options = { + services.clamsmtp = { + enable = mkOption { + type = types.bool; + default = false; + description = "Whether to enable clamsmtp."; + }; + + instances = mkOption { + description = "Instances of clamsmtp to run."; + type = types.listOf (types.submodule { options = { + action = mkOption { + type = types.enum [ "bounce" "drop" "pass" ]; + default = "drop"; + description = + '' + Action to take when a virus is detected. + + Note that viruses often spoof sender addresses, so bouncing is + in most cases not a good idea. + ''; + }; + + header = mkOption { + type = types.str; + default = ""; + example = "X-Virus-Scanned: ClamAV using ClamSMTP"; + description = + '' + A header to add to scanned messages. See clamsmtpd.conf(5) for + more details. Empty means no header. + ''; + }; + + keepAlives = mkOption { + type = types.int; + default = 0; + description = + '' + Number of seconds to wait between each NOOP sent to the sending + server. 0 to disable. + + This is meant for slow servers where the sending MTA times out + waiting for clamd to scan the file. + ''; + }; + + listen = mkOption { + type = types.str; + example = "127.0.0.1:10025"; + description = + '' + Address to wait for incoming SMTP connections on. See + clamsmtpd.conf(5) for more details. + ''; + }; + + quarantine = mkOption { + type = types.bool; + default = false; + description = + '' + Whether to quarantine files that contain viruses by leaving them + in the temporary directory. + ''; + }; + + maxConnections = mkOption { + type = types.int; + default = 64; + description = "Maximum number of connections to accept at once."; + }; + + outAddress = mkOption { + type = types.str; + description = + '' + Address of the SMTP server to send email to once it has been + scanned. + ''; + }; + + tempDirectory = mkOption { + type = types.str; + default = "/tmp"; + description = + '' + Temporary directory that needs to be accessible to both clamd + and clamsmtpd. + ''; + }; + + timeout = mkOption { + type = types.int; + default = 180; + description = "Time-out for network connections."; + }; + + transparentProxy = mkOption { + type = types.bool; + default = false; + description = "Enable clamsmtp's transparent proxy support."; + }; + + virusAction = mkOption { + type = with types; nullOr path; + default = null; + description = + '' + Command to run when a virus is found. Please see VIRUS ACTION in + clamsmtpd(8) for a discussion of this option and its safe use. + ''; + }; + + xClient = mkOption { + type = types.bool; + default = false; + description = + '' + Send the XCLIENT command to the receiving server, for forwarding + client addresses and connection information if the receiving + server supports this feature. + ''; + }; + };}); + }; + }; + }; + + ##### implementation + config = let + configfile = conf: pkgs.writeText "clamsmtpd.conf" + '' + Action: ${conf.action} + ClamAddress: ${clamdSocket} + Header: ${conf.header} + KeepAlives: ${toString conf.keepAlives} + Listen: ${conf.listen} + Quarantine: ${if conf.quarantine then "on" else "off"} + MaxConnections: ${toString conf.maxConnections} + OutAddress: ${conf.outAddress} + TempDirectory: ${conf.tempDirectory} + TimeOut: ${toString conf.timeout} + TransparentProxy: ${if conf.transparentProxy then "on" else "off"} + User: clamav + ${optionalString (conf.virusAction != null) "VirusAction: ${conf.virusAction}"} + XClient: ${if conf.xClient then "on" else "off"} + ''; + in + mkIf cfg.enable { + assertions = [ + { assertion = config.services.clamav.daemon.enable; + message = "clamsmtp requires clamav to be enabled"; + } + ]; + + systemd.services = listToAttrs (imap1 (i: conf: + nameValuePair "clamsmtp-${toString i}" { + description = "ClamSMTP instance ${toString i}"; + wantedBy = [ "multi-user.target" ]; + script = "exec ${pkgs.clamsmtp}/bin/clamsmtpd -f ${configfile conf}"; + after = [ "clamav-daemon.service" ]; + requires = [ "clamav-daemon.service" ]; + serviceConfig.Type = "forking"; + serviceConfig.PrivateTmp = "yes"; + unitConfig.JoinsNamespaceOf = "clamav-daemon.service"; + } + ) cfg.instances); + }; +} diff --git a/nixos/modules/services/mail/dkimproxy-out.nix b/nixos/modules/services/mail/dkimproxy-out.nix new file mode 100644 index 000000000000..894b88e25c1b --- /dev/null +++ b/nixos/modules/services/mail/dkimproxy-out.nix @@ -0,0 +1,118 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.services.dkimproxy-out; + keydir = "/var/lib/dkimproxy-out"; + privkey = "${keydir}/private.key"; + pubkey = "${keydir}/public.key"; +in +{ + ##### interface + options = { + services.dkimproxy-out = { + enable = mkOption { + type = types.bool; + default = false; + description = + '' + Whether to enable dkimproxy_out. + + Note that a key will be auto-generated, and can be found in + ${keydir}. + ''; + }; + + listen = mkOption { + type = types.str; + example = "127.0.0.1:10027"; + description = "Address:port DKIMproxy should listen on."; + }; + + relay = mkOption { + type = types.str; + example = "127.0.0.1:10028"; + description = "Address:port DKIMproxy should forward mail to."; + }; + + domains = mkOption { + type = with types; listOf str; + example = [ "example.org" "example.com" ]; + description = "List of domains DKIMproxy can sign for."; + }; + + selector = mkOption { + type = types.str; + example = "selector1"; + description = + '' + The selector to use for DKIM key identification. + + For example, if 'selector1' is used here, then for each domain + 'example.org' given in `domain`, 'selector1._domainkey.example.org' + should contain the TXT record indicating the public key is the one + in ${pubkey}: "v=DKIM1; t=s; p=[THE PUBLIC KEY]". + ''; + }; + + keySize = mkOption { + type = types.int; + default = 2048; + description = + '' + Size of the RSA key to use to sign outgoing emails. Note that the + maximum mandatorily verified as per RFC6376 is 2048. + ''; + }; + + # TODO: allow signature for other schemes than dkim(c=relaxed/relaxed)? + # This being the scheme used by gmail, maybe nothing more is needed for + # reasonable use. + }; + }; + + ##### implementation + config = let + configfile = pkgs.writeText "dkimproxy_out.conf" + '' + listen ${cfg.listen} + relay ${cfg.relay} + + domain ${concatStringsSep "," cfg.domains} + selector ${cfg.selector} + + signature dkim(c=relaxed/relaxed) + + keyfile ${privkey} + ''; + in + mkIf cfg.enable { + users.groups.dkimproxy-out = {}; + users.users.dkimproxy-out = { + description = "DKIMproxy_out daemon"; + group = "dkimproxy-out"; + isSystemUser = true; + }; + + systemd.services.dkimproxy-out = { + description = "DKIMproxy_out"; + wantedBy = [ "multi-user.target" ]; + preStart = '' + if [ ! -d "${keydir}" ]; then + mkdir -p "${keydir}" + chmod 0700 "${keydir}" + ${pkgs.openssl}/bin/openssl genrsa -out "${privkey}" ${toString cfg.keySize} + ${pkgs.openssl}/bin/openssl rsa -in "${privkey}" -pubout -out "${pubkey}" + chown -R dkimproxy-out:dkimproxy-out "${keydir}" + fi + ''; + script = '' + exec ${pkgs.dkimproxy}/bin/dkimproxy.out --conf_file=${configfile} + ''; + serviceConfig = { + User = "dkimproxy-out"; + PermissionsStartOnly = true; + }; + }; + }; +} diff --git a/nixos/modules/services/mail/rspamd.nix b/nixos/modules/services/mail/rspamd.nix index 6d403e448e04..b80aa48f2c86 100644 --- a/nixos/modules/services/mail/rspamd.nix +++ b/nixos/modules/services/mail/rspamd.nix @@ -31,6 +31,8 @@ let ${mkBindSockets cfg.bindUISocket} .include "$CONFDIR/worker-controller.inc" } + + ${cfg.extraConfig} ''; in @@ -79,6 +81,15 @@ in ''; }; + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra configuration to add at the end of the rspamd configuration + file. + ''; + }; + user = mkOption { type = types.string; default = "rspamd"; diff --git a/nixos/modules/services/misc/dysnomia.nix b/nixos/modules/services/misc/dysnomia.nix index df44d0a54866..c5c41ad296da 100644 --- a/nixos/modules/services/misc/dysnomia.nix +++ b/nixos/modules/services/misc/dysnomia.nix @@ -192,9 +192,11 @@ in mysqlPassword = builtins.readFile (config.services.mysql.rootPassword); }; } - // lib.optionalAttrs (config.services.postgresql.enable && cfg.enableAuthentication) { postgresql-database = { - postgresqlUsername = "root"; - }; } + // lib.optionalAttrs (config.services.postgresql.enable) { postgresql-database = { + } // lib.optionalAttrs (cfg.enableAuthentication) { + postgresqlUsername = "postgres"; + }; + } // lib.optionalAttrs (config.services.tomcat.enable) { tomcat-webapplication = { tomcatPort = 8080; }; } diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix index 7b2b40e59232..9ed5875a0191 100644 --- a/nixos/modules/services/misc/gitlab.nix +++ b/nixos/modules/services/misc/gitlab.nix @@ -29,8 +29,12 @@ let gitalyToml = pkgs.writeText "gitaly.toml" '' socket_path = "${lib.escape ["\""] gitalySocket}" + bin_dir = "${cfg.packages.gitaly}/bin" prometheus_listen_addr = "localhost:9236" + [git] + bin_path = "${pkgs.git}/bin/git" + [gitaly-ruby] dir = "${cfg.packages.gitaly.ruby}" @@ -70,7 +74,7 @@ let secret_key_base: ${cfg.secrets.secret} otp_key_base: ${cfg.secrets.otp} db_key_base: ${cfg.secrets.db} - jws_private_key: ${builtins.toJSON cfg.secrets.jws} + openid_connect_signing_key: ${builtins.toJSON cfg.secrets.jws} ''; gitlabConfig = { @@ -104,6 +108,7 @@ let ldap.enabled = false; omniauth.enabled = false; shared.path = "${cfg.statePath}/shared"; + gitaly.client_path = "${cfg.packages.gitaly}/bin"; backup.path = "${cfg.backupPath}"; gitlab_shell = { path = "${cfg.packages.gitlab-shell}"; @@ -117,8 +122,6 @@ let }; git = { bin_path = "git"; - max_size = 20971520; # 20MB - timeout = 10; }; monitoring = { ip_whitelist = [ "127.0.0.0/8" "::1/128" ]; @@ -248,7 +251,6 @@ in { databasePassword = mkOption { type = types.str; - default = ""; description = "Gitlab database user password."; }; @@ -440,12 +442,6 @@ in { environment.systemPackages = [ pkgs.git gitlab-rake cfg.packages.gitlab-shell ]; - assertions = [ - { assertion = cfg.databasePassword != ""; - message = "databasePassword must be set"; - } - ]; - # Redis is required for the sidekiq queue runner. services.redis.enable = mkDefault true; # We use postgres as the main data store. @@ -496,7 +492,9 @@ in { after = [ "network.target" "gitlab.service" ]; wantedBy = [ "multi-user.target" ]; environment.HOME = gitlabEnv.HOME; - path = with pkgs; [ gitAndTools.git cfg.packages.gitaly.rubyEnv ]; + environment.GEM_HOME = "${cfg.packages.gitaly.rubyEnv}/${ruby.gemPath}"; + environment.GITLAB_SHELL_CONFIG_PATH = gitlabEnv.GITLAB_SHELL_CONFIG_PATH; + path = with pkgs; [ gitAndTools.git cfg.packages.gitaly.rubyEnv ruby ]; serviceConfig = { #PermissionsStartOnly = true; # preStart must be run as root Type = "simple"; diff --git a/nixos/modules/services/misc/gitolite.nix b/nixos/modules/services/misc/gitolite.nix index f395b9558b5a..6e60316d000c 100644 --- a/nixos/modules/services/misc/gitolite.nix +++ b/nixos/modules/services/misc/gitolite.nix @@ -207,7 +207,7 @@ in gitolite setup -pk ${pubkeyFile} fi if [ -n "${hooks}" ]; then - cp ${hooks} .gitolite/hooks/common/ + cp -f ${hooks} .gitolite/hooks/common/ chmod +x .gitolite/hooks/common/* fi gitolite setup # Upgrade if needed diff --git a/nixos/modules/services/misc/gollum.nix b/nixos/modules/services/misc/gollum.nix index 81fb024f9094..0888221ab62f 100644 --- a/nixos/modules/services/misc/gollum.nix +++ b/nixos/modules/services/misc/gollum.nix @@ -32,6 +32,24 @@ in description = "Content of the configuration file"; }; + mathjax = mkOption { + type = types.bool; + default = false; + description = "Enable support for math rendering using MathJax"; + }; + + allowUploads = mkOption { + type = types.nullOr (types.enum [ "dir" "page" ]); + default = null; + description = "Enable uploads of external files"; + }; + + emoji = mkOption { + type = types.bool; + default = false; + description = "Parse and interpret emoji tags"; + }; + branch = mkOption { type = types.str; default = "master"; @@ -84,6 +102,9 @@ in --host ${cfg.address} \ --config ${builtins.toFile "gollum-config.rb" cfg.extraConfig} \ --ref ${cfg.branch} \ + ${optionalString cfg.mathjax "--mathjax"} \ + ${optionalString cfg.emoji "--emoji"} \ + ${optionalString (cfg.allowUploads != null) "--allow-uploads ${cfg.allowUploads}"} \ ${cfg.stateDir} ''; }; diff --git a/nixos/modules/services/misc/logkeys.nix b/nixos/modules/services/misc/logkeys.nix index 6051c884465d..df0b3ae24c90 100644 --- a/nixos/modules/services/misc/logkeys.nix +++ b/nixos/modules/services/misc/logkeys.nix @@ -1,4 +1,4 @@ -{ config, lib, ... }: +{ config, lib, pkgs, ... }: with lib; diff --git a/nixos/modules/services/misc/matrix-synapse.nix b/nixos/modules/services/misc/matrix-synapse.nix index 11463cf4500a..80979547d339 100644 --- a/nixos/modules/services/misc/matrix-synapse.nix +++ b/nixos/modules/services/misc/matrix-synapse.nix @@ -578,6 +578,18 @@ in { Extra config options for matrix-synapse. ''; }; + extraConfigFiles = mkOption { + type = types.listOf types.path; + default = []; + description = '' + Extra config files to include. + + The configuration files will be included based on the command line + argument --config-path. This allows to configure secrets without + having to go through the Nix store, e.g. based on deployment keys if + NixOPS is in use. + ''; + }; logConfig = mkOption { type = types.lines; default = readFile ./matrix-synapse-log_config.yaml; @@ -627,7 +639,11 @@ in { Group = "matrix-synapse"; WorkingDirectory = cfg.dataDir; PermissionsStartOnly = true; - ExecStart = "${cfg.package}/bin/homeserver --config-path ${configFile} --keys-directory ${cfg.dataDir}"; + ExecStart = '' + ${cfg.package}/bin/homeserver \ + ${ concatMapStringsSep "\n " (x: "--config-path ${x} \\") ([ configFile ] ++ cfg.extraConfigFiles) } + --keys-directory ${cfg.dataDir} + ''; Restart = "on-failure"; }; }; diff --git a/nixos/modules/services/misc/mbpfan.nix b/nixos/modules/services/misc/mbpfan.nix index 972d8b572d36..50f6f80ad00c 100644 --- a/nixos/modules/services/misc/mbpfan.nix +++ b/nixos/modules/services/misc/mbpfan.nix @@ -8,13 +8,7 @@ let in { options.services.mbpfan = { - enable = mkOption { - default = false; - type = types.bool; - description = '' - Whether to enable the mbpfan daemon. - ''; - }; + enable = mkEnableOption "mbpfan, fan controller daemon for Apple Macs and MacBooks"; package = mkOption { type = types.package; diff --git a/nixos/modules/services/misc/osrm.nix b/nixos/modules/services/misc/osrm.nix new file mode 100644 index 000000000000..7ec8b15906fc --- /dev/null +++ b/nixos/modules/services/misc/osrm.nix @@ -0,0 +1,85 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.osrm; +in + +{ + options.services.osrm = { + enable = mkOption { + type = types.bool; + default = false; + description = "Enable the OSRM service."; + }; + + address = mkOption { + type = types.str; + default = "0.0.0.0"; + description = "IP address on which the web server will listen."; + }; + + port = mkOption { + type = types.int; + default = 5000; + description = "Port on which the web server will run."; + }; + + threads = mkOption { + type = types.int; + default = 4; + description = "Number of threads to use."; + }; + + algorithm = mkOption { + type = types.enum [ "CH" "CoreCH" "MLD" ]; + default = "MLD"; + description = "Algorithm to use for the data. Must be one of CH, CoreCH, MLD"; + }; + + extraFlags = mkOption { + type = types.listOf types.str; + default = []; + example = [ "--max-table-size 1000" "--max-matching-size 1000" ]; + description = "Extra command line arguments passed to osrm-routed"; + }; + + dataFile = mkOption { + type = types.path; + example = "/var/lib/osrm/berlin-latest.osrm"; + description = "Data file location"; + }; + + }; + + config = mkIf cfg.enable { + + users.users.osrm = { + group = config.users.users.osrm.name; + description = "OSRM user"; + createHome = false; + }; + + users.groups.osrm = { }; + + systemd.services.osrm = { + description = "OSRM service"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + User = config.users.extraUsers.osrm.name; + ExecStart = '' + ${pkgs.osrm-backend}/bin/osrm-routed \ + --ip ${cfg.address} \ + --port ${toString cfg.port} \ + --threads ${toString cfg.threads} \ + --algorithm ${cfg.algorithm} \ + ${toString cfg.extraFlags} \ + ${cfg.dataFile} + ''; + }; + }; + }; +} diff --git a/nixos/modules/services/misc/xmr-stak.nix b/nixos/modules/services/misc/xmr-stak.nix new file mode 100644 index 000000000000..57f439365471 --- /dev/null +++ b/nixos/modules/services/misc/xmr-stak.nix @@ -0,0 +1,73 @@ +{ lib, config, pkgs, ... }: + +with lib; + +let + + cfg = config.services.xmr-stak; + + pkg = pkgs.xmr-stak.override { + inherit (cfg) openclSupport cudaSupport; + }; + + xmrConfArg = optionalString (cfg.configText != "") ("-c " + + pkgs.writeText "xmr-stak-config.txt" cfg.configText); + +in + +{ + options = { + services.xmr-stak = { + enable = mkEnableOption "xmr-stak miner"; + openclSupport = mkEnableOption "support for OpenCL (AMD/ATI graphics cards)"; + cudaSupport = mkEnableOption "support for CUDA (NVidia graphics cards)"; + + extraArgs = mkOption { + type = types.listOf types.str; + default = []; + example = [ "--noCPU" "--currency monero" ]; + description = "List of parameters to pass to xmr-stak."; + }; + + configText = mkOption { + type = types.lines; + default = ""; + example = '' + "currency" : "monero", + "pool_list" : + [ { "pool_address" : "pool.supportxmr.com:5555", + "wallet_address" : "<long-hash>", + "pool_password" : "minername", + "pool_weight" : 1, + }, + ], + ''; + description = '' + Verbatim xmr-stak config.txt. If empty, the <literal>-c</literal> + parameter will not be added to the xmr-stak command. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + systemd.services.xmr-stak = { + wantedBy = [ "multi-user.target" ]; + bindsTo = [ "network-online.target" ]; + after = [ "network-online.target" ]; + environment = mkIf cfg.cudaSupport { + LD_LIBRARY_PATH = "${pkgs.linuxPackages_latest.nvidia_x11}/lib"; + }; + script = '' + exec ${pkg}/bin/xmr-stak ${xmrConfArg} ${concatStringsSep " " cfg.extraArgs} + ''; + serviceConfig = let rootRequired = cfg.openclSupport || cfg.cudaSupport; in { + # xmr-stak generates cpu and/or gpu configuration files + WorkingDirectory = "/tmp"; + PrivateTmp = true; + DynamicUser = !rootRequired; + LimitMEMLOCK = toString (1024*1024); + }; + }; + }; +} diff --git a/nixos/modules/services/monitoring/smartd.nix b/nixos/modules/services/monitoring/smartd.nix index 1d6940c516a9..b8d9e58a5a82 100644 --- a/nixos/modules/services/monitoring/smartd.nix +++ b/nixos/modules/services/monitoring/smartd.nix @@ -64,7 +64,7 @@ let "DEVICESCAN ${notifyOpts}${cfg.defaults.autodetected}"} ''; - smartdOpts = { name, ... }: { + smartdDeviceOpts = { name, ... }: { options = { @@ -108,6 +108,18 @@ in ''; }; + extraOptions = mkOption { + default = []; + type = types.listOf types.str; + example = ["-A /var/log/smartd/" "--interval=3600"]; + description = '' + Extra command-line options passed to the <literal>smartd</literal> + daemon on startup. + + (See <literal>man 8 smartd</literal>.) + ''; + }; + notifications = { mail = { @@ -197,7 +209,7 @@ in devices = mkOption { default = []; example = [ { device = "/dev/sda"; } { device = "/dev/sdb"; options = "-d sat"; } ]; - type = with types; listOf (submodule smartdOpts); + type = with types; listOf (submodule smartdDeviceOpts); description = "List of devices to monitor."; }; @@ -222,7 +234,7 @@ in path = [ pkgs.nettools ]; # for hostname and dnsdomanname calls in smartd - serviceConfig.ExecStart = "${pkgs.smartmontools}/sbin/smartd --no-fork --configfile=${smartdConf}"; + serviceConfig.ExecStart = "${pkgs.smartmontools}/sbin/smartd ${lib.concatStringsSep " " cfg.extraOptions} --no-fork --configfile=${smartdConf}"; }; }; diff --git a/nixos/modules/services/monitoring/statsd.nix b/nixos/modules/services/monitoring/statsd.nix index df2adb9f2766..7b0e9981cbb1 100644 --- a/nixos/modules/services/monitoring/statsd.nix +++ b/nixos/modules/services/monitoring/statsd.nix @@ -9,6 +9,12 @@ let isBuiltinBackend = name: builtins.elem name [ "graphite" "console" "repeater" ]; + backendsToPackages = let + mkMap = list: name: + if isBuiltinBackend name then list + else list ++ [ pkgs.nodePackages.${name} ]; + in foldl mkMap []; + configFile = pkgs.writeText "statsd.conf" '' { address: "${cfg.listenAddress}", @@ -27,13 +33,21 @@ let prettyprint: false }, log: { - backend: "syslog" + backend: "stdout" }, automaticConfigReload: false${optionalString (cfg.extraConfig != null) ","} ${cfg.extraConfig} } ''; + deps = pkgs.buildEnv { + name = "statsd-runtime-deps"; + pathsToLink = [ "/lib" ]; + ignoreCollisions = true; + + paths = backendsToPackages cfg.backends; + }; + in { @@ -42,11 +56,7 @@ in options.services.statsd = { - enable = mkOption { - description = "Whether to enable statsd stats aggregation service"; - default = false; - type = types.bool; - }; + enable = mkEnableOption "statsd"; listenAddress = mkOption { description = "Address that statsd listens on over UDP"; @@ -110,6 +120,11 @@ in config = mkIf cfg.enable { + assertions = map (backend: { + assertion = !isBuiltinBackend backend -> hasAttrByPath [ backend ] pkgs.nodePackages; + message = "Only builtin backends (graphite, console, repeater) or backends enumerated in `pkgs.nodePackages` are allowed!"; + }) cfg.backends; + users.extraUsers = singleton { name = "statsd"; uid = config.ids.uids.statsd; @@ -120,9 +135,7 @@ in description = "Statsd Server"; wantedBy = [ "multi-user.target" ]; environment = { - NODE_PATH=concatMapStringsSep ":" - (pkg: "${builtins.getAttr pkg pkgs.statsd.nodePackages}/lib/node_modules") - (filter (name: !isBuiltinBackend name) cfg.backends); + NODE_PATH = "${deps}/lib/node_modules"; }; serviceConfig = { ExecStart = "${pkgs.statsd}/bin/statsd ${configFile}"; diff --git a/nixos/modules/services/network-filesystems/beegfs.nix b/nixos/modules/services/network-filesystems/beegfs.nix new file mode 100644 index 000000000000..a6a2ec6cbc36 --- /dev/null +++ b/nixos/modules/services/network-filesystems/beegfs.nix @@ -0,0 +1,343 @@ +{ config, lib, pkgs, ...} : + +with lib; + +let + cfg = config.services.beegfs; + + # functions for the generations of config files + + configMgmtd = name: cfg: pkgs.writeText "mgmt-${name}.conf" '' + storeMgmtdDirectory = ${cfg.mgmtd.storeDir} + storeAllowFirstRunInit = false + connAuthFile = ${cfg.connAuthFile} + connPortShift = ${toString cfg.connPortShift} + + ${cfg.mgmtd.extraConfig} + ''; + + configAdmon = name: cfg: pkgs.writeText "admon-${name}.conf" '' + sysMgmtdHost = ${cfg.mgmtdHost} + connAuthFile = ${cfg.connAuthFile} + connPortShift = ${toString cfg.connPortShift} + + ${cfg.admon.extraConfig} + ''; + + configMeta = name: cfg: pkgs.writeText "meta-${name}.conf" '' + storeMetaDirectory = ${cfg.meta.storeDir} + sysMgmtdHost = ${cfg.mgmtdHost} + connAuthFile = ${cfg.connAuthFile} + connPortShift = ${toString cfg.connPortShift} + storeAllowFirstRunInit = false + + ${cfg.mgmtd.extraConfig} + ''; + + configStorage = name: cfg: pkgs.writeText "storage-${name}.conf" '' + storeStorageDirectory = ${cfg.storage.storeDir} + sysMgmtdHost = ${cfg.mgmtdHost} + connAuthFile = ${cfg.connAuthFile} + connPortShift = ${toString cfg.connPortShift} + storeAllowFirstRunInit = false + + ${cfg.storage.extraConfig} + ''; + + configHelperd = name: cfg: pkgs.writeText "helperd-${name}.conf" '' + connAuthFile = ${cfg.connAuthFile} + ${cfg.helperd.extraConfig} + ''; + + configClientFilename = name : "/etc/beegfs/client-${name}.conf"; + + configClient = name: cfg: '' + sysMgmtdHost = ${cfg.mgmtdHost} + connAuthFile = ${cfg.connAuthFile} + connPortShift = ${toString cfg.connPortShift} + + ${cfg.client.extraConfig} + ''; + + serviceList = [ + { service = "admon"; cfgFile = configAdmon; } + { service = "meta"; cfgFile = configMeta; } + { service = "mgmtd"; cfgFile = configMgmtd; } + { service = "storage"; cfgFile = configStorage; } + ]; + + # functions to generate systemd.service entries + + systemdEntry = service: cfgFile: (mapAttrs' ( name: cfg: + (nameValuePair "beegfs-${service}-${name}" (mkIf cfg."${service}".enable { + wantedBy = [ "multi-user.target" ]; + requires = [ "network-online.target" ]; + after = [ "network-online.target" ]; + serviceConfig = rec { + ExecStart = '' + ${pkgs.beegfs}/bin/beegfs-${service} \ + cfgFile=${cfgFile name cfg} \ + pidFile=${PIDFile} + ''; + PIDFile = "/run/beegfs-${service}-${name}.pid"; + TimeoutStopSec = "300"; + }; + }))) cfg); + + systemdHelperd = mapAttrs' ( name: cfg: + (nameValuePair "beegfs-helperd-${name}" (mkIf cfg.client.enable { + wantedBy = [ "multi-user.target" ]; + requires = [ "network-online.target" ]; + after = [ "network-online.target" ]; + serviceConfig = rec { + ExecStart = '' + ${pkgs.beegfs}/bin/beegfs-helperd \ + cfgFile=${configHelperd name cfg} \ + pidFile=${PIDFile} + ''; + PIDFile = "/run/beegfs-helperd-${name}.pid"; + TimeoutStopSec = "300"; + }; + }))) cfg; + + # wrappers to beegfs tools. Avoid typing path of config files + utilWrappers = mapAttrsToList ( name: cfg: + ( pkgs.runCommand "beegfs-utils-${name}" { nativeBuildInputs = [ pkgs.makeWrapper ]; } '' + mkdir -p $out/bin + + makeWrapper ${pkgs.beegfs}/bin/beegfs-check-servers \ + $out/bin/beegfs-check-servers-${name} \ + --add-flags "-c ${configClientFilename name}" \ + --prefix PATH : ${lib.makeBinPath [ pkgs.beegfs ]} + + makeWrapper ${pkgs.beegfs}/bin/beegfs-ctl \ + $out/bin/beegfs-ctl-${name} \ + --add-flags "--cfgFile=${configClientFilename name}" + + makeWrapper ${pkgs.beegfs}/bin/beegfs-ctl \ + $out/bin/beegfs-df-${name} \ + --add-flags "--cfgFile=${configClientFilename name}" \ + --add-flags --listtargets \ + --add-flags --hidenodeid \ + --add-flags --pools \ + --add-flags --spaceinfo + + makeWrapper ${pkgs.beegfs}/bin/beegfs-fsck \ + $out/bin/beegfs-fsck-${name} \ + --add-flags "--cfgFile=${configClientFilename name}" + '' + )) cfg; +in +{ + ###### interface + + options = { + services.beegfsEnable = mkEnableOption "BeeGFS"; + + services.beegfs = mkOption { + default = {}; + description = '' + BeeGFS configurations. Every mount point requires a separate configuration. + ''; + type = with types; attrsOf (submodule ({ config, ... } : { + options = { + mgmtdHost = mkOption { + type = types.str; + default = null; + example = "master"; + description = ''Hostname of managament host.''; + }; + + connAuthFile = mkOption { + type = types.str; + default = ""; + example = "/etc/my.key"; + description = "File containing shared secret authentication."; + }; + + connPortShift = mkOption { + type = types.int; + default = 0; + example = 5; + description = '' + For each additional beegfs configuration shift all + service TCP/UDP ports by at least 5. + ''; + }; + + client = { + enable = mkEnableOption "BeeGFS client"; + + mount = mkOption { + type = types.bool; + default = true; + description = "Create fstab entry automatically"; + }; + + mountPoint = mkOption { + type = types.str; + default = "/run/beegfs"; + description = '' + Mount point under which the beegfs filesytem should be mounted. + If mounted manually the mount option specifing the config file is needed: + cfgFile=/etc/beegfs/beegfs-client-<name>.conf + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Additional lines for beegfs-client.conf. + See documentation for further details. + ''; + }; + }; + + helperd = { + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Additional lines for beegfs-helperd.conf. See documentation + for further details. + ''; + }; + }; + + mgmtd = { + enable = mkEnableOption "BeeGFS mgmtd daemon"; + + storeDir = mkOption { + type = types.path; + default = null; + example = "/data/beegfs-mgmtd"; + description = '' + Data directory for mgmtd. + Must not be shared with other beegfs daemons. + This directory must exist and it must be initialized + with beegfs-setup-mgmtd, e.g. "beegfs-setup-mgmtd -C -p <storeDir>" + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Additional lines for beegfs-mgmtd.conf. See documentation + for further details. + ''; + }; + }; + + admon = { + enable = mkEnableOption "BeeGFS admon daemon"; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Additional lines for beegfs-admon.conf. See documentation + for further details. + ''; + }; + }; + + meta = { + enable = mkEnableOption "BeeGFS meta data daemon"; + + storeDir = mkOption { + type = types.path; + default = null; + example = "/data/beegfs-meta"; + description = '' + Data directory for meta data service. + Must not be shared with other beegfs daemons. + The underlying filesystem must be mounted with xattr turned on. + This directory must exist and it must be initialized + with beegfs-setup-meta, e.g. + "beegfs-setup-meta -C -s <serviceID> -p <storeDir>" + ''; + }; + + extraConfig = mkOption { + type = types.str; + default = ""; + description = '' + Additional lines for beegfs-meta.conf. See documentation + for further details. + ''; + }; + }; + + storage = { + enable = mkEnableOption "BeeGFS storage daemon"; + + storeDir = mkOption { + type = types.path; + default = null; + example = "/data/beegfs-storage"; + description = '' + Data directories for storage service. + Must not be shared with other beegfs daemons. + The underlying filesystem must be mounted with xattr turned on. + This directory must exist and it must be initialized + with beegfs-setup-storage, e.g. + "beegfs-setup-storage -C -s <serviceID> -i <storageTargetID> -p <storeDir>" + ''; + }; + + extraConfig = mkOption { + type = types.str; + default = ""; + description = '' + Addional lines for beegfs-storage.conf. See documentation + for further details. + ''; + }; + }; + }; + })); + }; + }; + + ###### implementation + + config = + mkIf config.services.beegfsEnable { + + environment.systemPackages = utilWrappers; + + # Put the client.conf files in /etc since they are needed + # by the commandline tools + environment.etc = mapAttrs' ( name: cfg: + (nameValuePair "beegfs/client-${name}.conf" (mkIf (cfg.client.enable) + { + enable = true; + text = configClient name cfg; + }))) cfg; + + # Kernel module, we need it only once per host. + boot = mkIf ( + foldr (a: b: a || b) false + (map (x: x.client.enable) (collect (x: x ? client) cfg))) + { + kernelModules = [ "beegfs" ]; + extraModulePackages = [ pkgs.linuxPackages.beegfs-module ]; + }; + + # generate fstab entries + fileSystems = mapAttrs' (name: cfg: + (nameValuePair cfg.client.mountPoint (optionalAttrs cfg.client.mount (mkIf cfg.client.enable { + device = "beegfs_nodev"; + fsType = "beegfs"; + mountPoint = cfg.client.mountPoint; + options = [ "cfgFile=${configClientFilename name}" "_netdev" ]; + })))) cfg; + + # generate systemd services + systemd.services = systemdHelperd // + foldr (a: b: a // b) {} + (map (x: systemdEntry x.service x.cfgFile) serviceList); + }; +} diff --git a/nixos/modules/services/network-filesystems/davfs2.nix b/nixos/modules/services/network-filesystems/davfs2.nix new file mode 100644 index 000000000000..6b2a770100c5 --- /dev/null +++ b/nixos/modules/services/network-filesystems/davfs2.nix @@ -0,0 +1,74 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.davfs2; + cfgFile = pkgs.writeText "davfs2.conf" '' + dav_user ${cfg.davUser} + dav_group ${cfg.davGroup} + ${cfg.extraConfig} + ''; +in +{ + options.services.davfs2 = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable davfs2. + ''; + }; + + davUser = mkOption { + type = types.string; + default = "davfs2"; + description = '' + When invoked by root the mount.davfs daemon will run as this user. + Value must be given as name, not as numerical id. + ''; + }; + + davGroup = mkOption { + type = types.string; + default = "davfs2"; + description = '' + The group of the running mount.davfs daemon. Ordinary users must be + member of this group in order to mount a davfs2 file system. Value must + be given as name, not as numerical id. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = '' + kernel_fs coda + proxy foo.bar:8080 + use_locks 0 + ''; + description = '' + Extra lines appended to the configuration of davfs2. + '' ; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ pkgs.davfs2 ]; + environment.etc."davfs2/davfs2.conf".source = cfgFile; + + users.extraGroups = optionalAttrs (cfg.davGroup == "davfs2") (singleton { + name = "davfs2"; + gid = config.ids.gids.davfs2; + }); + + users.extraUsers = optionalAttrs (cfg.davUser == "davfs2") (singleton { + name = "davfs2"; + createHome = false; + group = cfg.davGroup; + uid = config.ids.uids.davfs2; + description = "davfs2 user"; + }); + }; + +} diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix index 9b9c91a4f167..09cd9cb22ca8 100644 --- a/nixos/modules/services/network-filesystems/samba.nix +++ b/nixos/modules/services/network-filesystems/samba.nix @@ -56,6 +56,7 @@ let serviceConfig = { ExecStart = "${samba}/sbin/${appName} ${args}"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + LimitNOFILE = 16384; Type = "notify"; }; diff --git a/nixos/modules/services/networking/dnscrypt-proxy.nix b/nixos/modules/services/networking/dnscrypt-proxy.nix index ed658258c7f9..857657eea4db 100644 --- a/nixos/modules/services/networking/dnscrypt-proxy.nix +++ b/nixos/modules/services/networking/dnscrypt-proxy.nix @@ -10,7 +10,7 @@ let # This is somewhat more flexible than preloading the key as an # embedded string. upstreamResolverListPubKey = pkgs.fetchurl { - url = https://raw.githubusercontent.com/jedisct1/dnscrypt-proxy/master/minisign.pub; + url = https://raw.githubusercontent.com/dyne/dnscrypt-proxy/master/minisign.pub; sha256 = "18lnp8qr6ghfc2sd46nn1rhcpr324fqlvgsp4zaigw396cd7vnnh"; }; @@ -258,9 +258,9 @@ in domain=raw.githubusercontent.com get="curl -fSs --resolve $domain:443:$(hostip -r 8.8.8.8 $domain | head -1)" $get -o dnscrypt-resolvers.csv.tmp \ - https://$domain/jedisct1/dnscrypt-proxy/master/dnscrypt-resolvers.csv + https://$domain/dyne/dnscrypt-proxy/master/dnscrypt-resolvers.csv $get -o dnscrypt-resolvers.csv.minisig.tmp \ - https://$domain/jedisct1/dnscrypt-proxy/master/dnscrypt-resolvers.csv.minisig + https://$domain/dyne/dnscrypt-proxy/master/dnscrypt-resolvers.csv.minisig mv dnscrypt-resolvers.csv.minisig{.tmp,} if ! minisign -q -V -p ${upstreamResolverListPubKey} \ -m dnscrypt-resolvers.csv.tmp -x dnscrypt-resolvers.csv.minisig ; then diff --git a/nixos/modules/services/networking/i2pd.nix b/nixos/modules/services/networking/i2pd.nix index ca2e2a065dcf..8f5aeee4a16b 100644 --- a/nixos/modules/services/networking/i2pd.nix +++ b/nixos/modules/services/networking/i2pd.nix @@ -126,6 +126,7 @@ let [${tun.name}] type = client destination = ${tun.destination} + destinationport = ${toString tun.destinationPort} keys = ${tun.keys} address = ${tun.address} port = ${toString tun.port} @@ -137,15 +138,15 @@ let '') } ${flip concatMapStrings - (collect (tun: tun ? port && tun ? host) cfg.inTunnels) - (tun: let portStr = toString tun.port; in '' + (collect (tun: tun ? port && tun ? address) cfg.inTunnels) + (tun: '' [${tun.name}] type = server destination = ${tun.destination} keys = ${tun.keys} host = ${tun.address} - port = ${tun.port} - inport = ${tun.inPort} + port = ${toString tun.port} + inport = ${toString tun.inPort} accesslist = ${builtins.concatStringsSep "," tun.accessList} '') } @@ -405,7 +406,13 @@ in default = {}; type = with types; loaOf (submodule ( { name, config, ... }: { - options = commonTunOpts name; + options = { + destinationPort = mkOption { + type = types.int; + default = 0; + description = "Connect to particular port at destination."; + }; + } // commonTunOpts name; config = { name = mkDefault name; }; diff --git a/nixos/modules/services/networking/kresd.nix b/nixos/modules/services/networking/kresd.nix index 18e2ab9aebf1..011a9b2f58ea 100644 --- a/nixos/modules/services/networking/kresd.nix +++ b/nixos/modules/services/networking/kresd.nix @@ -72,6 +72,7 @@ in (iface: if elem ":" (stringToCharacters iface) then "[${iface}]:53" else "${iface}:53") cfg.interfaces; socketConfig.ListenDatagram = listenStreams; + socketConfig.FreeBind = true; }; systemd.sockets.kresd-control = rec { @@ -82,20 +83,11 @@ in socketConfig = { FileDescriptorName = "control"; Service = "kresd.service"; - SocketMode = "0660"; # only root user/group may connect + SocketMode = "0660"; # only root user/group may connect and control kresd }; }; - # Create the cacheDir; tmpfiles don't work on nixos-rebuild switch. - systemd.services.kresd-cachedir = { - serviceConfig.Type = "oneshot"; - script = '' - if [ ! -d '${cfg.cacheDir}' ]; then - mkdir -p '${cfg.cacheDir}' - chown kresd:kresd '${cfg.cacheDir}' - fi - ''; - }; + systemd.tmpfiles.rules = [ "d '${cfg.cacheDir}' 0770 kresd kresd - -" ]; systemd.services.kresd = { description = "Knot-resolver daemon"; @@ -104,16 +96,15 @@ in User = "kresd"; Type = "notify"; WorkingDirectory = cfg.cacheDir; + Restart = "on-failure"; }; script = '' exec '${package}/bin/kresd' --config '${configFile}' \ - -k '${cfg.cacheDir}/root.key' + -k '${pkgs.dns-root-data}/root.key' ''; - after = [ "kresd-cachedir.service" ]; - requires = [ "kresd.socket" "kresd-cachedir.service" ]; - wantedBy = [ "sockets.target" ]; + requires = [ "kresd.socket" ]; }; }; } diff --git a/nixos/modules/services/networking/lldpd.nix b/nixos/modules/services/networking/lldpd.nix index ba4e1b1542fe..db1534edfd7c 100644 --- a/nixos/modules/services/networking/lldpd.nix +++ b/nixos/modules/services/networking/lldpd.nix @@ -24,6 +24,7 @@ in description = "lldpd user"; group = "_lldpd"; home = "/var/run/lldpd"; + isSystemUser = true; }; users.extraGroups._lldpd = {}; diff --git a/nixos/modules/services/networking/nat.nix b/nixos/modules/services/networking/nat.nix index 366bb2ed7a80..df4246d216d8 100644 --- a/nixos/modules/services/networking/nat.nix +++ b/nixos/modules/services/networking/nat.nix @@ -19,6 +19,8 @@ let iptables -w -t nat -D POSTROUTING -j nixos-nat-post 2>/dev/null || true iptables -w -t nat -F nixos-nat-post 2>/dev/null || true iptables -w -t nat -X nixos-nat-post 2>/dev/null || true + + ${cfg.extraStopCommands} ''; setupNat = '' @@ -53,6 +55,14 @@ let -j DNAT --to-destination ${fwd.destination} '') cfg.forwardPorts} + ${optionalString (cfg.dmzHost != null) '' + iptables -w -t nat -A nixos-nat-pre \ + -i ${cfg.externalInterface} -j DNAT \ + --to-destination ${cfg.dmzHost} + ''} + + ${cfg.extraCommands} + # Append our chains to the nat tables iptables -w -t nat -A PREROUTING -j nixos-nat-pre iptables -w -t nat -A POSTROUTING -j nixos-nat-post @@ -125,15 +135,15 @@ in type = with types; listOf (submodule { options = { sourcePort = mkOption { - type = types.int; + type = types.either types.int (types.strMatching "[[:digit:]]+:[[:digit:]]+"); example = 8080; - description = "Source port of the external interface"; + description = "Source port of the external interface; to specify a port range, use a string with a colon (e.g. \"60000:61000\")"; }; destination = mkOption { type = types.str; example = "10.0.0.1:80"; - description = "Forward connection to destination ip:port"; + description = "Forward connection to destination ip:port; to specify a port range, use ip:start-end"; }; proto = mkOption { @@ -153,6 +163,39 @@ in ''; }; + networking.nat.dmzHost = mkOption { + type = types.nullOr types.str; + default = null; + example = "10.0.0.1"; + description = + '' + The local IP address to which all traffic that does not match any + forwarding rule is forwarded. + ''; + }; + + networking.nat.extraCommands = mkOption { + type = types.lines; + default = ""; + example = "iptables -A INPUT -p icmp -j ACCEPT"; + description = + '' + Additional shell commands executed as part of the nat + initialisation script. + ''; + }; + + networking.nat.extraStopCommands = mkOption { + type = types.lines; + default = ""; + example = "iptables -D INPUT -p icmp -j ACCEPT || true"; + description = + '' + Additional shell commands executed as part of the nat + teardown script. + ''; + }; + }; diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix index 6bdae32f72bb..62afbf32c2f6 100644 --- a/nixos/modules/services/networking/networkmanager.nix +++ b/nixos/modules/services/networking/networkmanager.nix @@ -241,6 +241,19 @@ in { A list of scripts which will be executed in response to network events. ''; }; + + enableStrongSwan = mkOption { + type = types.bool; + default = false; + description = '' + Enable the StrongSwan plugin. + </para><para> + If you enable this option the + <literal>networkmanager_strongswan</literal> plugin will be added to + the <option>networking.networkmanager.packages</option> option + so you don't need to to that yourself. + ''; + }; }; }; @@ -333,13 +346,13 @@ in { wireless.enable = lib.mkDefault false; }; - powerManagement.resumeCommands = '' - ${config.systemd.package}/bin/systemctl restart network-manager - ''; - security.polkit.extraConfig = polkitConf; - services.dbus.packages = cfg.packages; + networking.networkmanager.packages = + mkIf cfg.enableStrongSwan [ pkgs.networkmanager_strongswan ]; + + services.dbus.packages = + optional cfg.enableStrongSwan pkgs.strongswanNM ++ cfg.packages; services.udev.packages = cfg.packages; }; diff --git a/nixos/modules/services/networking/nsd.nix b/nixos/modules/services/networking/nsd.nix index c8b8ed547ebb..4241e6fcceab 100644 --- a/nixos/modules/services/networking/nsd.nix +++ b/nixos/modules/services/networking/nsd.nix @@ -11,6 +11,8 @@ let # build nsd with the options needed for the given config nsdPkg = pkgs.nsd.override { + configFile = "${configFile}/nsd.conf"; + bind8Stats = cfg.bind8Stats; ipv6 = cfg.ipv6; ratelimit = cfg.ratelimit.enable; @@ -788,6 +790,8 @@ in config = mkIf cfg.enable { + environment.systemPackages = [ nsdPkg ]; + users.extraGroups = singleton { name = username; gid = config.ids.gids.nsd; @@ -845,4 +849,6 @@ in }; }; + + meta.maintainers = with lib.maintainers; [ hrdinka ]; } diff --git a/nixos/modules/services/networking/prosody.nix b/nixos/modules/services/networking/prosody.nix index fb9c9dc67f24..f34d8e172b46 100644 --- a/nixos/modules/services/networking/prosody.nix +++ b/nixos/modules/services/networking/prosody.nix @@ -10,98 +10,126 @@ let options = { - # TODO: require attribute key = mkOption { - type = types.str; - description = "Path to the key file"; + type = types.path; + description = "Path to the key file."; }; - # TODO: require attribute cert = mkOption { - type = types.str; - description = "Path to the certificate file"; + type = types.path; + description = "Path to the certificate file."; + }; + + extraOptions = mkOption { + type = types.attrs; + default = {}; + description = "Extra SSL configuration options."; }; + }; }; moduleOpts = { roster = mkOption { + type = types.bool; default = true; description = "Allow users to have a roster"; }; saslauth = mkOption { + type = types.bool; default = true; description = "Authentication for clients and servers. Recommended if you want to log in."; }; tls = mkOption { + type = types.bool; default = true; description = "Add support for secure TLS on c2s/s2s connections"; }; dialback = mkOption { + type = types.bool; default = true; description = "s2s dialback support"; }; disco = mkOption { + type = types.bool; default = true; description = "Service discovery"; }; legacyauth = mkOption { + type = types.bool; default = true; description = "Legacy authentication. Only used by some old clients and bots"; }; version = mkOption { + type = types.bool; default = true; description = "Replies to server version requests"; }; uptime = mkOption { + type = types.bool; default = true; description = "Report how long server has been running"; }; time = mkOption { + type = types.bool; default = true; description = "Let others know the time here on this server"; }; ping = mkOption { + type = types.bool; default = true; description = "Replies to XMPP pings with pongs"; }; console = mkOption { + type = types.bool; default = false; description = "telnet to port 5582"; }; bosh = mkOption { + type = types.bool; default = false; description = "Enable BOSH clients, aka 'Jabber over HTTP'"; }; httpserver = mkOption { + type = types.bool; default = false; description = "Serve static files from a directory over HTTP"; }; websocket = mkOption { + type = types.bool; default = false; description = "Enable WebSocket support"; }; }; - createSSLOptsStr = o: - if o ? key && o ? cert then - ''ssl = { key = "${o.key}"; certificate = "${o.cert}"; };'' - else ""; + toLua = x: + if builtins.isString x then ''"${x}"'' + else if builtins.isBool x then toString x + else if builtins.isInt x then toString x + else throw "Invalid Lua value"; + + createSSLOptsStr = o: '' + ssl = { + key = "${o.key}"; + certificate = "${o.cert}"; + ${concatStringsSep "\n" (mapAttrsToList (name: value: "${name} = ${toLua value};") o.extraOptions)} + }; + ''; vHostOpts = { ... }: { @@ -114,18 +142,20 @@ let }; enabled = mkOption { + type = types.bool; default = false; description = "Whether to enable the virtual host"; }; ssl = mkOption { - description = "Paths to SSL files"; + type = types.nullOr (types.submodule sslOpts); default = null; - options = [ sslOpts ]; + description = "Paths to SSL files"; }; extraConfig = mkOption { - default = ''''; + type = types.lines; + default = ""; description = "Additional virtual host specific configuration"; }; @@ -144,11 +174,13 @@ in services.prosody = { enable = mkOption { + type = types.bool; default = false; description = "Whether to enable the prosody server"; }; allowRegistration = mkOption { + type = types.bool; default = false; description = "Allow account creation"; }; @@ -156,8 +188,9 @@ in modules = moduleOpts; extraModules = mkOption { - description = "Enable custom modules"; + type = types.listOf types.str; default = []; + description = "Enable custom modules"; }; virtualHosts = mkOption { @@ -183,20 +216,21 @@ in }; ssl = mkOption { - description = "Paths to SSL files"; + type = types.nullOr (types.submodule sslOpts); default = null; - options = [ sslOpts ]; + description = "Paths to SSL files"; }; admins = mkOption { - description = "List of administrators of the current host"; - example = [ "admin1@example.com" "admin2@example.com" ]; + type = types.listOf types.str; default = []; + example = [ "admin1@example.com" "admin2@example.com" ]; + description = "List of administrators of the current host"; }; extraConfig = mkOption { type = types.lines; - default = ''''; + default = ""; description = "Additional prosody configuration"; }; @@ -263,17 +297,17 @@ in }; systemd.services.prosody = { - description = "Prosody XMPP server"; after = [ "network-online.target" ]; wants = [ "network-online.target" ]; wantedBy = [ "multi-user.target" ]; + restartTriggers = [ config.environment.etc."prosody/prosody.cfg.lua".source ]; serviceConfig = { User = "prosody"; + Type = "forking"; PIDFile = "/var/lib/prosody/prosody.pid"; ExecStart = "${pkgs.prosody}/bin/prosodyctl start"; }; - }; }; diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix index f0fddcca766f..aa9c0fa1c09f 100644 --- a/nixos/modules/services/networking/ssh/sshd.nix +++ b/nixos/modules/services/networking/ssh/sshd.nix @@ -248,13 +248,10 @@ in let service = { description = "SSH Daemon"; - wantedBy = optional (!cfg.startWhenNeeded) "multi-user.target"; - + after = [ "network.target" ]; stopIfChanged = false; - path = [ cfgc.package pkgs.gawk ]; - environment.LD_LIBRARY_PATH = nssModulesPath; preStart = diff --git a/nixos/modules/services/scheduling/fcron.nix b/nixos/modules/services/scheduling/fcron.nix index ac589be57736..e3b6b638f5a7 100644 --- a/nixos/modules/services/scheduling/fcron.nix +++ b/nixos/modules/services/scheduling/fcron.nix @@ -90,16 +90,24 @@ in [ (allowdeny "allow" (cfg.allow)) (allowdeny "deny" cfg.deny) # see man 5 fcron.conf - { source = pkgs.writeText "fcron.conf" '' - fcrontabs = /var/spool/fcron - pidfile = /var/run/fcron.pid - fifofile = /var/run/fcron.fifo - fcronallow = /etc/fcron.allow - fcrondeny = /etc/fcron.deny - shell = /bin/sh - sendmail = /run/wrappers/bin/sendmail - editor = ${pkgs.vim}/bin/vim - ''; + { source = + let + isSendmailWrapped = + lib.hasAttr "sendmail" config.security.wrappers; + sendmailPath = + if isSendmailWrapped then "/run/wrappers/bin/sendmail" + else "${config.system.path}/bin/sendmail"; + in + pkgs.writeText "fcron.conf" '' + fcrontabs = /var/spool/fcron + pidfile = /var/run/fcron.pid + fifofile = /var/run/fcron.fifo + fcronallow = /etc/fcron.allow + fcrondeny = /etc/fcron.deny + shell = /bin/sh + sendmail = ${sendmailPath} + editor = ${pkgs.vim}/bin/vim + ''; target = "fcron.conf"; gid = config.ids.gids.fcron; mode = "0644"; diff --git a/nixos/modules/services/security/clamav.nix b/nixos/modules/services/security/clamav.nix index 7de2d121e76c..4161c61ed375 100644 --- a/nixos/modules/services/security/clamav.nix +++ b/nixos/modules/services/security/clamav.nix @@ -97,8 +97,8 @@ in systemd.services.clamav-daemon = optionalAttrs cfg.daemon.enable { description = "ClamAV daemon (clamd)"; - after = mkIf cfg.updater.enable [ "clamav-freshclam.service" ]; - requires = mkIf cfg.updater.enable [ "clamav-freshclam.service" ]; + after = optional cfg.updater.enable "clamav-freshclam.service"; + requires = optional cfg.updater.enable "clamav-freshclam.service"; wantedBy = [ "multi-user.target" ]; restartTriggers = [ clamdConfigFile ]; diff --git a/nixos/modules/services/security/tor.nix b/nixos/modules/services/security/tor.nix index bc79d9f2a590..fa4aeb22ae9d 100644 --- a/nixos/modules/services/security/tor.nix +++ b/nixos/modules/services/security/tor.nix @@ -9,6 +9,26 @@ let opt = name: value: optionalString (value != null) "${name} ${value}"; optint = name: value: optionalString (value != null && value != 0) "${name} ${toString value}"; + isolationOptions = { + type = types.listOf (types.enum [ + "IsolateClientAddr" + "IsolateSOCKSAuth" + "IsolateClientProtocol" + "IsolateDestPort" + "IsolateDestAddr" + ]); + default = []; + example = [ + "IsolateClientAddr" + "IsolateSOCKSAuth" + "IsolateClientProtocol" + "IsolateDestPort" + "IsolateDestAddr" + ]; + description = "Tor isolation options"; + }; + + torRc = '' User tor DataDirectory ${torDirectory} @@ -20,10 +40,20 @@ let ${optint "ControlPort" cfg.controlPort} '' # Client connection config - + optionalString cfg.client.enable '' - SOCKSPort ${cfg.client.socksListenAddress} IsolateDestAddr + + optionalString cfg.client.enable '' + SOCKSPort ${cfg.client.socksListenAddress} ${toString cfg.client.socksIsolationOptions} SOCKSPort ${cfg.client.socksListenAddressFaster} ${opt "SocksPolicy" cfg.client.socksPolicy} + + ${optionalString cfg.client.transparentProxy.enable '' + TransPort ${cfg.client.transparentProxy.listenAddress} ${toString cfg.client.transparentProxy.isolationOptions} + ''} + + ${optionalString cfg.client.dns.enable '' + DNSPort ${cfg.client.dns.listenAddress} ${toString cfg.client.dns.isolationOptions} + AutomapHostsOnResolve 1 + AutomapHostsSuffixes ${concatStringsSep "," cfg.client.dns.automapHostsSuffixes} + ''} '' # Relay config + optionalString cfg.relay.enable '' @@ -154,6 +184,55 @@ in ''; }; + socksIsolationOptions = mkOption (isolationOptions // { + default = ["IsolateDestAddr"]; + }); + + transparentProxy = { + enable = mkOption { + type = types.bool; + default = false; + description = "Whether to enable tor transaprent proxy"; + }; + + listenAddress = mkOption { + type = types.str; + default = "127.0.0.1:9040"; + example = "192.168.0.1:9040"; + description = '' + Bind transparent proxy to this address. + ''; + }; + + isolationOptions = mkOption isolationOptions; + }; + + dns = { + enable = mkOption { + type = types.bool; + default = false; + description = "Whether to enable tor dns resolver"; + }; + + listenAddress = mkOption { + type = types.str; + default = "127.0.0.1:9053"; + example = "192.168.0.1:9053"; + description = '' + Bind tor dns to this address. + ''; + }; + + isolationOptions = mkOption isolationOptions; + + automapHostsSuffixes = mkOption { + type = types.listOf types.str; + default = [".onion" ".exit"]; + example = [".onion"]; + description = "List of suffixes to use with automapHostsOnResolve"; + }; + }; + privoxy.enable = mkOption { type = types.bool; default = true; diff --git a/nixos/modules/services/security/usbguard.nix b/nixos/modules/services/security/usbguard.nix index 1f2c56a9efa1..4e685e633354 100644 --- a/nixos/modules/services/security/usbguard.nix +++ b/nixos/modules/services/security/usbguard.nix @@ -56,7 +56,7 @@ in { }; rules = mkOption { - type = types.nullOr types.str; + type = types.nullOr types.lines; default = null; example = '' allow with-interface equals { 08:*:* } diff --git a/nixos/modules/services/system/localtime.nix b/nixos/modules/services/system/localtime.nix new file mode 100644 index 000000000000..b9355bbb9441 --- /dev/null +++ b/nixos/modules/services/system/localtime.nix @@ -0,0 +1,60 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.localtime; +in { + options = { + services.localtime = { + enable = mkOption { + default = false; + description = '' + Enable <literal>localtime</literal>, simple daemon for keeping the system + timezone up-to-date based on the current location. It uses geoclue2 to + determine the current location and systemd-timedated to actually set + the timezone. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + services.geoclue2.enable = true; + + security.polkit.extraConfig = '' + polkit.addRule(function(action, subject) { + if (action.id == "org.freedesktop.timedate1.set-timezone" + && subject.user == "localtimed") { + return polkit.Result.YES; + } + }); + ''; + + users.users = [{ + name = "localtimed"; + description = "Taskserver user"; + }]; + + systemd.services.localtime = { + description = "localtime service"; + wantedBy = [ "multi-user.target" ]; + partOf = [ "geoclue.service "]; + + serviceConfig = { + Restart = "on-failure"; + # TODO: make it work with dbus + #DynamicUser = true; + Nice = 10; + User = "localtimed"; + PrivateTmp = "yes"; + PrivateDevices = true; + PrivateNetwork = "yes"; + NoNewPrivileges = "yes"; + ProtectSystem = "strict"; + ProtectHome = true; + ExecStart = "${pkgs.localtime}/bin/localtimed"; + }; + }; + }; +} diff --git a/nixos/modules/services/web-apps/tt-rss.nix b/nixos/modules/services/web-apps/tt-rss.nix index 76b0ee6da968..c784f4756d19 100644 --- a/nixos/modules/services/web-apps/tt-rss.nix +++ b/nixos/modules/services/web-apps/tt-rss.nix @@ -99,8 +99,8 @@ let user = mkOption { type = types.str; - default = "nginx"; - example = "nginx"; + default = "tt_rss"; + example = "tt_rss"; description = '' User account under which both the update daemon and the web-application run. ''; @@ -466,26 +466,28 @@ let ''; }; - services.nginx.virtualHosts = mkIf (cfg.virtualHost != null) { - "${cfg.virtualHost}" = { - root = "${cfg.root}"; - - locations."/" = { - index = "index.php"; - }; - - locations."~ \.php$" = { - extraConfig = '' - fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_pass unix:${phpfpmSocketName}; - fastcgi_index index.php; - fastcgi_param SCRIPT_FILENAME ${cfg.root}/$fastcgi_script_name; - ''; + services.nginx = { + enable = true; + # NOTE: No configuration is done if not using virtual host + virtualHosts = mkIf (cfg.virtualHost != null) { + "${cfg.virtualHost}" = { + root = "${cfg.root}"; + + locations."/" = { + index = "index.php"; + }; + + locations."~ \.php$" = { + extraConfig = '' + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass unix:${phpfpmSocketName}; + fastcgi_index index.php; + ''; + }; }; }; }; - systemd.services.tt-rss = let dbService = if cfg.database.type == "pgsql" then "postgresql.service" else "mysql.service"; in { @@ -496,7 +498,7 @@ let callSql = e: if cfg.database.type == "pgsql" then '' ${optionalString (cfg.database.password != null) "PGPASSWORD=${cfg.database.password}"} \ - ${pkgs.postgresql95}/bin/psql \ + ${pkgs.sudo}/bin/sudo -u ${cfg.user} ${config.services.postgresql.package}/bin/psql \ -U ${cfg.database.user} \ ${optionalString (cfg.database.host != null) "-h ${cfg.database.host} --port ${toString dbPort}"} \ -c '${e}' \ @@ -521,6 +523,14 @@ let '' + (optionalString (cfg.database.type == "pgsql") '' + ${optionalString (cfg.database.host == null && cfg.database.password == null) '' + if ! [ -e ${cfg.root}/.db-created ]; then + ${pkgs.sudo}/bin/sudo -u ${config.services.postgresql.superUser} ${config.services.postgresql.package}/bin/createuser ${cfg.database.user} + ${pkgs.sudo}/bin/sudo -u ${config.services.postgresql.superUser} ${config.services.postgresql.package}/bin/createdb -O ${cfg.database.user} ${cfg.database.name} + touch ${cfg.root}/.db-created + fi + ''} + exists=$(${callSql "select count(*) > 0 from pg_tables where tableowner = user"} \ | tail -n+3 | head -n-2 | sed -e 's/[ \n\t]*//') @@ -554,5 +564,28 @@ let requires = ["${dbService}"]; after = ["network.target" "${dbService}"]; }; + + services.mysql = optionalAttrs (cfg.database.type == "mysql") { + enable = true; + package = mkDefault pkgs.mysql; + ensureDatabases = [ cfg.database.name ]; + ensureUsers = [ + { + name = cfg.user; + ensurePermissions = { + "${cfg.database.name}.*" = "ALL PRIVILEGES"; + }; + } + ]; + }; + + services.postgresql = optionalAttrs (cfg.database.type == "pgsql") { + enable = mkDefault true; + }; + + users = optionalAttrs (cfg.user == "tt_rss") { + extraUsers.tt_rss.group = "tt_rss"; + extraGroups.tt_rss = {}; + }; }; } diff --git a/nixos/modules/services/web-servers/lighttpd/default.nix b/nixos/modules/services/web-servers/lighttpd/default.nix index 700b4469c565..d23e810dcc62 100644 --- a/nixos/modules/services/web-servers/lighttpd/default.nix +++ b/nixos/modules/services/web-servers/lighttpd/default.nix @@ -50,11 +50,14 @@ let "mod_geoip" "mod_magnet" "mod_mysql_vhost" + "mod_openssl" # since v1.4.46 "mod_scgi" "mod_setenv" "mod_trigger_b4_dl" "mod_uploadprogress" + "mod_vhostdb" # since v1.4.46 "mod_webdav" + "mod_wstunnel" # since v1.4.46 ]; maybeModuleString = moduleName: diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix index 97511aac9737..2951e63e863e 100644 --- a/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixos/modules/services/web-servers/nginx/default.nix @@ -167,7 +167,8 @@ let listenString = { addr, port, ssl, ... }: "listen ${addr}:${toString port} " - + optionalString ssl "ssl http2 " + + optionalString ssl "ssl " + + optionalString (ssl && vhost.http2) "http2 " + optionalString vhost.default "default_server " + ";"; diff --git a/nixos/modules/services/web-servers/nginx/vhost-options.nix b/nixos/modules/services/web-servers/nginx/vhost-options.nix index 801601aafd9d..29f08cc4f307 100644 --- a/nixos/modules/services/web-servers/nginx/vhost-options.nix +++ b/nixos/modules/services/web-servers/nginx/vhost-options.nix @@ -114,6 +114,20 @@ with lib; description = "Path to server SSL certificate key."; }; + http2 = mkOption { + type = types.bool; + default = true; + description = '' + Whether to enable HTTP 2. + Note that (as of writing) due to nginx's implementation, to disable + HTTP 2 you have to disable it on all vhosts that use a given + IP address / port. + If there is one server block configured to enable http2,then it is + enabled for all server blocks on this IP. + See https://stackoverflow.com/a/39466948/263061. + ''; + }; + root = mkOption { type = types.nullOr types.path; default = null; diff --git a/nixos/modules/services/web-servers/tomcat.nix b/nixos/modules/services/web-servers/tomcat.nix index 943415e08c64..0b2e5c0b69d9 100644 --- a/nixos/modules/services/web-servers/tomcat.nix +++ b/nixos/modules/services/web-servers/tomcat.nix @@ -29,7 +29,7 @@ in type = types.package; default = pkgs.tomcat85; defaultText = "pkgs.tomcat85"; - example = lib.literalExample "pkgs.tomcatUnstable"; + example = lib.literalExample "pkgs.tomcat9"; description = '' Which tomcat package to use. ''; diff --git a/nixos/modules/services/x11/desktop-managers/default.nix b/nixos/modules/services/x11/desktop-managers/default.nix index 39b27d4ceb61..4622c7b760f0 100644 --- a/nixos/modules/services/x11/desktop-managers/default.nix +++ b/nixos/modules/services/x11/desktop-managers/default.nix @@ -109,9 +109,5 @@ in }; - config = { - services.xserver.displayManager.session = cfg.session.list; - environment.systemPackages = - mkIf cfg.session.needBGPackages [ pkgs.feh ]; # xsetroot via xserver.enable - }; + config.services.xserver.displayManager.session = cfg.session.list; } diff --git a/nixos/modules/services/x11/desktop-managers/enlightenment.nix b/nixos/modules/services/x11/desktop-managers/enlightenment.nix index 8a523f0d8036..7f3dc0d7847b 100644 --- a/nixos/modules/services/x11/desktop-managers/enlightenment.nix +++ b/nixos/modules/services/x11/desktop-managers/enlightenment.nix @@ -47,7 +47,7 @@ in export GTK_DATA_PREFIX=${config.system.path} # find theme engines export GTK_PATH=${config.system.path}/lib/gtk-3.0:${config.system.path}/lib/gtk-2.0 - export XDG_MENU_PREFIX=enlightenment + export XDG_MENU_PREFIX=e- export GST_PLUGIN_PATH="${GST_PLUGIN_PATH}" diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix index d2c856fc9332..21d30df5b695 100644 --- a/nixos/modules/services/x11/desktop-managers/gnome3.nix +++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix @@ -136,7 +136,7 @@ in { # find theme engines export GTK_PATH=${config.system.path}/lib/gtk-3.0:${config.system.path}/lib/gtk-2.0 - export XDG_MENU_PREFIX=gnome + export XDG_MENU_PREFIX=gnome- ${concatMapStrings (p: '' if [ -d "${p}/share/gsettings-schemas/${p.name}" ]; then diff --git a/nixos/modules/services/x11/desktop-managers/mate.nix b/nixos/modules/services/x11/desktop-managers/mate.nix index ab8a0a48b483..814503ab0bc4 100644 --- a/nixos/modules/services/x11/desktop-managers/mate.nix +++ b/nixos/modules/services/x11/desktop-managers/mate.nix @@ -12,6 +12,17 @@ let in filter (x: !(builtins.elem (pkgName x) ysNames)) xs; + addToXDGDirs = p: '' + if [ -d "${p}/share/gsettings-schemas/${p.name}" ]; then + export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${p}/share/gsettings-schemas/${p.name} + fi + + if [ -d "${p}/lib/girepository-1.0" ]; then + export GI_TYPELIB_PATH=$GI_TYPELIB_PATH''${GI_TYPELIB_PATH:+:}${p}/lib/girepository-1.0 + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH''${LD_LIBRARY_PATH:+:}${p}/lib + fi + ''; + xcfg = config.services.xserver; cfg = xcfg.desktopManager.mate; @@ -20,10 +31,14 @@ in { options = { - services.xserver.desktopManager.mate.enable = mkOption { - type = types.bool; - default = false; - description = "Enable the MATE desktop environment"; + services.xserver.desktopManager.mate = { + enable = mkOption { + type = types.bool; + default = false; + description = "Enable the MATE desktop environment"; + }; + + debug = mkEnableOption "mate-session debug messages"; }; environment.mate.excludePackages = mkOption { @@ -47,15 +62,34 @@ in # Find theme engines export GTK_PATH=${config.system.path}/lib/gtk-3.0:${config.system.path}/lib/gtk-2.0 - export XDG_MENU_PREFIX=mate + export XDG_MENU_PREFIX=mate- # Find the mouse export XCURSOR_PATH=~/.icons:${config.system.path}/share/icons + # Let caja find extensions + export CAJA_EXTENSION_DIRS=$CAJA_EXTENSION_DIRS''${CAJA_EXTENSION_DIRS:+:}${config.system.path}/lib/caja/extensions-2.0 + + # Let caja extensions find gsettings schemas + ${concatMapStrings (p: '' + if [ -d "${p}/lib/caja/extensions-2.0" ]; then + ${addToXDGDirs p} + fi + '') + config.environment.systemPackages + } + + # Let mate-panel find applets + export MATE_PANEL_APPLETS_DIR=$MATE_PANEL_APPLETS_DIR''${MATE_PANEL_APPLETS_DIR:+:}${config.system.path}/share/mate-panel/applets + export MATE_PANEL_EXTRA_MODULES=$MATE_PANEL_EXTRA_MODULES''${MATE_PANEL_EXTRA_MODULES:+:}${config.system.path}/lib/mate-panel/applets + + # Add mate-control-center paths to some XDG variables because its schemas are needed by mate-settings-daemon, and mate-settings-daemon is a dependency for mate-control-center (that is, they are mutually recursive) + ${addToXDGDirs pkgs.mate.mate-control-center} + # Update user dirs as described in http://freedesktop.org/wiki/Software/xdg-user-dirs/ ${pkgs.xdg-user-dirs}/bin/xdg-user-dirs-update - ${pkgs.mate.mate-session-manager}/bin/mate-session & + ${pkgs.mate.mate-session-manager}/bin/mate-session ${optionalString cfg.debug "--debug"} & waitPID=$! ''; }; diff --git a/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixos/modules/services/x11/desktop-managers/plasma5.nix index bb4f4e868fea..17a2cde3a65d 100644 --- a/nixos/modules/services/x11/desktop-managers/plasma5.nix +++ b/nixos/modules/services/x11/desktop-managers/plasma5.nix @@ -25,8 +25,8 @@ in type = types.bool; default = true; description = '' - Enable support for Qt 4-based applications. Particularly, install the - Qt 4 version of the Breeze theme and a default backend for Phonon. + Enable support for Qt 4-based applications. Particularly, install a + default backend for Phonon. ''; }; @@ -142,11 +142,13 @@ in kde-gtk-config breeze-gtk + qtvirtualkeyboard + libsForQt56.phonon-backend-gstreamer libsForQt5.phonon-backend-gstreamer ] - ++ lib.optionals cfg.enableQt4Support [ breeze-qt4 pkgs.phonon-backend-gstreamer ] + ++ lib.optionals cfg.enableQt4Support [ pkgs.phonon-backend-gstreamer ] # Optional hardware support features ++ lib.optional config.hardware.bluetooth.enable bluedevil @@ -193,16 +195,6 @@ in theme = mkDefault "breeze"; }; - boot.plymouth = { - theme = mkDefault "breeze"; - themePackages = mkDefault [ - (pkgs.breeze-plymouth.override { - nixosBranding = true; - nixosVersion = config.system.nixosRelease; - }) - ]; - }; - security.pam.services.kde = { allowNullPassword = true; }; # Doing these one by one seems silly, but we currently lack a better diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix index 9c42dc8781b9..9d5d03638e04 100644 --- a/nixos/modules/services/x11/desktop-managers/xfce.nix +++ b/nixos/modules/services/x11/desktop-managers/xfce.nix @@ -3,15 +3,13 @@ with lib; let - xcfg = config.services.xserver; + pcfg = config.hardware.pulseaudio; cfg = xcfg.desktopManager.xfce; - in { options = { - services.xserver.desktopManager.xfce = { enable = mkOption { type = types.bool; @@ -96,8 +94,8 @@ in pkgs.xfce.xfce4icontheme pkgs.xfce.xfce4session pkgs.xfce.xfce4settings - pkgs.xfce.xfce4mixer - pkgs.xfce.xfce4volumed + (if pcfg.enable then pkgs.xfce.xfce4mixer_pulse else pkgs.xfce.xfce4mixer) + (if pcfg.enable then pkgs.xfce.xfce4volumed_pulse else pkgs.xfce.xfce4volumed) pkgs.xfce.xfce4-screenshooter pkgs.xfce.xfconf # This supplies some "abstract" icons such as @@ -124,6 +122,7 @@ in [ "/share/xfce4" "/share/themes" "/share/mime" "/share/desktop-directories" "/share/gtksourceview-2.0" ]; environment.variables.GIO_EXTRA_MODULES = [ "${pkgs.xfce.gvfs}/lib/gio/modules" ]; + environment.variables.GDK_PIXBUF_MODULE_FILE = "${pkgs.librsvg.out}/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"; # Enable helpful DBus services. services.udisks2.enable = true; diff --git a/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix b/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix index 1d5dcb2c7cbe..35b715b98fcd 100644 --- a/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix +++ b/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix @@ -45,6 +45,8 @@ let theme-name = ${cfg.theme.name} icon-theme-name = ${cfg.iconTheme.name} background = ${ldmcfg.background} + ${optionalString (cfg.clock-format != null) "clock-format = ${cfg.clock-format}"} + ${optionalString (cfg.indicators != null) "indicators = ${concatStringsSep ";" cfg.indicators}"} ${cfg.extraConfig} ''; @@ -104,6 +106,35 @@ in }; + clock-format = mkOption { + type = types.nullOr types.str; + default = null; + example = "%F"; + description = '' + Clock format string (as expected by strftime, e.g. "%H:%M") + to use with the lightdm gtk greeter panel. + + If set to null the default clock format is used. + ''; + }; + + indicators = mkOption { + type = types.nullOr (types.listOf types.str); + default = null; + example = [ "~host" "~spacer" "~clock" "~spacer" "~session" "~language" "~a11y" "~power" ]; + description = '' + List of allowed indicator modules to use for the lightdm gtk + greeter panel. + + Built-in indicators include "~a11y", "~language", "~session", + "~power", "~clock", "~host", "~spacer". Unity indicators can be + represented by short name (e.g. "sound", "power"), service file name, + or absolute path. + + If set to null the default indicators are used. + ''; + }; + extraConfig = mkOption { type = types.lines; default = ""; diff --git a/nixos/modules/services/x11/hardware/libinput.nix b/nixos/modules/services/x11/hardware/libinput.nix index 5aecdef812e6..d0a87f183b6f 100644 --- a/nixos/modules/services/x11/hardware/libinput.nix +++ b/nixos/modules/services/x11/hardware/libinput.nix @@ -170,7 +170,7 @@ in { disableWhileTyping = mkOption { type = types.bool; - default = true; + default = false; description = '' Disable input method while typing. diff --git a/nixos/modules/services/x11/window-managers/awesome.nix b/nixos/modules/services/x11/window-managers/awesome.nix index eb97449c6bd9..71eb02ec5954 100644 --- a/nixos/modules/services/x11/window-managers/awesome.nix +++ b/nixos/modules/services/x11/window-managers/awesome.nix @@ -6,7 +6,11 @@ let cfg = config.services.xserver.windowManager.awesome; awesome = cfg.package; - inherit (pkgs.luaPackages) getLuaPath getLuaCPath; + getLuaPath = lib : dir : "${lib}/${dir}/lua/${pkgs.luaPackages.lua.luaversion}"; + makeSearchPath = lib.concatMapStrings (path: + " --search " + (getLuaPath path "share") + + " --search " + (getLuaPath path "lib") + ); in { @@ -46,10 +50,7 @@ in { name = "awesome"; start = '' - export LUA_CPATH="${lib.concatStringsSep ";" (map getLuaCPath cfg.luaModules)}" - export LUA_PATH="${lib.concatStringsSep ";" (map getLuaPath cfg.luaModules)}" - - ${awesome}/bin/awesome & + ${awesome}/bin/awesome ${makeSearchPath cfg.luaModules} & waitPID=$! ''; }; diff --git a/nixos/modules/system/boot/grow-partition.nix b/nixos/modules/system/boot/grow-partition.nix new file mode 100644 index 000000000000..c4c6d82dc5c8 --- /dev/null +++ b/nixos/modules/system/boot/grow-partition.nix @@ -0,0 +1,43 @@ +# This module automatically grows the root partition. +# This allows an instance to be created with a bigger root filesystem +# than provided by the machine image. + +{ config, lib, pkgs, ... }: + +with lib; + +{ + + options = { + boot.growPartition = mkEnableOption "grow the root partition on boot"; + }; + + config = mkIf config.boot.growPartition { + + 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 + + substitute "${pkgs.cloud-utils}/bin/.growpart-wrapped" "$out/bin/growpart" \ + --replace "${pkgs.bash}/bin/sh" "/bin/sh" \ + --replace "awk" "gawk" \ + --replace "sed" "gnused" + + ln -s sed $out/bin/gnused + ''; + + boot.initrd.postDeviceCommands = '' + rootDevice="${config.fileSystems."/".device}" + if [ -e "$rootDevice" ]; then + rootDevice="$(readlink -f "$rootDevice")" + parentDevice="$(lsblk -npo PKNAME "$rootDevice")" + TMPDIR=/run sh $(type -P growpart) "$parentDevice" "''${rootDevice#$parentDevice}" + udevadm settle + fi + ''; + + }; + +} diff --git a/nixos/modules/system/boot/initrd-ssh.nix b/nixos/modules/system/boot/initrd-ssh.nix index d78775c27582..cdeff4845948 100644 --- a/nixos/modules/system/boot/initrd-ssh.nix +++ b/nixos/modules/system/boot/initrd-ssh.nix @@ -89,9 +89,6 @@ in config = mkIf (config.boot.initrd.network.enable && cfg.enable) { assertions = [ - { assertion = cfg.hostRSAKey != null || cfg.hostDSSKey != null || cfg.hostECDSAKey != null; - message = "You should specify at least one host key for initrd SSH"; - } { assertion = cfg.authorizedKeys != []; message = "You should specify at least one authorized key for initrd SSH"; } @@ -121,7 +118,7 @@ in echo ${escapeShellArg key} >> /root/.ssh/authorized_keys '') cfg.authorizedKeys)} - dropbear -s -j -k -E -m -p ${toString cfg.port} + dropbear -s -j -k -E -m -p ${toString cfg.port} ${optionalString (cfg.hostRSAKey == null && cfg.hostDSSKey == null && cfg.hostECDSAKey == null) "-R"} ''; boot.initrd.secrets = diff --git a/nixos/modules/system/boot/kernel.nix b/nixos/modules/system/boot/kernel.nix index 4db9631743e3..90074a1ba77b 100644 --- a/nixos/modules/system/boot/kernel.nix +++ b/nixos/modules/system/boot/kernel.nix @@ -197,7 +197,7 @@ in "mmc_block" # Support USB keyboards, in case the boot fails and we only have - # a USB keyboard. + # a USB keyboard, or for LUKS passphrase prompt. "uhci_hcd" "ehci_hcd" "ehci_pci" @@ -206,7 +206,7 @@ in "xhci_hcd" "xhci_pci" "usbhid" - "hid_generic" "hid_lenovo" "hid_apple" "hid_roccat" + "hid_generic" "hid_lenovo" "hid_apple" "hid_roccat" "hid_logitech_hidpp" # Misc. keyboard stuff. "pcips2" "atkbd" "i8042" diff --git a/nixos/modules/system/boot/luksroot.nix b/nixos/modules/system/boot/luksroot.nix index 06f004fb06ec..eefee5a479e7 100644 --- a/nixos/modules/system/boot/luksroot.nix +++ b/nixos/modules/system/boot/luksroot.nix @@ -227,6 +227,11 @@ in default = [ "aes" "aes_generic" "blowfish" "twofish" "serpent" "cbc" "xts" "lrw" "sha1" "sha256" "sha512" + + # workaround until https://marc.info/?l=linux-crypto-vger&m=148783562211457&w=4 is merged + # remove once 'modprobe --show-depends xts' shows ecb as a dependency + "ecb" + (if pkgs.stdenv.system == "x86_64-linux" then "aes_x86_64" else "aes_i586") ]; description = '' @@ -434,7 +439,9 @@ in ["firewire_ohci" "firewire_core" "firewire_sbp2"]; # Some modules that may be needed for mounting anything ciphered - boot.initrd.availableKernelModules = [ "dm_mod" "dm_crypt" "cryptd" ] ++ luks.cryptoModules; + # Also load input_leds to get caps lock light working (#12456) + boot.initrd.availableKernelModules = [ "dm_mod" "dm_crypt" "cryptd" "input_leds" ] + ++ luks.cryptoModules; # copy the cryptsetup binary and it's dependencies boot.initrd.extraUtilsCommands = '' diff --git a/nixos/modules/system/boot/plymouth.nix b/nixos/modules/system/boot/plymouth.nix index 4b0c498424b5..e78fdf1311d3 100644 --- a/nixos/modules/system/boot/plymouth.nix +++ b/nixos/modules/system/boot/plymouth.nix @@ -8,9 +8,14 @@ let cfg = config.boot.plymouth; + breezePlymouth = pkgs.breeze-plymouth.override { + nixosBranding = true; + nixosVersion = config.system.nixosRelease; + }; + themesEnv = pkgs.buildEnv { name = "plymouth-themes"; - paths = [ plymouth ] ++ cfg.themePackages; + paths = [ plymouth breezePlymouth ] ++ cfg.themePackages; }; configFile = pkgs.writeText "plymouthd.conf" '' @@ -38,7 +43,7 @@ in }; theme = mkOption { - default = "fade-in"; + default = "breeze"; type = types.str; description = '' Splash screen theme. diff --git a/nixos/modules/tasks/filesystems/btrfs.nix b/nixos/modules/tasks/filesystems/btrfs.nix index 8cfa1b6921d3..1384873b6631 100644 --- a/nixos/modules/tasks/filesystems/btrfs.nix +++ b/nixos/modules/tasks/filesystems/btrfs.nix @@ -1,35 +1,132 @@ -{ config, lib, pkgs, ... }: +{ config, lib, pkgs, utils, ... }: with lib; let inInitrd = any (fs: fs == "btrfs") config.boot.initrd.supportedFilesystems; + inSystem = any (fs: fs == "btrfs") config.boot.supportedFilesystems; + + cfgScrub = config.services.btrfs.autoScrub; + + enableAutoScrub = cfgScrub.enable; + enableBtrfs = inInitrd || inSystem || enableAutoScrub; in { - config = mkIf (any (fs: fs == "btrfs") config.boot.supportedFilesystems) { + options = { + # One could also do regular btrfs balances, but that shouldn't be necessary + # during normal usage and as long as the filesystems aren't filled near capacity + services.btrfs.autoScrub = { + enable = mkEnableOption "Enable regular btrfs scrub"; - system.fsPackages = [ pkgs.btrfs-progs ]; + fileSystems = mkOption { + type = types.listOf types.path; + example = [ "/" ]; + description = '' + List of paths to btrfs filesystems to regularily call <command>btrfs scrub</command> on. + Defaults to all mount points with btrfs filesystems. + If you mount a filesystem multiple times or additionally mount subvolumes, + you need to manually specify this list to avoid scrubbing multiple times. + ''; + }; - boot.initrd.kernelModules = mkIf inInitrd [ "btrfs" "crc32c" ]; + interval = mkOption { + default = "monthly"; + type = types.str; + example = "weekly"; + description = '' + Systemd calendar expression for when to scrub btrfs filesystems. + The recommended period is a month but could be less + (<citerefentry><refentrytitle>btrfs-scrub</refentrytitle> + <manvolnum>8</manvolnum></citerefentry>). + See + <citerefentry><refentrytitle>systemd.time</refentrytitle> + <manvolnum>7</manvolnum></citerefentry> + for more information on the syntax. + ''; + }; + + }; + }; - boot.initrd.extraUtilsCommands = mkIf inInitrd + config = mkMerge [ + (mkIf enableBtrfs { + system.fsPackages = [ pkgs.btrfs-progs ]; + + boot.initrd.kernelModules = mkIf inInitrd [ "btrfs" "crc32c" ]; + + boot.initrd.extraUtilsCommands = mkIf inInitrd '' copy_bin_and_libs ${pkgs.btrfs-progs}/bin/btrfs ln -sv btrfs $out/bin/btrfsck ln -sv btrfsck $out/bin/fsck.btrfs ''; - boot.initrd.extraUtilsCommandsTest = mkIf inInitrd + boot.initrd.extraUtilsCommandsTest = mkIf inInitrd '' $out/bin/btrfs --version ''; - boot.initrd.postDeviceCommands = mkIf inInitrd + boot.initrd.postDeviceCommands = mkIf inInitrd '' btrfs device scan ''; - }; + }) + + (mkIf enableAutoScrub { + assertions = [ + { + assertion = cfgScrub.enable -> (cfgScrub.fileSystems != []); + message = '' + If 'services.btrfs.autoScrub' is enabled, you need to have at least one + btrfs file system mounted via 'fileSystems' or specify a list manually + in 'services.btrfs.autoScrub.fileSystems'. + ''; + } + ]; + + # This will yield duplicated units if the user mounts a filesystem multiple times + # or additionally mounts subvolumes, but going the other way around via devices would + # yield duplicated units when a filesystem spans multiple devices. + # This way around seems like the more sensible default. + services.btrfs.autoScrub.fileSystems = mkDefault (mapAttrsToList (name: fs: fs.mountPoint) + (filterAttrs (name: fs: fs.fsType == "btrfs") config.fileSystems)); + + # TODO: Did not manage to do it via the usual btrfs-scrub@.timer/.service + # template units due to problems enabling the parameterized units, + # so settled with many units and templating via nix for now. + # https://github.com/NixOS/nixpkgs/pull/32496#discussion_r156527544 + systemd.timers = let + scrubTimer = fs: let + fs' = utils.escapeSystemdPath fs; + in nameValuePair "btrfs-scrub-${fs'}" { + description = "regular btrfs scrub timer on ${fs}"; + + wantedBy = [ "timers.target" ]; + timerConfig = { + OnCalendar = cfgScrub.interval; + AccuracySec = "1d"; + Persistent = true; + }; + }; + in listToAttrs (map scrubTimer cfgScrub.fileSystems); + + systemd.services = let + scrubService = fs: let + fs' = utils.escapeSystemdPath fs; + in nameValuePair "btrfs-scrub-${fs'}" { + description = "btrfs scrub on ${fs}"; + + serviceConfig = { + Type = "oneshot"; + Nice = 19; + IOSchedulingClass = "idle"; + ExecStart = "${pkgs.btrfs-progs}/bin/btrfs scrub start -B ${fs}"; + }; + }; + in listToAttrs (map scrubService cfgScrub.fileSystems); + }) + ]; } diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix index 7fee99115329..2c0a165887bd 100644 --- a/nixos/modules/tasks/filesystems/zfs.nix +++ b/nixos/modules/tasks/filesystems/zfs.nix @@ -268,7 +268,7 @@ in assertions = [ { assertion = config.networking.hostId != null; - message = "ZFS requires config.networking.hostId to be set"; + message = "ZFS requires networking.hostId to be set"; } { assertion = !cfgZfs.forceImportAll || cfgZfs.forceImportRoot; diff --git a/nixos/modules/testing/test-instrumentation.nix b/nixos/modules/testing/test-instrumentation.nix index 1d6c41406107..9b4136223c0f 100644 --- a/nixos/modules/testing/test-instrumentation.nix +++ b/nixos/modules/testing/test-instrumentation.nix @@ -128,7 +128,7 @@ in # Make it easy to log in as root when running the test interactively. users.extraUsers.root.initialHashedPassword = mkOverride 150 ""; - services.xserver.displayManager.logToJournal = true; + services.xserver.displayManager.job.logToJournal = true; }; } diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix index 6cb9e07ae820..f74c42a777f5 100644 --- a/nixos/modules/virtualisation/amazon-image.nix +++ b/nixos/modules/virtualisation/amazon-image.nix @@ -11,7 +11,7 @@ with lib; let cfg = config.ec2; in { - imports = [ ../profiles/headless.nix ./ec2-data.nix ./grow-partition.nix ./amazon-init.nix ]; + imports = [ ../profiles/headless.nix ./ec2-data.nix ./amazon-init.nix ]; config = { @@ -21,7 +21,7 @@ let cfg = config.ec2; in } ]; - virtualisation.growPartition = cfg.hvm; + boot.growPartition = cfg.hvm; fileSystems."/" = { device = "/dev/disk/by-label/nixos"; diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix index e68bfd860601..4038454b2d2f 100644 --- a/nixos/modules/virtualisation/containers.nix +++ b/nixos/modules/virtualisation/containers.nix @@ -726,6 +726,11 @@ in networking.dhcpcd.denyInterfaces = [ "ve-*" "vb-*" ]; + services.udev.extraRules = optionalString config.networking.networkmanager.enable '' + # Don't manage interfaces created by nixos-container. + ENV{INTERFACE}=="v[eb]-*", ENV{NM_UNMANAGED}="1" + ''; + environment.systemPackages = [ pkgs.nixos-container ]; }); } diff --git a/nixos/modules/virtualisation/ec2-amis.nix b/nixos/modules/virtualisation/ec2-amis.nix index 14826b6272f7..01512911a057 100644 --- a/nixos/modules/virtualisation/ec2-amis.nix +++ b/nixos/modules/virtualisation/ec2-amis.nix @@ -223,21 +223,22 @@ let self = { "17.03".us-west-2.hvm-ebs = "ami-a93daac9"; "17.03".us-west-2.hvm-s3 = "ami-5139ae31"; - # 17.09.1483.d0f0657ca0 - "17.09".eu-west-1.hvm-ebs = "ami-cf33e7b6"; - "17.09".eu-west-2.hvm-ebs = "ami-7d061419"; - "17.09".eu-central-1.hvm-ebs = "ami-7548fa1a"; - "17.09".us-east-1.hvm-ebs = "ami-6f669d15"; - "17.09".us-east-2.hvm-ebs = "ami-cbe1ccae"; - "17.09".us-west-1.hvm-ebs = "ami-9d95a5fd"; - "17.09".us-west-2.hvm-ebs = "ami-d3956fab"; - "17.09".ca-central-1.hvm-ebs = "ami-ee4ef78a"; - "17.09".ap-southeast-1.hvm-ebs = "ami-1dfc807e"; - "17.09".ap-southeast-2.hvm-ebs = "ami-dcb350be"; - "17.09".ap-northeast-1.hvm-ebs = "ami-00ec3d66"; - "17.09".ap-northeast-2.hvm-ebs = "ami-1107dd7f"; - "17.09".sa-east-1.hvm-ebs = "ami-0377086f"; - "17.09".ap-south-1.hvm-ebs = "ami-4a064625"; + # 17.09.2681.59661f21be6 + "17.09".eu-west-1.hvm-ebs = "ami-a30192da"; + "17.09".eu-west-2.hvm-ebs = "ami-295a414d"; + "17.09".eu-west-3.hvm-ebs = "ami-8c0eb9f1"; + "17.09".eu-central-1.hvm-ebs = "ami-266cfe49"; + "17.09".us-east-1.hvm-ebs = "ami-40bee63a"; + "17.09".us-east-2.hvm-ebs = "ami-9d84aff8"; + "17.09".us-west-1.hvm-ebs = "ami-d14142b1"; + "17.09".us-west-2.hvm-ebs = "ami-3eb40346"; + "17.09".ca-central-1.hvm-ebs = "ami-ca8207ae"; + "17.09".ap-southeast-1.hvm-ebs = "ami-84bccff8"; + "17.09".ap-southeast-2.hvm-ebs = "ami-0dc5386f"; + "17.09".ap-northeast-1.hvm-ebs = "ami-89b921ef"; + "17.09".ap-northeast-2.hvm-ebs = "ami-179b3b79"; + "17.09".sa-east-1.hvm-ebs = "ami-4762202b"; + "17.09".ap-south-1.hvm-ebs = "ami-4e376021"; latest = self."17.09"; }; in self diff --git a/nixos/modules/virtualisation/google-compute-image.nix b/nixos/modules/virtualisation/google-compute-image.nix index e3b3e6a5f4ab..75717e08ab2a 100644 --- a/nixos/modules/virtualisation/google-compute-image.nix +++ b/nixos/modules/virtualisation/google-compute-image.nix @@ -6,7 +6,7 @@ let gce = pkgs.google-compute-engine; in { - imports = [ ../profiles/headless.nix ../profiles/qemu-guest.nix ./grow-partition.nix ]; + imports = [ ../profiles/headless.nix ../profiles/qemu-guest.nix ]; system.build.googleComputeImage = import ../../lib/make-disk-image.nix { name = "google-compute-image"; @@ -29,6 +29,7 @@ in autoResize = true; }; + boot.growPartition = true; boot.kernelParams = [ "console=ttyS0" "panic=1" "boot.panic_on_fail" ]; boot.initrd.kernelModules = [ "virtio_scsi" ]; boot.kernelModules = [ "virtio_pci" "virtio_net" ]; diff --git a/nixos/modules/virtualisation/grow-partition.nix b/nixos/modules/virtualisation/grow-partition.nix index 2cb932d208f0..444c0bc1630e 100644 --- a/nixos/modules/virtualisation/grow-partition.nix +++ b/nixos/modules/virtualisation/grow-partition.nix @@ -1,48 +1,3 @@ -# This module automatically grows the root partition on virtual machines. -# This allows an instance to be created with a bigger root filesystem -# than provided by the machine image. - -{ config, lib, pkgs, ... }: - -with lib; - -{ - - options = { - - virtualisation.growPartition = mkOption { - type = types.bool; - default = true; - }; - - }; - - config = mkIf config.virtualisation.growPartition { - - 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 - - substitute "${pkgs.cloud-utils}/bin/.growpart-wrapped" "$out/bin/growpart" \ - --replace "${pkgs.bash}/bin/sh" "/bin/sh" \ - --replace "awk" "gawk" \ - --replace "sed" "gnused" - - ln -s sed $out/bin/gnused - ''; - - boot.initrd.postDeviceCommands = '' - rootDevice="${config.fileSystems."/".device}" - if [ -e "$rootDevice" ]; then - rootDevice="$(readlink -f "$rootDevice")" - parentDevice="$(lsblk -npo PKNAME "$rootDevice")" - TMPDIR=/run sh $(type -P growpart) "$parentDevice" "''${rootDevice#$parentDevice}" - udevadm settle - fi - ''; - - }; - -} +# This profile is deprecated, use boot.growPartition directly. +builtins.trace "the profile <nixos/modules/virtualisation/grow-partition.nix> is deprecated, use boot.growPartition instead" +{ } diff --git a/nixos/modules/virtualisation/hyperv-guest.nix b/nixos/modules/virtualisation/hyperv-guest.nix new file mode 100644 index 000000000000..ecd2a8117710 --- /dev/null +++ b/nixos/modules/virtualisation/hyperv-guest.nix @@ -0,0 +1,37 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.virtualisation.hypervGuest; + +in { + options = { + virtualisation.hypervGuest = { + enable = mkEnableOption "Hyper-V Guest Support"; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ config.boot.kernelPackages.hyperv-daemons.bin ]; + + security.rngd.enable = false; + + # enable hotadding memory + services.udev.packages = lib.singleton (pkgs.writeTextFile { + name = "hyperv-memory-hotadd-udev-rules"; + destination = "/etc/udev/rules.d/99-hyperv-memory-hotadd.rules"; + text = '' + ACTION="add", SUBSYSTEM=="memory", ATTR{state}="online" + ''; + }); + + systemd = { + packages = [ config.boot.kernelPackages.hyperv-daemons.lib ]; + + targets.hyperv-daemons = { + wantedBy = [ "multi-user.target" ]; + }; + }; + }; +} diff --git a/nixos/modules/virtualisation/libvirtd.nix b/nixos/modules/virtualisation/libvirtd.nix index 8aa7ad8e3911..64465ae18522 100644 --- a/nixos/modules/virtualisation/libvirtd.nix +++ b/nixos/modules/virtualisation/libvirtd.nix @@ -37,11 +37,13 @@ in { ''; }; - virtualisation.libvirtd.enableKVM = mkOption { - type = types.bool; - default = true; + virtualisation.libvirtd.qemuPackage = mkOption { + type = types.package; + default = pkgs.qemu; description = '' - This option enables support for QEMU/KVM in libvirtd. + Qemu package to use with libvirt. + `pkgs.qemu` can emulate alien architectures (e.g. aarch64 on x86) + `pkgs.qemu_kvm` saves disk space allowing to emulate only host architectures. ''; }; @@ -102,7 +104,7 @@ in { config = mkIf cfg.enable { - environment.systemPackages = with pkgs; [ libvirt netcat-openbsd qemu_kvm ]; + environment.systemPackages = with pkgs; [ libvirt netcat-openbsd cfg.qemuPackage ]; boot.kernelModules = [ "tun" ]; @@ -154,9 +156,9 @@ in { # stable (not GC'able as in /nix/store) paths for using in <emulator> section of xml configs mkdir -p /run/libvirt/nix-emulators - ln -s --force ${pkgs.libvirt}/libexec/libvirt_lxc /run/libvirt/nix-emulators/ - ${optionalString pkgs.stdenv.isAarch64 "ln -s --force ${pkgs.qemu}/bin/qemu-system-aarch64 /run/libvirt/nix-emulators/"} - ${optionalString cfg.enableKVM "ln -s --force ${pkgs.qemu_kvm}/bin/qemu-kvm /run/libvirt/nix-emulators/"} + for emulator in ${pkgs.libvirt}/libexec/libvirt_lxc ${cfg.qemuPackage}/bin/qemu-kvm ${cfg.qemuPackage}/bin/qemu-system-*; do + ln -s --force "$emulator" /run/libvirt/nix-emulators/ + done ${optionalString cfg.qemuOvmf '' mkdir -p /run/libvirt/nix-ovmf diff --git a/nixos/modules/virtualisation/lxcfs.nix b/nixos/modules/virtualisation/lxcfs.nix index 48462dc66da8..b2457403463a 100644 --- a/nixos/modules/virtualisation/lxcfs.nix +++ b/nixos/modules/virtualisation/lxcfs.nix @@ -28,13 +28,9 @@ in { ###### implementation config = mkIf cfg.enable { - services.cgmanager.enable = true; - systemd.services.lxcfs = { description = "FUSE filesystem for LXC"; wantedBy = [ "multi-user.target" ]; - requires = [ "cgmanager.service" ]; - after = [ "cgmanager.service" ]; before = [ "lxc.service" ]; restartIfChanged = false; serviceConfig = { diff --git a/nixos/modules/virtualisation/nova-config.nix b/nixos/modules/virtualisation/nova-config.nix index c865cf451e40..c1d2a314daf2 100644 --- a/nixos/modules/virtualisation/nova-config.nix +++ b/nixos/modules/virtualisation/nova-config.nix @@ -6,7 +6,6 @@ with lib; imports = [ ../profiles/qemu-guest.nix ../profiles/headless.nix - ./grow-partition.nix ]; config = { @@ -15,8 +14,7 @@ with lib; autoResize = true; }; - virtualisation.growPartition = true; - + boot.growPartition = true; boot.kernelParams = [ "console=ttyS0" ]; boot.loader.grub.device = "/dev/vda"; boot.loader.timeout = 0; diff --git a/nixos/modules/virtualisation/nova.nix b/nixos/modules/virtualisation/nova.nix deleted file mode 100644 index c2837d0e2e24..000000000000 --- a/nixos/modules/virtualisation/nova.nix +++ /dev/null @@ -1,174 +0,0 @@ -# Module for Nova, a.k.a. OpenStack Compute. - -{ config, lib, pkgs, ... }: - -with lib; - -let - - cfg = config.virtualisation.nova; - - nova = pkgs.nova; - - novaConf = pkgs.writeText "nova.conf" - '' - --nodaemon - --verbose - ${cfg.extraConfig} - ''; - -in - -{ - - ###### interface - - options = { - - virtualisation.nova.enableSingleNode = - mkOption { - default = false; - description = - '' - This option enables Nova, also known as OpenStack Compute, - a cloud computing system, as a single-machine - installation. That is, all of Nova's components are - enabled on this machine, using SQLite as Nova's database. - This is useful for evaluating and experimenting with Nova. - However, for a real cloud computing environment, you'll - want to enable some of Nova's services on other machines, - and use a database such as MySQL. - ''; - }; - - virtualisation.nova.extraConfig = - mkOption { - default = ""; - description = - '' - Additional text appended to <filename>nova.conf</filename>, - the main Nova configuration file. - ''; - }; - - }; - - - ###### implementation - - config = mkIf cfg.enableSingleNode { - - environment.systemPackages = [ nova pkgs.euca2ools pkgs.novaclient ]; - - environment.etc = - [ { source = novaConf; - target = "nova/nova.conf"; - } - ]; - - # Nova requires libvirtd and RabbitMQ. - virtualisation.libvirtd.enable = true; - services.rabbitmq.enable = true; - - # `qemu-nbd' required the `nbd' kernel module. - boot.kernelModules = [ "nbd" ]; - - system.activationScripts.nova = - '' - mkdir -m 755 -p /var/lib/nova - mkdir -m 755 -p /var/lib/nova/networks - mkdir -m 700 -p /var/lib/nova/instances - mkdir -m 700 -p /var/lib/nova/keys - - # Allow the CA certificate generation script (called by - # nova-api) to work. - mkdir -m 700 -p /var/lib/nova/CA /var/lib/nova/CA/private - - # Initialise the SQLite database. - ${nova}/bin/nova-manage db sync - ''; - - # `nova-api' receives and executes external client requests from - # tools such as euca2ools. It listens on port 8773 (XML) and 8774 - # (JSON). - jobs.nova_api = - { name = "nova-api"; - - description = "Nova API service"; - - startOn = "ip-up"; - - # `openssl' is required to generate the CA. `openssh' is - # required to generate key pairs. - path = [ pkgs.openssl config.programs.ssh.package pkgs.bash ]; - - respawn = false; - - exec = "${nova}/bin/nova-api --flagfile=${novaConf} --api_paste_config=${nova}/etc/nova/api-paste.ini"; - }; - - # `nova-objectstore' is a simple image server. Useful if you're - # not running the OpenStack Imaging Service (Swift). It serves - # images placed in /var/lib/nova/images/. - jobs.nova_objectstore = - { name = "nova-objectstore"; - - description = "Nova Simple Object Store Service"; - - startOn = "ip-up"; - - preStart = - '' - mkdir -m 700 -p /var/lib/nova/images - ''; - - exec = "${nova}/bin/nova-objectstore --flagfile=${novaConf}"; - }; - - # `nova-scheduler' schedules VM execution requests. - jobs.nova_scheduler = - { name = "nova-scheduler"; - - description = "Nova Scheduler Service"; - - startOn = "ip-up"; - - exec = "${nova}/bin/nova-scheduler --flagfile=${novaConf}"; - }; - - # `nova-compute' starts and manages virtual machines. - jobs.nova_compute = - { name = "nova-compute"; - - description = "Nova Compute Service"; - - startOn = "ip-up"; - - path = - [ pkgs.sudo pkgs.vlan pkgs.nettools pkgs.iptables pkgs.qemu_kvm - pkgs.e2fsprogs pkgs.utillinux pkgs.multipath-tools pkgs.iproute - pkgs.bridge-utils - ]; - - exec = "${nova}/bin/nova-compute --flagfile=${novaConf}"; - }; - - # `nova-network' manages networks and allocates IP addresses. - jobs.nova_network = - { name = "nova-network"; - - description = "Nova Network Service"; - - startOn = "ip-up"; - - path = - [ pkgs.sudo pkgs.vlan pkgs.dnsmasq pkgs.nettools pkgs.iptables - pkgs.iproute pkgs.bridge-utils pkgs.radvd - ]; - - exec = "${nova}/bin/nova-network --flagfile=${novaConf}"; - }; - - }; - -} diff --git a/nixos/modules/virtualisation/openstack/common.nix b/nixos/modules/virtualisation/openstack/common.nix deleted file mode 100644 index 2feb0a873951..000000000000 --- a/nixos/modules/virtualisation/openstack/common.nix +++ /dev/null @@ -1,84 +0,0 @@ -{ lib }: - -with lib; - -rec { - # A shell script string helper to get the value of a secret at - # runtime. - getSecret = secretOption: - if secretOption.storage == "fromFile" - then ''$(cat ${secretOption.value})'' - else ''${secretOption.value}''; - - - # A shell script string help to replace at runtime in a file the - # pattern of a secret by its value. - replaceSecret = secretOption: filename: '' - sed -i "s/${secretOption.pattern}/${getSecret secretOption}/g" ${filename} - ''; - - # This generates an option that can be used to declare secrets which - # can be stored in the nix store, or not. A pattern is written in - # the nix store to represent the secret. The pattern can - # then be overwritten with the value of the secret at runtime. - mkSecretOption = {name, description ? ""}: - mkOption { - description = description; - type = types.submodule ({ - options = { - pattern = mkOption { - type = types.str; - default = "##${name}##"; - description = "The pattern that represent the secret."; - }; - storage = mkOption { - type = types.enum [ "fromNixStore" "fromFile" ]; - description = '' - Choose the way the password is provisionned. If - fromNixStore is used, the value is the password and it is - written in the nix store. If fromFile is used, the value - is a path from where the password will be read at - runtime. This is generally used with <link - xlink:href="https://nixos.org/nixops/manual/#opt-deployment.keys"> - deployment keys</link> of Nixops. - '';}; - value = mkOption { - type = types.str; - description = '' - If the storage is fromNixStore, the value is the password itself, - otherwise it is a path to the file that contains the password. - ''; - }; - };}); - }; - - databaseOption = name: { - host = mkOption { - type = types.str; - default = "localhost"; - description = '' - Host of the database. - ''; - }; - - name = mkOption { - type = types.str; - default = name; - description = '' - Name of the existing database. - ''; - }; - - user = mkOption { - type = types.str; - default = name; - description = '' - The database user. The user must exist and has access to - the specified database. - ''; - }; - password = mkSecretOption { - name = name + "MysqlPassword"; - description = "The database user's password";}; - }; -} diff --git a/nixos/modules/virtualisation/openstack/glance.nix b/nixos/modules/virtualisation/openstack/glance.nix deleted file mode 100644 index 7862409a65ec..000000000000 --- a/nixos/modules/virtualisation/openstack/glance.nix +++ /dev/null @@ -1,245 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; with import ./common.nix {inherit lib;}; - -let - cfg = config.virtualisation.openstack.glance; - commonConf = '' - [database] - connection = "mysql://${cfg.database.user}:${cfg.database.password.pattern}@${cfg.database.host}/${cfg.database.name}" - notification_driver = noop - - [keystone_authtoken] - auth_url = ${cfg.authUrl} - auth_plugin = password - project_name = service - project_domain_id = default - user_domain_id = default - username = ${cfg.serviceUsername} - password = ${cfg.servicePassword.pattern} - - [glance_store] - default_store = file - filesystem_store_datadir = /var/lib/glance/images/ - ''; - glanceApiConfTpl = pkgs.writeText "glance-api.conf" '' - ${commonConf} - - [paste_deploy] - flavor = keystone - config_file = ${cfg.package}/etc/glance-api-paste.ini - ''; - glanceRegistryConfTpl = pkgs.writeText "glance-registry.conf" '' - ${commonConf} - - [paste_deploy] - config_file = ${cfg.package}/etc/glance-registry-paste.ini - ''; - glanceApiConf = "/var/lib/glance/glance-api.conf"; - glanceRegistryConf = "/var/lib/glance/glance-registry.conf"; - -in { - options.virtualisation.openstack.glance = { - package = mkOption { - type = types.package; - default = pkgs.glance; - defaultText = "pkgs.glance"; - description = '' - Glance package to use. - ''; - }; - - enable = mkOption { - default = false; - type = types.bool; - description = '' - This option enables Glance as a single-machine - installation. That is, all of Glance's components are - enabled on this machine. This is useful for evaluating and - experimenting with Glance. Note we are currently not - providing any configurations for a multi-node setup. - ''; - }; - - authUrl = mkOption { - type = types.str; - default = http://localhost:5000; - description = '' - Complete public Identity (Keystone) API endpoint. Note this is - unversionned. - ''; - }; - - serviceUsername = mkOption { - type = types.str; - default = "glance"; - description = '' - The Glance service username. This user is created if bootstrap - is enable, otherwise it has to be manually created before - starting this service. - ''; - }; - - servicePassword = mkSecretOption { - name = "glanceAdminPassword"; - description = '' - The Glance service user's password. - ''; - }; - - database = databaseOption "glance"; - - bootstrap = { - enable = mkOption { - default = false; - type = types.bool; - description = '' - Bootstrap the Glance service by creating the service tenant, - an admin account and a public endpoint. This option provides - a ready-to-use glance service. This is only done at the - first Glance execution by the systemd post start section. - The keystone admin account is used to create required - Keystone resource for the Glance service. - - <note><para> This option is a helper for setting up - development or testing environments.</para></note> - ''; - }; - - endpointPublic = mkOption { - type = types.str; - default = "http://localhost:9292"; - description = '' - The public image endpoint. The link <link - xlink:href="http://docs.openstack.org/liberty/install-guide-rdo/keystone-services.html"> - create endpoint</link> provides more informations - about that. - ''; - }; - - keystoneAdminUsername = mkOption { - type = types.str; - default = "admin"; - description = '' - The keystone admin user name used to create the Glance account. - ''; - }; - - keystoneAdminPassword = mkSecretOption { - name = "keystoneAdminPassword"; - description = '' - The keystone admin user's password. - ''; - }; - - keystoneAdminTenant = mkOption { - type = types.str; - default = "admin"; - description = '' - The keystone admin tenant used to create the Glance account. - ''; - }; - keystoneAuthUrl = mkOption { - type = types.str; - default = "http://localhost:5000/v2.0"; - description = '' - The keystone auth url used to create the Glance account. - ''; - }; - }; - }; - - config = mkIf cfg.enable { - users.extraUsers = [{ - name = "glance"; - group = "glance"; - uid = config.ids.gids.glance; - - }]; - users.extraGroups = [{ - name = "glance"; - gid = config.ids.gids.glance; - }]; - - systemd.services.glance-registry = { - description = "OpenStack Glance Registry Daemon"; - after = [ "network.target"]; - path = [ pkgs.curl pkgs.pythonPackages.keystoneclient pkgs.gawk ]; - wantedBy = [ "multi-user.target" ]; - preStart = '' - mkdir -m 775 -p /var/lib/glance/{images,scrubber,image_cache} - chown glance:glance /var/lib/glance/{images,scrubber,image_cache} - - # Secret file managment - cp ${glanceRegistryConfTpl} ${glanceRegistryConf}; - chown glance:glance ${glanceRegistryConf}; - chmod 640 ${glanceRegistryConf} - ${replaceSecret cfg.database.password glanceRegistryConf} - ${replaceSecret cfg.servicePassword glanceRegistryConf} - - cp ${glanceApiConfTpl} ${glanceApiConf}; - chown glance:glance ${glanceApiConf}; - chmod 640 ${glanceApiConf} - ${replaceSecret cfg.database.password glanceApiConf} - ${replaceSecret cfg.servicePassword glanceApiConf} - - # Initialise the database - ${cfg.package}/bin/glance-manage --config-file=${glanceApiConf} --config-file=${glanceRegistryConf} db_sync - ''; - postStart = '' - set -eu - export OS_AUTH_URL=${cfg.bootstrap.keystoneAuthUrl} - export OS_USERNAME=${cfg.bootstrap.keystoneAdminUsername} - export OS_PASSWORD=${getSecret cfg.bootstrap.keystoneAdminPassword} - export OS_TENANT_NAME=${cfg.bootstrap.keystoneAdminTenant} - - # Wait until the keystone is available for use - count=0 - while ! keystone user-get ${cfg.bootstrap.keystoneAdminUsername} > /dev/null - do - if [ $count -eq 30 ] - then - echo "Tried 30 times, giving up..." - exit 1 - fi - - echo "Keystone not yet started. Waiting for 1 second..." - count=$((count++)) - sleep 1 - done - - # If the service glance doesn't exist, we consider glance is - # not initialized - if ! keystone service-get glance - then - keystone service-create --type image --name glance - ID=$(keystone service-get glance | awk '/ id / { print $4 }') - keystone endpoint-create --region RegionOne --service $ID --internalurl http://localhost:9292 --adminurl http://localhost:9292 --publicurl ${cfg.bootstrap.endpointPublic} - - keystone user-create --name ${cfg.serviceUsername} --tenant service --pass ${getSecret cfg.servicePassword} - keystone user-role-add --tenant service --user ${cfg.serviceUsername} --role admin - fi - ''; - serviceConfig = { - PermissionsStartOnly = true; # preStart must be run as root - TimeoutStartSec = "600"; # 10min for initial db migrations - User = "glance"; - Group = "glance"; - ExecStart = "${cfg.package}/bin/glance-registry --config-file=${glanceRegistryConf}"; - }; - }; - systemd.services.glance-api = { - description = "OpenStack Glance API Daemon"; - after = [ "glance-registry.service" "network.target"]; - requires = [ "glance-registry.service" "network.target"]; - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - PermissionsStartOnly = true; # preStart must be run as root - User = "glance"; - Group = "glance"; - ExecStart = "${cfg.package}/bin/glance-api --config-file=${glanceApiConf}"; - }; - }; - }; - -} diff --git a/nixos/modules/virtualisation/openstack/keystone.nix b/nixos/modules/virtualisation/openstack/keystone.nix deleted file mode 100644 index e32c5a4cae1b..000000000000 --- a/nixos/modules/virtualisation/openstack/keystone.nix +++ /dev/null @@ -1,220 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; with import ./common.nix {inherit lib;}; - -let - cfg = config.virtualisation.openstack.keystone; - keystoneConfTpl = pkgs.writeText "keystone.conf" '' - [DEFAULT] - admin_token = ${cfg.adminToken.pattern} - policy_file=${cfg.package}/etc/policy.json - - [database] - - connection = "mysql://${cfg.database.user}:${cfg.database.password.pattern}@${cfg.database.host}/${cfg.database.name}" - - [paste_deploy] - config_file = ${cfg.package}/etc/keystone-paste.ini - - ${cfg.extraConfig} - ''; - keystoneConf = "/var/lib/keystone/keystone.conf"; - -in { - options.virtualisation.openstack.keystone = { - package = mkOption { - type = types.package; - example = literalExample "pkgs.keystone"; - description = '' - Keystone package to use. - ''; - }; - - enable = mkOption { - default = false; - type = types.bool; - description = '' - Enable Keystone, the OpenStack Identity Service - ''; - }; - - extraConfig = mkOption { - default = ""; - type = types.lines; - description = '' - Additional text appended to <filename>keystone.conf</filename>, - the main Keystone configuration file. - ''; - }; - - adminToken = mkSecretOption { - name = "adminToken"; - description = '' - This is the admin token used to boostrap keystone, - ie. to provision first resources. - ''; - }; - - bootstrap = { - enable = mkOption { - default = false; - type = types.bool; - description = '' - Bootstrap the Keystone service by creating the service - tenant, an admin account and a public endpoint. This options - provides a ready-to-use admin account. This is only done at - the first Keystone execution by the systemd post start. - - Note this option is a helper for setting up development or - testing environments. - ''; - }; - - endpointPublic = mkOption { - type = types.str; - default = "http://localhost:5000/v2.0"; - description = '' - The public identity endpoint. The link <link - xlink:href="http://docs.openstack.org/liberty/install-guide-rdo/keystone-services.html"> - create keystone endpoint</link> provides more informations - about that. - ''; - }; - - adminUsername = mkOption { - type = types.str; - default = "admin"; - description = '' - A keystone admin username. - ''; - }; - - adminPassword = mkSecretOption { - name = "keystoneAdminPassword"; - description = '' - The keystone admin user's password. - ''; - }; - - adminTenant = mkOption { - type = types.str; - default = "admin"; - description = '' - A keystone admin tenant name. - ''; - }; - }; - - database = { - host = mkOption { - type = types.str; - default = "localhost"; - description = '' - Host of the database. - ''; - }; - - name = mkOption { - type = types.str; - default = "keystone"; - description = '' - Name of the existing database. - ''; - }; - - user = mkOption { - type = types.str; - default = "keystone"; - description = '' - The database user. The user must exist and has access to - the specified database. - ''; - }; - password = mkSecretOption { - name = "mysqlPassword"; - description = "The database user's password";}; - }; - }; - - config = mkIf cfg.enable { - # Note: when changing the default, make it conditional on - # ‘system.stateVersion’ to maintain compatibility with existing - # systems! - virtualisation.openstack.keystone.package = mkDefault pkgs.keystone; - - users.extraUsers = [{ - name = "keystone"; - group = "keystone"; - uid = config.ids.uids.keystone; - }]; - users.extraGroups = [{ - name = "keystone"; - gid = config.ids.gids.keystone; - }]; - - systemd.services.keystone-all = { - description = "OpenStack Keystone Daemon"; - after = [ "network.target"]; - path = [ cfg.package pkgs.mysql pkgs.curl pkgs.pythonPackages.keystoneclient pkgs.gawk ]; - wantedBy = [ "multi-user.target" ]; - preStart = '' - mkdir -m 755 -p /var/lib/keystone - - cp ${keystoneConfTpl} ${keystoneConf}; - chown keystone:keystone ${keystoneConf}; - chmod 640 ${keystoneConf} - - ${replaceSecret cfg.database.password keystoneConf} - ${replaceSecret cfg.adminToken keystoneConf} - - # Initialise the database - ${cfg.package}/bin/keystone-manage --config-file=${keystoneConf} db_sync - # Set up the keystone's PKI infrastructure - ${cfg.package}/bin/keystone-manage --config-file=${keystoneConf} pki_setup --keystone-user keystone --keystone-group keystone - ''; - postStart = optionalString cfg.bootstrap.enable '' - set -eu - # Wait until the keystone is available for use - count=0 - while ! curl --fail -s http://localhost:35357/v2.0 > /dev/null - do - if [ $count -eq 30 ] - then - echo "Tried 30 times, giving up..." - exit 1 - fi - - echo "Keystone not yet started. Waiting for 1 second..." - count=$((count++)) - sleep 1 - done - - # We use the service token to create a first admin user - export OS_SERVICE_ENDPOINT=http://localhost:35357/v2.0 - export OS_SERVICE_TOKEN=${getSecret cfg.adminToken} - - # If the tenant service doesn't exist, we consider - # keystone is not initialized - if ! keystone tenant-get service - then - keystone tenant-create --name service - keystone tenant-create --name ${cfg.bootstrap.adminTenant} - keystone user-create --name ${cfg.bootstrap.adminUsername} --tenant ${cfg.bootstrap.adminTenant} --pass ${getSecret cfg.bootstrap.adminPassword} - keystone role-create --name admin - keystone role-create --name Member - keystone user-role-add --tenant ${cfg.bootstrap.adminTenant} --user ${cfg.bootstrap.adminUsername} --role admin - keystone service-create --type identity --name keystone - ID=$(keystone service-get keystone | awk '/ id / { print $4 }') - keystone endpoint-create --region RegionOne --service $ID --publicurl ${cfg.bootstrap.endpointPublic} --adminurl http://localhost:35357/v2.0 --internalurl http://localhost:5000/v2.0 - fi - ''; - serviceConfig = { - PermissionsStartOnly = true; # preStart must be run as root - TimeoutStartSec = "600"; # 10min for initial db migrations - User = "keystone"; - Group = "keystone"; - ExecStart = "${cfg.package}/bin/keystone-all --config-file=${keystoneConf}"; - }; - }; - }; -} diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix index 770e5fb848a9..26f7945a4eda 100644 --- a/nixos/modules/virtualisation/qemu-vm.nix +++ b/nixos/modules/virtualisation/qemu-vm.nix @@ -18,7 +18,7 @@ let "i686-linux" = "${qemu}/bin/qemu-kvm"; "x86_64-linux" = "${qemu}/bin/qemu-kvm -cpu kvm64"; "armv7l-linux" = "${qemu}/bin/qemu-system-arm -enable-kvm -machine virt -cpu host"; - "aarch64-linux" = "${qemu}/bin/qemu-system-aarch64 -enable-kvm -machine virt -cpu host"; + "aarch64-linux" = "${qemu}/bin/qemu-system-aarch64 -enable-kvm -machine virt,gic-version=host -cpu host"; }.${pkgs.stdenv.system}; # FIXME: figure out a common place for this instead of copy pasting diff --git a/nixos/modules/virtualisation/virtualbox-image.nix b/nixos/modules/virtualisation/virtualbox-image.nix index d68b3bb73904..00381c426d23 100644 --- a/nixos/modules/virtualisation/virtualbox-image.nix +++ b/nixos/modules/virtualisation/virtualbox-image.nix @@ -8,8 +8,6 @@ let in { - imports = [ ./grow-partition.nix ]; - options = { virtualbox = { baseImageSize = mkOption { @@ -23,7 +21,6 @@ in { }; config = { - system.build.virtualBoxOVA = import ../../lib/make-disk-image.nix { name = "nixos-ova-${config.system.nixosLabel}-${pkgs.stdenv.system}"; @@ -71,6 +68,7 @@ in { autoResize = true; }; + boot.growPartition = true; boot.loader.grub.device = "/dev/sda"; virtualisation.virtualbox.guest.enable = true; diff --git a/nixos/release.nix b/nixos/release.nix index bb6a73eb68ec..3dd670c30bad 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -1,6 +1,6 @@ { nixpkgs ? { outPath = ./..; revCount = 56789; shortRev = "gfedcba"; } , stableBranch ? false -, supportedSystems ? [ "x86_64-linux" ] +, supportedSystems ? [ "x86_64-linux" "aarch64-linux" ] }: with import ../lib; @@ -89,6 +89,27 @@ let }); }).config)); + makeNetboot = config: + let + config_evaled = import lib/eval-config.nix config; + build = config_evaled.config.system.build; + kernelTarget = config_evaled.pkgs.stdenv.platform.kernelTarget; + in + pkgs.symlinkJoin { + name="netboot"; + paths=[ + build.netbootRamdisk + build.kernel + build.netbootIpxeScript + ]; + postBuild = '' + mkdir -p $out/nix-support + echo "file ${kernelTarget} $out/${kernelTarget}" >> $out/nix-support/hydra-build-products + echo "file initrd $out/initrd" >> $out/nix-support/hydra-build-products + echo "file ipxe $out/netboot.ipxe" >> $out/nix-support/hydra-build-products + ''; + }; + in rec { @@ -103,28 +124,22 @@ in rec { # Build the initial ramdisk so Hydra can keep track of its size over time. initialRamdisk = buildFromConfig ({ pkgs, ... }: { }) (config: config.system.build.initialRamdisk); - netboot.x86_64-linux = let build = (import lib/eval-config.nix { + netboot = { + x86_64-linux = makeNetboot { system = "x86_64-linux"; modules = [ ./modules/installer/netboot/netboot-minimal.nix versionModule ]; - }).config.system.build; - in - pkgs.symlinkJoin { - name="netboot"; - paths=[ - build.netbootRamdisk - build.kernel - build.netbootIpxeScript - ]; - postBuild = '' - mkdir -p $out/nix-support - echo "file bzImage $out/bzImage" >> $out/nix-support/hydra-build-products - echo "file initrd $out/initrd" >> $out/nix-support/hydra-build-products - echo "file ipxe $out/netboot.ipxe" >> $out/nix-support/hydra-build-products - ''; }; + } // (optionalAttrs (elem "aarch64-linux" supportedSystems) { + aarch64-linux = makeNetboot { + system = "aarch64-linux"; + modules = [ + ./modules/installer/netboot/netboot-minimal.nix + versionModule + ]; + };}); iso_minimal = forAllSystems (system: makeIso { module = ./modules/installer/cd-dvd/installation-cd-minimal.nix; @@ -217,6 +232,7 @@ in rec { tests.atd = callTest tests/atd.nix {}; tests.acme = callTest tests/acme.nix {}; tests.avahi = callTest tests/avahi.nix {}; + tests.beegfs = callTest tests/beegfs.nix {}; tests.bittorrent = callTest tests/bittorrent.nix {}; tests.blivet = callTest tests/blivet.nix {}; tests.boot = callSubTests tests/boot.nix {}; @@ -252,7 +268,6 @@ in rec { tests.fleet = hydraJob (import tests/fleet.nix { system = "x86_64-linux"; }); #tests.gitlab = callTest tests/gitlab.nix {}; tests.gitolite = callTest tests/gitolite.nix {}; - tests.glance = callTest tests/glance.nix {}; tests.gocd-agent = callTest tests/gocd-agent.nix {}; tests.gocd-server = callTest tests/gocd-server.nix {}; tests.gnome3 = callTest tests/gnome3.nix {}; @@ -279,7 +294,6 @@ in rec { tests.kernel-copperhead = callTest tests/kernel-copperhead.nix {}; tests.kernel-latest = callTest tests/kernel-latest.nix {}; tests.kernel-lts = callTest tests/kernel-lts.nix {}; - tests.keystone = callTest tests/keystone.nix {}; tests.kubernetes = hydraJob (import tests/kubernetes/default.nix { system = "x86_64-linux"; }); tests.latestKernel.login = callTest tests/login.nix { latestKernel = true; }; tests.ldap = callTest tests/ldap.nix {}; @@ -333,10 +347,12 @@ in rec { tests.slim = callTest tests/slim.nix {}; tests.smokeping = callTest tests/smokeping.nix {}; tests.snapper = callTest tests/snapper.nix {}; + tests.statsd = callTest tests/statsd.nix {}; tests.switchTest = callTest tests/switch-test.nix {}; tests.taskserver = callTest tests/taskserver.nix {}; tests.tomcat = callTest tests/tomcat.nix {}; tests.udisks2 = callTest tests/udisks2.nix {}; + tests.vault = callTest tests/vault.nix {}; tests.virtualbox = callSubTests tests/virtualbox.nix { system = "x86_64-linux"; }; tests.wordpress = callTest tests/wordpress.nix {}; tests.xfce = callTest tests/xfce.nix {}; diff --git a/nixos/tests/beegfs.nix b/nixos/tests/beegfs.nix new file mode 100644 index 000000000000..433910feafe3 --- /dev/null +++ b/nixos/tests/beegfs.nix @@ -0,0 +1,115 @@ +import ./make-test.nix ({ pkgs, ... } : + +let + connAuthFile="beegfs/auth-def.key"; + + client = { config, pkgs, lib, ... } : { + networking.firewall.enable = false; + services.beegfsEnable = true; + services.beegfs.default = { + mgmtdHost = "mgmt"; + connAuthFile = "/etc/${connAuthFile}"; + client = { + mount = false; + enable = true; + }; + }; + + fileSystems = pkgs.lib.mkVMOverride # FIXME: this should be creatd by the module + [ { mountPoint = "/beegfs"; + device = "default"; + fsType = "beegfs"; + options = [ "cfgFile=/etc/beegfs/client-default.conf" "_netdev" ]; + } + ]; + + environment.etc."${connAuthFile}" = { + enable = true; + text = "ThisIsALousySecret"; + mode = "0600"; + }; + }; + + + server = service : { config, pkgs, lib, ... } : { + networking.firewall.enable = false; + boot.initrd.postDeviceCommands = '' + ${pkgs.e2fsprogs}/bin/mkfs.ext4 -L data /dev/vdb + ''; + + virtualisation.emptyDiskImages = [ 4096 ]; + + fileSystems = pkgs.lib.mkVMOverride + [ { mountPoint = "/data"; + device = "/dev/disk/by-label/data"; + fsType = "ext4"; + } + ]; + + environment.systemPackages = with pkgs; [ beegfs ]; + environment.etc."${connAuthFile}" = { + enable = true; + text = "ThisIsALousySecret"; + mode = "0600"; + }; + + services.beegfsEnable = true; + services.beegfs.default = { + mgmtdHost = "mgmt"; + connAuthFile = "/etc/${connAuthFile}"; + "${service}" = { + enable = true; + storeDir = "/data"; + }; + }; + }; + +in +{ + name = "beegfs"; + + nodes = { + meta = server "meta"; + mgmt = server "mgmtd"; + storage1 = server "storage"; + storage2 = server "storage"; + client1 = client; + client2 = client; + }; + + testScript = '' + # Initalize the data directories + $mgmt->waitForUnit("default.target"); + $mgmt->succeed("beegfs-setup-mgmtd -C -f -p /data"); + $mgmt->succeed("systemctl start beegfs-mgmtd-default"); + + $meta->waitForUnit("default.target"); + $meta->succeed("beegfs-setup-meta -C -f -s 1 -p /data"); + $meta->succeed("systemctl start beegfs-meta-default"); + + $storage1->waitForUnit("default.target"); + $storage1->succeed("beegfs-setup-storage -C -f -s 1 -i 1 -p /data"); + $storage1->succeed("systemctl start beegfs-storage-default"); + + $storage2->waitForUnit("default.target"); + $storage2->succeed("beegfs-setup-storage -C -f -s 2 -i 2 -p /data"); + $storage2->succeed("systemctl start beegfs-storage-default"); + + # + + # Basic test + $client1->waitForUnit("beegfs.mount"); + $client1->succeed("beegfs-check-servers-default"); + $client1->succeed("echo test > /beegfs/test"); + $client2->waitForUnit("beegfs.mount"); + $client2->succeed("test -e /beegfs/test"); + $client2->succeed("cat /beegfs/test | grep test"); + + # test raid0/stripping + $client1->succeed("dd if=/dev/urandom bs=1M count=10 of=/beegfs/striped"); + $client2->succeed("cat /beegfs/striped > /dev/null"); + + # check if fs is still healthy + $client1->succeed("beegfs-fsck-default --checkfs"); + ''; +}) diff --git a/nixos/tests/glance.nix b/nixos/tests/glance.nix deleted file mode 100644 index 992b77227a4b..000000000000 --- a/nixos/tests/glance.nix +++ /dev/null @@ -1,77 +0,0 @@ -{ system ? builtins.currentSystem }: - -with import ../lib/testing.nix { inherit system; }; -with pkgs.lib; - -let - glanceMysqlPassword = "glanceMysqlPassword"; - glanceAdminPassword = "glanceAdminPassword"; - - createDb = pkgs.writeText "db-provisionning.sql" '' - create database keystone; - GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' IDENTIFIED BY 'keystone'; - GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' IDENTIFIED BY 'keystone'; - - create database glance; - GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'localhost' IDENTIFIED BY '${glanceMysqlPassword}'; - GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'%' IDENTIFIED BY '${glanceMysqlPassword}'; - ''; - - image = - (import ../lib/eval-config.nix { - inherit system; - modules = [ ../../nixos/modules/virtualisation/nova-image.nix ]; - }).config.system.build.novaImage; - - # The admin keystone account - adminOpenstackCmd = "OS_TENANT_NAME=admin OS_USERNAME=admin OS_PASSWORD=keystone OS_AUTH_URL=http://localhost:5000/v3 OS_IDENTITY_API_VERSION=3 openstack"; - -in makeTest { - meta = with pkgs.stdenv.lib.maintainers; { - maintainers = [ lewo ]; - }; - machine = - { config, pkgs, ... }: - { - services.mysql.enable = true; - services.mysql.package = pkgs.mysql; - services.mysql.initialScript = createDb; - - virtualisation = { - openstack.keystone = { - enable = true; - database.password = { value = "keystone"; storage = "fromNixStore"; }; - adminToken = { value = "adminToken"; storage = "fromNixStore"; }; - bootstrap.enable = true; - bootstrap.adminPassword = { value = "keystone"; storage = "fromNixStore"; }; - }; - - openstack.glance = { - enable = true; - database.password = { value = glanceMysqlPassword; storage = "fromNixStore"; }; - servicePassword = { value = glanceAdminPassword; storage = "fromNixStore"; }; - - bootstrap = { - enable = true; - keystoneAdminPassword = { value = "keystone"; storage = "fromNixStore"; }; - }; - }; - - memorySize = 2096; - diskSize = 4 * 1024; - }; - - environment.systemPackages = with pkgs.pythonPackages; with pkgs; [ - openstackclient - ]; - }; - - testScript = - '' - $machine->waitForUnit("glance-api.service"); - - # Since Glance api can take time to start, we retry until success - $machine->waitUntilSucceeds("${adminOpenstackCmd} image create nixos --file ${image}/nixos.img --disk-format qcow2 --container-format bare --public"); - $machine->succeed("${adminOpenstackCmd} image list") =~ /nixos/ or die; - ''; -} diff --git a/nixos/tests/jenkins.nix b/nixos/tests/jenkins.nix index a9833058f378..ed55b2ff5871 100644 --- a/nixos/tests/jenkins.nix +++ b/nixos/tests/jenkins.nix @@ -36,6 +36,9 @@ import ./make-test.nix ({ pkgs, ...} : { startAll; $master->waitForUnit("jenkins"); + + $master->mustSucceed("curl http://localhost:8080 | grep 'Authentication required'"); + print $master->execute("sudo -u jenkins groups"); $master->mustSucceed("sudo -u jenkins groups | grep jenkins | grep users"); @@ -44,4 +47,4 @@ import ./make-test.nix ({ pkgs, ...} : { $slave->mustFail("systemctl is-enabled jenkins.service"); ''; -}) \ No newline at end of file +}) diff --git a/nixos/tests/keystone.nix b/nixos/tests/keystone.nix deleted file mode 100644 index 358e352f776f..000000000000 --- a/nixos/tests/keystone.nix +++ /dev/null @@ -1,82 +0,0 @@ -{ system ? builtins.currentSystem }: - -with import ../lib/testing.nix { inherit system; }; -with pkgs.lib; - -let - keystoneMysqlPassword = "keystoneMysqlPassword"; - keystoneMysqlPasswordFile = "/var/run/keystoneMysqlPassword"; - keystoneAdminPassword = "keystoneAdminPassword"; - - createKeystoneDb = pkgs.writeText "create-keystone-db.sql" '' - create database keystone; - GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' IDENTIFIED BY '${keystoneMysqlPassword}'; - GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' IDENTIFIED BY '${keystoneMysqlPassword}'; - ''; - # The admin keystone account - adminOpenstackCmd = "OS_TENANT_NAME=admin OS_USERNAME=admin OS_PASSWORD=${keystoneAdminPassword} OS_AUTH_URL=http://localhost:5000/v3 OS_IDENTITY_API_VERSION=3 openstack"; - # The created demo keystone account - demoOpenstackCmd = "OS_TENANT_NAME=demo OS_USERNAME=demo OS_PASSWORD=demo OS_AUTH_URL=http://localhost:5000/v3 OS_IDENTITY_API_VERSION=3 openstack"; - -in makeTest { - meta = with pkgs.stdenv.lib.maintainers; { - maintainers = [ lewo ]; - }; - machine = - { config, pkgs, ... }: - { - # This is to simulate nixops deployment process. - # https://nixos.org/nixops/manual/#opt-deployment.keys - boot.postBootCommands = "echo ${keystoneMysqlPassword} > ${keystoneMysqlPasswordFile}"; - - services.mysql.enable = true; - services.mysql.initialScript = createKeystoneDb; - - virtualisation = { - - openstack.keystone = { - enable = true; - # Check if we can get the secret from a file - database.password = { - value = keystoneMysqlPasswordFile; - storage = "fromFile"; - }; - adminToken = { - value = "adminToken"; - storage = "fromNixStore"; - }; - - bootstrap.enable = true; - # Check if we can get the secret from the store - bootstrap.adminPassword = { - value = keystoneAdminPassword; - storage = "fromNixStore"; - }; - }; - - memorySize = 2096; - diskSize = 4 * 1024; - }; - - environment.systemPackages = with pkgs.pythonPackages; with pkgs; [ - openstackclient - ]; - }; - - testScript = - '' - $machine->waitForUnit("keystone-all.service"); - - # Verify that admin ccount is working - $machine->succeed("${adminOpenstackCmd} token issue"); - - # Try to create a new user - $machine->succeed("${adminOpenstackCmd} project create --domain default --description 'Demo Project' demo"); - $machine->succeed("${adminOpenstackCmd} user create --domain default --password demo demo"); - $machine->succeed("${adminOpenstackCmd} role create user"); - $machine->succeed("${adminOpenstackCmd} role add --project demo --user demo user"); - - # Verify this new account is working - $machine->succeed("${demoOpenstackCmd} token issue"); - ''; -} diff --git a/nixos/tests/printing.nix b/nixos/tests/printing.nix index e44e5bf11d33..2d3ecaf94cfa 100644 --- a/nixos/tests/printing.nix +++ b/nixos/tests/printing.nix @@ -39,7 +39,7 @@ import ./make-test.nix ({pkgs, ... }: { $client->waitForUnit("cups.service"); $client->sleep(10); # wait until cups is fully initialized $client->succeed("lpstat -r") =~ /scheduler is running/ or die; - $client->succeed("lpstat -H") =~ "/var/run/cups/cups.sock" or die; + $client->succeed("lpstat -H") =~ "localhost:631" or die; $client->succeed("curl --fail http://localhost:631/"); $client->succeed("curl --fail http://server:631/"); $server->fail("curl --fail --connect-timeout 2 http://client:631/"); diff --git a/nixos/tests/radicale.nix b/nixos/tests/radicale.nix index f694fc75ef77..8ac0639c6a8c 100644 --- a/nixos/tests/radicale.nix +++ b/nixos/tests/radicale.nix @@ -20,7 +20,7 @@ let ''; }; # WARNING: DON'T DO THIS IN PRODUCTION! - # This puts secrets (albeit hashed) directly into the Nix store for ease of testing. + # This puts unhashed secrets directly into the Nix store for ease of testing. environment.etc."radicale/htpasswd".source = pkgs.runCommand "htpasswd" {} '' ${pkgs.apacheHttpd}/bin/htpasswd -bcB "$out" ${user} ${password} ''; diff --git a/nixos/tests/statsd.nix b/nixos/tests/statsd.nix new file mode 100644 index 000000000000..d6bbc3901630 --- /dev/null +++ b/nixos/tests/statsd.nix @@ -0,0 +1,40 @@ +import ./make-test.nix ({ pkgs, lib }: + +with lib; + +{ + name = "statsd"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ ma27 ]; + }; + + nodes.statsd1 = { + services.statsd.enable = true; + services.statsd.backends = [ "statsd-influxdb-backend" "console" ]; + services.statsd.extraConfig = '' + influxdb: { + username: "root", + password: "root", + database: "statsd" + } + ''; + + services.influxdb.enable = true; + + systemd.services.influx-init = { + description = "Setup Influx Test Base"; + after = [ "influxdb.service" ]; + before = [ "statsd.service" ]; + + script = '' + echo "CREATE DATABASE statsd" | ${pkgs.influxdb}/bin/influx + ''; + }; + }; + + testScript = '' + $statsd1->start(); + $statsd1->waitForUnit("statsd.service"); + $statsd1->succeed("nc -z 127.0.0.1 8126"); + ''; +}) diff --git a/nixos/tests/vault.nix b/nixos/tests/vault.nix new file mode 100644 index 000000000000..2c08d06f286b --- /dev/null +++ b/nixos/tests/vault.nix @@ -0,0 +1,23 @@ +import ./make-test.nix ({ pkgs, ... }: +{ + name = "vault"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ lnl7 ]; + }; + machine = { config, pkgs, ... }: { + environment.systemPackages = [ pkgs.vault ]; + environment.variables.VAULT_ADDR = "http://127.0.0.1:8200"; + services.vault.enable = true; + }; + + testScript = + '' + startAll; + + $machine->waitForUnit('multi-user.target'); + $machine->waitForUnit('vault.service'); + $machine->waitForOpenPort(8200); + $machine->succeed('vault init'); + $machine->succeed('vault status | grep "Sealed: true"'); + ''; +}) diff --git a/nixos/tests/virtualbox.nix b/nixos/tests/virtualbox.nix index c519d7dae8be..5574293ba377 100644 --- a/nixos/tests/virtualbox.nix +++ b/nixos/tests/virtualbox.nix @@ -109,9 +109,6 @@ let } '' ${pkgs.parted}/sbin/parted --script /dev/vda mklabel msdos ${pkgs.parted}/sbin/parted --script /dev/vda -- mkpart primary ext2 1M -1s - . /sys/class/block/vda1/uevent - mknod /dev/vda1 b $MAJOR $MINOR - ${pkgs.e2fsprogs}/sbin/mkfs.ext4 /dev/vda1 ${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda1 mkdir /mnt |