diff options
Diffstat (limited to 'nixos')
143 files changed, 3930 insertions, 928 deletions
diff --git a/nixos/doc/manual/administration/cleaning-store.xml b/nixos/doc/manual/administration/cleaning-store.xml index 41dc65795b68..4cf62947f528 100644 --- a/nixos/doc/manual/administration/cleaning-store.xml +++ b/nixos/doc/manual/administration/cleaning-store.xml @@ -21,7 +21,7 @@ Alternatively, you can use a systemd unit that does the same in the background: <screen> -$ systemctl start nix-gc.service +# systemctl start nix-gc.service </screen> You can tell NixOS in <filename>configuration.nix</filename> to run @@ -59,4 +59,4 @@ $ nix-store --optimise Since this command needs to read the entire Nix store, it can take quite a while to finish.</para> -</chapter> \ No newline at end of file +</chapter> diff --git a/nixos/doc/manual/administration/container-networking.xml b/nixos/doc/manual/administration/container-networking.xml index adea3e69840d..1b1576d3babe 100644 --- a/nixos/doc/manual/administration/container-networking.xml +++ b/nixos/doc/manual/administration/container-networking.xml @@ -13,7 +13,7 @@ create</literal>, it gets it own private IPv4 address in the range address as follows: <screen> -$ nixos-container show-ip foo +# nixos-container show-ip foo 10.233.4.2 $ ping -c1 10.233.4.2 @@ -47,4 +47,4 @@ where <literal>eth0</literal> should be replaced with the desired external interface. Note that <literal>ve-+</literal> is a wildcard that matches all container interfaces.</para> -</section> \ No newline at end of file +</section> diff --git a/nixos/doc/manual/administration/imperative-containers.xml b/nixos/doc/manual/administration/imperative-containers.xml index 6131d4e04ea8..3a52658436ac 100644 --- a/nixos/doc/manual/administration/imperative-containers.xml +++ b/nixos/doc/manual/administration/imperative-containers.xml @@ -11,7 +11,7 @@ identifier <literal>foo</literal> as follows: <screen> -$ nixos-container create foo +# nixos-container create foo </screen> This creates the container’s root directory in @@ -25,7 +25,7 @@ line. For instance, to create a container that has <literal>root</literal>: <screen> -$ nixos-container create foo --config 'services.openssh.enable = true; \ +# nixos-container create foo --config 'services.openssh.enable = true; \ users.extraUsers.root.openssh.authorizedKeys.keys = ["ssh-dss AAAAB3N…"];' </screen> @@ -35,7 +35,7 @@ $ nixos-container create foo --config 'services.openssh.enable = true; \ run: <screen> -$ nixos-container start foo +# nixos-container start foo </screen> This command will return as soon as the container has booted and has @@ -46,7 +46,7 @@ Thus, if something went wrong, you can get status info using <command>systemctl</command>: <screen> -$ systemctl status container@foo +# systemctl status container@foo </screen> </para> @@ -55,7 +55,7 @@ $ systemctl status container@foo root using the <command>root-login</command> operation: <screen> -$ nixos-container root-login foo +# nixos-container root-login foo [root@foo:~]# </screen> @@ -65,7 +65,7 @@ authentication). You can also get a regular login prompt using the the host: <screen> -$ nixos-container login foo +# nixos-container login foo foo login: alice Password: *** </screen> @@ -74,7 +74,7 @@ With <command>nixos-container run</command>, you can execute arbitrary commands in the container: <screen> -$ nixos-container run foo -- uname -a +# nixos-container run foo -- uname -a Linux foo 3.4.82 #1-NixOS SMP Thu Mar 20 14:44:05 UTC 2014 x86_64 GNU/Linux </screen> @@ -86,17 +86,17 @@ container. First, on the host, you can edit and run <screen> -$ nixos-container update foo +# nixos-container update foo </screen> This will build and activate the new configuration. You can also specify a new configuration on the command line: <screen> -$ nixos-container update foo --config 'services.httpd.enable = true; \ +# nixos-container update foo --config 'services.httpd.enable = true; \ services.httpd.adminAddr = "foo@example.org";' -$ curl http://$(nixos-container show-ip foo)/ +# curl http://$(nixos-container show-ip foo)/ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">… </screen> @@ -116,9 +116,9 @@ start</literal>, respectively, or by using destroy a container, including its file system, do <screen> -$ nixos-container destroy foo +# nixos-container destroy foo </screen> </para> -</section> \ No newline at end of file +</section> diff --git a/nixos/doc/manual/administration/maintenance-mode.xml b/nixos/doc/manual/administration/maintenance-mode.xml index 15c1f902da79..17a1609e5579 100644 --- a/nixos/doc/manual/administration/maintenance-mode.xml +++ b/nixos/doc/manual/administration/maintenance-mode.xml @@ -9,10 +9,10 @@ <para>You can enter rescue mode by running: <screen> -$ systemctl rescue</screen> +# systemctl rescue</screen> This will eventually give you a single-user root shell. Systemd will stop (almost) all system services. To get out of maintenance mode, just exit from the rescue shell.</para> -</section> \ No newline at end of file +</section> diff --git a/nixos/doc/manual/administration/network-problems.xml b/nixos/doc/manual/administration/network-problems.xml index 3af9cc59742f..91f9eb4e22c6 100644 --- a/nixos/doc/manual/administration/network-problems.xml +++ b/nixos/doc/manual/administration/network-problems.xml @@ -18,14 +18,14 @@ You can disable the use of the binary cache by adding <option>--option use-binary-caches false</option>, e.g. <screen> -$ nixos-rebuild switch --option use-binary-caches false +# nixos-rebuild switch --option use-binary-caches false </screen> If you have an alternative binary cache at your disposal, you can use it instead: <screen> -$ nixos-rebuild switch --option binary-caches http://my-cache.example.org/ +# nixos-rebuild switch --option binary-caches http://my-cache.example.org/ </screen> </para> diff --git a/nixos/doc/manual/administration/rebooting.xml b/nixos/doc/manual/administration/rebooting.xml index d1db7b141cf2..23f3a3219c6a 100644 --- a/nixos/doc/manual/administration/rebooting.xml +++ b/nixos/doc/manual/administration/rebooting.xml @@ -10,7 +10,7 @@ doing: <screen> -$ shutdown +# shutdown </screen> This is equivalent to running <command>systemctl @@ -19,7 +19,7 @@ poweroff</command>.</para> <para>To reboot the system, run <screen> -$ reboot +# reboot </screen> which is equivalent to <command>systemctl reboot</command>. @@ -28,7 +28,7 @@ Alternatively, you can quickly reboot the system using the new kernel into memory: <screen> -$ systemctl kexec +# systemctl kexec </screen> </para> @@ -41,4 +41,4 @@ $ systemctl kexec i.e. on a virtual console or in X11; otherwise, the user is asked for authentication.</para> -</chapter> \ No newline at end of file +</chapter> diff --git a/nixos/doc/manual/administration/rollback.xml b/nixos/doc/manual/administration/rollback.xml index 23a3ece7c070..ae621f33de2c 100644 --- a/nixos/doc/manual/administration/rollback.xml +++ b/nixos/doc/manual/administration/rollback.xml @@ -19,7 +19,7 @@ fails to boot. After the system has booted, you can make the selected configuration the default for subsequent boots: <screen> -$ /run/current-system/bin/switch-to-configuration boot</screen> +# /run/current-system/bin/switch-to-configuration boot</screen> </para> @@ -27,12 +27,12 @@ $ /run/current-system/bin/switch-to-configuration boot</screen> system: <screen> -$ nixos-rebuild switch --rollback</screen> +# nixos-rebuild switch --rollback</screen> This is equivalent to running: <screen> -$ /nix/var/nix/profiles/system-<replaceable>N</replaceable>-link/bin/switch-to-configuration switch</screen> +# /nix/var/nix/profiles/system-<replaceable>N</replaceable>-link/bin/switch-to-configuration switch</screen> where <replaceable>N</replaceable> is the number of the NixOS system configuration. To get a list of the available configurations, do: @@ -45,4 +45,4 @@ lrwxrwxrwx 1 root root 78 Aug 12 13:54 /nix/var/nix/profiles/system-268-link -> </para> -</section> \ No newline at end of file +</section> diff --git a/nixos/doc/manual/administration/service-mgmt.xml b/nixos/doc/manual/administration/service-mgmt.xml index c0940a42f307..1627c7a2fdeb 100644 --- a/nixos/doc/manual/administration/service-mgmt.xml +++ b/nixos/doc/manual/administration/service-mgmt.xml @@ -66,9 +66,9 @@ messages from the service. <para>Units can be stopped, started or restarted: <screen> -$ systemctl stop postgresql.service -$ systemctl start postgresql.service -$ systemctl restart postgresql.service +# systemctl stop postgresql.service +# systemctl start postgresql.service +# systemctl restart postgresql.service </screen> These operations are synchronous: they wait until the service has diff --git a/nixos/doc/manual/administration/store-corruption.xml b/nixos/doc/manual/administration/store-corruption.xml index 0160cb45358b..9f567042b727 100644 --- a/nixos/doc/manual/administration/store-corruption.xml +++ b/nixos/doc/manual/administration/store-corruption.xml @@ -18,7 +18,7 @@ you may be able to fix it automatically.</para> system configuration, you can fix it by doing <screen> -$ nixos-rebuild switch --repair +# nixos-rebuild switch --repair </screen> This will cause Nix to check every path in the closure, and if its @@ -28,10 +28,10 @@ the path is rebuilt or redownloaded.</para> <para>You can also scan the entire Nix store for corrupt paths: <screen> -$ nix-store --verify --check-contents --repair +# nix-store --verify --check-contents --repair </screen> Any corrupt paths will be redownloaded if they’re available in a binary cache; otherwise, they cannot be repaired.</para> -</section> \ No newline at end of file +</section> diff --git a/nixos/doc/manual/administration/user-sessions.xml b/nixos/doc/manual/administration/user-sessions.xml index 05e2c1a9b29f..0a7eb8cd123c 100644 --- a/nixos/doc/manual/administration/user-sessions.xml +++ b/nixos/doc/manual/administration/user-sessions.xml @@ -45,9 +45,9 @@ track of this, you can terminate a session in a way that ensures that all the session’s processes are gone: <screen> -$ loginctl terminate-session c3 +# loginctl terminate-session c3 </screen> </para> -</chapter> \ No newline at end of file +</chapter> diff --git a/nixos/doc/manual/configuration/adding-custom-packages.xml b/nixos/doc/manual/configuration/adding-custom-packages.xml index c1789fcbc041..ab3665bae504 100644 --- a/nixos/doc/manual/configuration/adding-custom-packages.xml +++ b/nixos/doc/manual/configuration/adding-custom-packages.xml @@ -31,7 +31,7 @@ and you run <command>nixos-rebuild</command>, specifying your own Nixpkgs tree: <screen> -$ nixos-rebuild switch -I nixpkgs=/path/to/my/nixpkgs</screen> +# nixos-rebuild switch -I nixpkgs=/path/to/my/nixpkgs</screen> </para> diff --git a/nixos/doc/manual/configuration/linux-kernel.xml b/nixos/doc/manual/configuration/linux-kernel.xml index 0cdae4f64416..52be26d6024a 100644 --- a/nixos/doc/manual/configuration/linux-kernel.xml +++ b/nixos/doc/manual/configuration/linux-kernel.xml @@ -19,7 +19,7 @@ kernel.</para> <para>The default Linux kernel configuration should be fine for most users. You can see the configuration of your current kernel with the following command: <programlisting> -cat /proc/config.gz | gunzip +zcat /proc/config.gz </programlisting> If you want to change the kernel configuration, you can use the <option>packageOverrides</option> feature (see <xref @@ -72,7 +72,7 @@ available parameters, run <command>sysctl -a</command>.</para> <para>When developing kernel modules it's often convenient to run edit-compile-run loop as quickly as possible. - See below snippet as an example of developing <literal>mellanix</literal> + See below snippet as an example of developing <literal>mellanox</literal> drivers. </para> @@ -82,7 +82,7 @@ $ nix-shell '<nixpkgs>' -A linuxPackages.kernel $ unpackPhase $ cd linux-* $ make -C $dev/lib/modules/*/build M=$(pwd)/drivers/net/ethernet/mellanox modules -$ sudo insmod ./drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko +# insmod ./drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko ]]></screen> </section> diff --git a/nixos/doc/manual/configuration/luks-file-systems.xml b/nixos/doc/manual/configuration/luks-file-systems.xml index 45475dbcd446..2062456703f7 100644 --- a/nixos/doc/manual/configuration/luks-file-systems.xml +++ b/nixos/doc/manual/configuration/luks-file-systems.xml @@ -9,23 +9,23 @@ <para>NixOS supports file systems that are encrypted using <emphasis>LUKS</emphasis> (Linux Unified Key Setup). For example, here is how you create an encrypted Ext4 file system on the device -<filename>/dev/sda2</filename>: +<filename>/dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d</filename>: <screen> -$ cryptsetup luksFormat /dev/sda2 +# cryptsetup luksFormat /dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d WARNING! ======== -This will overwrite data on /dev/sda2 irrevocably. +This will overwrite data on /dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d irrevocably. Are you sure? (Type uppercase yes): YES Enter LUKS passphrase: *** Verify passphrase: *** -$ cryptsetup luksOpen /dev/sda2 crypted -Enter passphrase for /dev/sda2: *** +# cryptsetup luksOpen /dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d crypted +Enter passphrase for /dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d: *** -$ mkfs.ext4 /dev/mapper/crypted +# mkfs.ext4 /dev/mapper/crypted </screen> To ensure that this file system is automatically mounted at boot time @@ -33,7 +33,7 @@ as <filename>/</filename>, add the following to <filename>configuration.nix</filename>: <programlisting> -boot.initrd.luks.devices = [ { device = "/dev/sda2"; name = "crypted"; } ]; +boot.initrd.luks.devices.crypted.device = "/dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d"; fileSystems."/".device = "/dev/mapper/crypted"; </programlisting> diff --git a/nixos/doc/manual/configuration/user-mgmt.xml b/nixos/doc/manual/configuration/user-mgmt.xml index 631742059278..829e5b9ea842 100644 --- a/nixos/doc/manual/configuration/user-mgmt.xml +++ b/nixos/doc/manual/configuration/user-mgmt.xml @@ -63,14 +63,14 @@ commands such as <command>useradd</command>, account named <literal>alice</literal>: <screen> -$ useradd -m alice</screen> +# useradd -m alice</screen> To make all nix tools available to this new user use `su - USER` which opens a login shell (==shell that loads the profile) for given user. This will create the ~/.nix-defexpr symlink. So run: <screen> -$ su - alice -c "true"</screen> +# su - alice -c "true"</screen> The flag <option>-m</option> causes the creation of a home directory @@ -79,7 +79,7 @@ have an initial password and therefore cannot log in. A password can be set using the <command>passwd</command> utility: <screen> -$ passwd alice +# passwd alice Enter new UNIX password: *** Retype new UNIX password: *** </screen> @@ -87,7 +87,7 @@ Retype new UNIX password: *** A user can be deleted using <command>userdel</command>: <screen> -$ userdel -r alice</screen> +# userdel -r alice</screen> The flag <option>-r</option> deletes the user’s home directory. Accounts can be modified using <command>usermod</command>. Unix diff --git a/nixos/doc/manual/configuration/wireless.xml b/nixos/doc/manual/configuration/wireless.xml index e4560f2da36b..1868380dcbfa 100644 --- a/nixos/doc/manual/configuration/wireless.xml +++ b/nixos/doc/manual/configuration/wireless.xml @@ -41,13 +41,13 @@ If you are using WPA2 the <command>wpa_passphrase</command> tool might be useful to generate the <literal>wpa_supplicant.conf</literal>. <screen> -$ wpa_passphrase ESSID PSK > /etc/wpa_supplicant.conf</screen> +# wpa_passphrase ESSID PSK > /etc/wpa_supplicant.conf</screen> After you have edited the <literal>wpa_supplicant.conf</literal>, you need to restart the wpa_supplicant service. <screen> -$ systemctl restart wpa_supplicant.service</screen> +# systemctl restart wpa_supplicant.service</screen> </para> </section> diff --git a/nixos/doc/manual/configuration/x-windows.xml b/nixos/doc/manual/configuration/x-windows.xml index 7f43acab2c38..3040839861c1 100644 --- a/nixos/doc/manual/configuration/x-windows.xml +++ b/nixos/doc/manual/configuration/x-windows.xml @@ -5,7 +5,7 @@ xml:id="sec-x11"> <title>X Window System</title> - + <para>The X Window System (X11) provides the basis of NixOS’ graphical user interface. It can be enabled as follows: <programlisting> @@ -48,7 +48,7 @@ services.xserver.autorun = false; </programlisting> The X server can then be started manually: <screen> -$ systemctl start display-manager.service +# systemctl start display-manager.service </screen> </para> @@ -115,5 +115,14 @@ services.xserver.synaptics.twoFingerScroll = true; </simplesect> +<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 +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> + +</simplesect> </chapter> diff --git a/nixos/doc/manual/development/building-nixos.xml b/nixos/doc/manual/development/building-nixos.xml index 21c5bfe6a5b1..150fa1d7017e 100644 --- a/nixos/doc/manual/development/building-nixos.xml +++ b/nixos/doc/manual/development/building-nixos.xml @@ -25,8 +25,8 @@ $ nix-build -A config.system.build.isoImage -I nixos-config=modules/installer/cd suggested by the following command: <screen> -$ mount -o loop -t iso9660 ./result/iso/cd.iso /mnt/iso</screen> +# mount -o loop -t iso9660 ./result/iso/cd.iso /mnt/iso</screen> </para> -</chapter> \ No newline at end of file +</chapter> diff --git a/nixos/doc/manual/development/building-parts.xml b/nixos/doc/manual/development/building-parts.xml index cb8dee039c8e..09a40114f02e 100644 --- a/nixos/doc/manual/development/building-parts.xml +++ b/nixos/doc/manual/development/building-parts.xml @@ -94,8 +94,8 @@ $ nix-build -A 'config.systemd.units."httpd.service".unit' <screen> $ cp $(nix-build -A 'config.systemd.units."httpd.service".unit')/httpd.service \ /run/systemd/system/tmp-httpd.service -$ systemctl daemon-reload -$ systemctl start tmp-httpd.service +# systemctl daemon-reload +# systemctl start tmp-httpd.service </screen> Note that the unit must not have the same name as any unit in @@ -110,4 +110,4 @@ $ systemctl start tmp-httpd.service </para> -</chapter> \ No newline at end of file +</chapter> diff --git a/nixos/doc/manual/development/option-declarations.xml b/nixos/doc/manual/development/option-declarations.xml index ea5d1241876e..b0689aa1d97f 100644 --- a/nixos/doc/manual/development/option-declarations.xml +++ b/nixos/doc/manual/development/option-declarations.xml @@ -7,8 +7,8 @@ <title>Option Declarations</title> <para>An option declaration specifies the name, type and description -of a NixOS configuration option. It is illegal to define an option -that hasn’t been declared in any module. A option declaration +of a NixOS configuration option. It is invalid to define an option +that hasn’t been declared in any module. An option declaration generally looks like this: <programlisting> @@ -42,7 +42,7 @@ options = { <listitem> <para>The default value used if no value is defined by any module. A default is not required; in that case, if the option - value is ever used, an error will be thrown.</para> + value is never used, an error will be thrown.</para> </listitem> </varlistentry> diff --git a/nixos/doc/manual/development/sources.xml b/nixos/doc/manual/development/sources.xml index fd0b0109b322..7cd5ce0002c2 100644 --- a/nixos/doc/manual/development/sources.xml +++ b/nixos/doc/manual/development/sources.xml @@ -70,7 +70,7 @@ sources, you need to tell <command>nixos-rebuild</command> about them using the <option>-I</option> flag: <screen> -$ nixos-rebuild switch -I nixpkgs=<replaceable>/my/sources</replaceable>/nixpkgs +# nixos-rebuild switch -I nixpkgs=<replaceable>/my/sources</replaceable>/nixpkgs </screen> </para> diff --git a/nixos/doc/manual/development/testing-installer.xml b/nixos/doc/manual/development/testing-installer.xml index 87e40e326171..20c8d51815ad 100644 --- a/nixos/doc/manual/development/testing-installer.xml +++ b/nixos/doc/manual/development/testing-installer.xml @@ -12,16 +12,16 @@ properly: <screen> $ nix-build -A config.system.build.nixos-install -$ mount -t tmpfs none /mnt -$ ./result/bin/nixos-install</screen> +# mount -t tmpfs none /mnt +# ./result/bin/nixos-install</screen> To start a login shell in the new NixOS installation in <filename>/mnt</filename>: <screen> -$ ./result/bin/nixos-install --chroot +# ./result/bin/nixos-install --chroot </screen> </para> -</chapter> \ No newline at end of file +</chapter> diff --git a/nixos/doc/manual/installation/changing-config.xml b/nixos/doc/manual/installation/changing-config.xml index aa31742434e4..43b591a1cae9 100644 --- a/nixos/doc/manual/installation/changing-config.xml +++ b/nixos/doc/manual/installation/changing-config.xml @@ -10,7 +10,7 @@ contains the current configuration of your machine. Whenever you’ve changed something to that file, you should do <screen> -$ nixos-rebuild switch</screen> +# nixos-rebuild switch</screen> to build the new configuration, make it the default configuration for booting, and try to realise the configuration in the running system @@ -23,7 +23,7 @@ either run them from a root shell or by prefixing them with <para>You can also do <screen> -$ nixos-rebuild test</screen> +# nixos-rebuild test</screen> to build the configuration and switch the running system to it, but without making it the boot default. So if (say) the configuration @@ -33,7 +33,7 @@ configuration.</para> <para>There is also <screen> -$ nixos-rebuild boot</screen> +# nixos-rebuild boot</screen> to build the configuration and make it the boot default, but not switch to it now (so it will only take effect after the next @@ -44,7 +44,7 @@ of the GRUB 2 boot screen by giving it a different <emphasis>profile name</emphasis>, e.g. <screen> -$ nixos-rebuild switch -p test </screen> +# nixos-rebuild switch -p test </screen> which causes the new configuration (and previous ones created using <literal>-p test</literal>) to show up in the GRUB submenu “NixOS - diff --git a/nixos/doc/manual/installation/installing-uefi.xml b/nixos/doc/manual/installation/installing-uefi.xml index 90d18695447c..927648febc50 100644 --- a/nixos/doc/manual/installation/installing-uefi.xml +++ b/nixos/doc/manual/installation/installing-uefi.xml @@ -5,7 +5,7 @@ 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: @@ -26,7 +26,7 @@ changes: <literal>vfat</literal> filesystem.</para> </listitem> <listitem> - <para>You must set <option>boot.loader.gummiboot.enable</option> to + <para>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> @@ -38,7 +38,7 @@ changes: </listitem> <listitem> <para>You may want to look at the options starting with - <option>boot.loader.efi</option> and <option>boot.loader.gummiboot</option> + <option>boot.loader.efi</option> and <option>boot.loader.systemd-boot</option> as well.</para> </listitem> </itemizedlist> diff --git a/nixos/doc/manual/installation/installing.xml b/nixos/doc/manual/installation/installing.xml index 3e53062c3e84..2f118d27b1a5 100644 --- a/nixos/doc/manual/installation/installing.xml +++ b/nixos/doc/manual/installation/installing.xml @@ -54,7 +54,7 @@ changes. For example: <screen> -$ mkfs.ext4 -L nixos /dev/sda1</screen> +# mkfs.ext4 -L nixos /dev/sda1</screen> </para></listitem> @@ -66,10 +66,10 @@ $ mkfs.ext4 -L nixos /dev/sda1</screen> <listitem><para>For creating LVM volumes, the LVM commands, e.g., <screen> -$ pvcreate /dev/sda1 /dev/sdb1 -$ vgcreate MyVolGroup /dev/sda1 /dev/sdb1 -$ lvcreate --size 2G --name bigdisk MyVolGroup -$ lvcreate --size 1G --name smalldisk MyVolGroup</screen> +# pvcreate /dev/sda1 /dev/sdb1 +# vgcreate MyVolGroup /dev/sda1 /dev/sdb1 +# lvcreate --size 2G --name bigdisk MyVolGroup +# lvcreate --size 1G --name smalldisk MyVolGroup</screen> </para></listitem> @@ -84,7 +84,7 @@ $ lvcreate --size 1G --name smalldisk MyVolGroup</screen> be installed on <filename>/mnt</filename>, e.g. <screen> -$ mount /dev/disk/by-label/nixos /mnt +# mount /dev/disk/by-label/nixos /mnt </screen> </para></listitem> @@ -113,14 +113,14 @@ $ mount /dev/disk/by-label/nixos /mnt generate an initial configuration file for you: <screen> -$ nixos-generate-config --root /mnt</screen> +# nixos-generate-config --root /mnt</screen> You should then edit <filename>/mnt/etc/nixos/configuration.nix</filename> to suit your needs: <screen> -$ nano /mnt/etc/nixos/configuration.nix +# nano /mnt/etc/nixos/configuration.nix </screen> If you’re using the graphical ISO image, other editors may be @@ -162,7 +162,7 @@ $ nano /mnt/etc/nixos/configuration.nix <listitem><para>Do the installation: <screen> -$ nixos-install</screen> +# nixos-install</screen> Cross fingers. If this fails due to a temporary problem (such as a network issue while downloading binaries from the NixOS binary @@ -186,7 +186,7 @@ Retype new UNIX password: *** <listitem><para>If everything went well: <screen> -$ reboot</screen> +# reboot</screen> </para></listitem> @@ -235,15 +235,15 @@ 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> -$ mkfs.ext4 -L nixos /dev/sda1 -$ mkswap -L swap /dev/sda2 -$ swapon /dev/sda2 -$ mount /dev/disk/by-label/nixos /mnt -$ nixos-generate-config --root /mnt -$ nano /mnt/etc/nixos/configuration.nix -$ nixos-install -$ reboot</screen> +# fdisk /dev/sda # <lineannotation>(or whatever device you want to install on)</lineannotation> +# mkfs.ext4 -L nixos /dev/sda1 +# mkswap -L swap /dev/sda2 +# swapon /dev/sda2 +# mount /dev/disk/by-label/nixos /mnt +# nixos-generate-config --root /mnt +# nano /mnt/etc/nixos/configuration.nix +# nixos-install +# reboot</screen> </example> <example xml:id='ex-config'><title>NixOS Configuration</title> diff --git a/nixos/doc/manual/installation/upgrading.xml b/nixos/doc/manual/installation/upgrading.xml index c4812cc637c3..65d395b0c88e 100644 --- a/nixos/doc/manual/installation/upgrading.xml +++ b/nixos/doc/manual/installation/upgrading.xml @@ -60,33 +60,33 @@ the <literal>nixos-14.12</literal> channel. To see which NixOS channel you’re subscribed to, run the following as root: <screen> -$ nix-channel --list | grep nixos +# nix-channel --list | grep nixos nixos https://nixos.org/channels/nixos-unstable </screen> To switch to a different NixOS channel, do <screen> -$ nix-channel --add https://nixos.org/channels/<replaceable>channel-name</replaceable> nixos +# nix-channel --add https://nixos.org/channels/<replaceable>channel-name</replaceable> nixos </screen> (Be sure to include the <literal>nixos</literal> parameter at the end.) For instance, to use the NixOS 14.12 stable channel: <screen> -$ nix-channel --add https://nixos.org/channels/nixos-14.12 nixos +# nix-channel --add https://nixos.org/channels/nixos-14.12 nixos </screen> If you have a server, you may want to use the “small” channel instead: <screen> -$ nix-channel --add https://nixos.org/channels/nixos-14.12-small nixos +# nix-channel --add https://nixos.org/channels/nixos-14.12-small nixos </screen> And if you want to live on the bleeding edge: <screen> -$ nix-channel --add https://nixos.org/channels/nixos-unstable nixos +# nix-channel --add https://nixos.org/channels/nixos-unstable nixos </screen> </para> @@ -95,7 +95,7 @@ $ nix-channel --add https://nixos.org/channels/nixos-unstable nixos channel by running <screen> -$ nixos-rebuild switch --upgrade +# nixos-rebuild switch --upgrade </screen> which is equivalent to the more verbose <literal>nix-channel --update diff --git a/nixos/doc/manual/man-configuration.xml b/nixos/doc/manual/man-configuration.xml index d49369d2c584..05531b3909a3 100644 --- a/nixos/doc/manual/man-configuration.xml +++ b/nixos/doc/manual/man-configuration.xml @@ -1,7 +1,7 @@ <refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xi="http://www.w3.org/2001/XInclude"> - + <refmeta> <refentrytitle><filename>configuration.nix</filename></refentrytitle> <manvolnum>5</manvolnum> @@ -34,5 +34,5 @@ therein.</para> <xi:include href="options-db.xml" /> </refsection> - + </refentry> diff --git a/nixos/doc/manual/man-nixos-build-vms.xml b/nixos/doc/manual/man-nixos-build-vms.xml index f37677629d0c..878ebee05273 100644 --- a/nixos/doc/manual/man-nixos-build-vms.xml +++ b/nixos/doc/manual/man-nixos-build-vms.xml @@ -1,7 +1,7 @@ <refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xi="http://www.w3.org/2001/XInclude"> - + <refmeta> <refentrytitle><command>nixos-build-vms</command></refentrytitle> <manvolnum>8</manvolnum> @@ -42,10 +42,10 @@ points to the generated virtual network. services.openssh.enable = true; nixpkgs.system = "i686-linux"; deployment.targetHost = "test1.example.net"; - + # Other NixOS options }; - + test2 = {pkgs, config, ...}: { services.openssh.enable = true; @@ -53,7 +53,7 @@ points to the generated virtual network. environment.systemPackages = [ pkgs.lynx ]; nixpkgs.system = "x86_64-linux"; deployment.targetHost = "test2.example.net"; - + # Other NixOS options }; } diff --git a/nixos/doc/manual/man-nixos-generate-config.xml b/nixos/doc/manual/man-nixos-generate-config.xml index 140642bc9c9c..993a932ddfbe 100644 --- a/nixos/doc/manual/man-nixos-generate-config.xml +++ b/nixos/doc/manual/man-nixos-generate-config.xml @@ -113,8 +113,8 @@ <varlistentry> <term><option>--no-filesystems</option></term> <listitem> - <para>Omit everything concerning file system information - (which includes swap devices) from the hardware configuration.</para> + <para>Omit everything concerning file systems and swap devices + from the hardware configuration.</para> </listitem> </varlistentry> diff --git a/nixos/doc/manual/man-nixos-option.xml b/nixos/doc/manual/man-nixos-option.xml index 2875336c67e5..6be8bc780f13 100644 --- a/nixos/doc/manual/man-nixos-option.xml +++ b/nixos/doc/manual/man-nixos-option.xml @@ -1,7 +1,7 @@ <refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xi="http://www.w3.org/2001/XInclude"> - + <refmeta> <refentrytitle><command>nixos-option</command></refentrytitle> <manvolnum>8</manvolnum> @@ -64,7 +64,7 @@ $ nixos-option boot.loader.grub.enable Value: true -Default: +Default: true Description: diff --git a/nixos/doc/manual/manual.xml b/nixos/doc/manual/manual.xml index 736d1d4eff71..2c28dd448016 100644 --- a/nixos/doc/manual/manual.xml +++ b/nixos/doc/manual/manual.xml @@ -3,7 +3,7 @@ xmlns:xi="http://www.w3.org/2001/XInclude" version="5.0" xml:id="book-nixos-manual"> - + <info> <title>NixOS Manual</title> <subtitle>Version <xi:include href="version" parse="text" /></subtitle> @@ -26,6 +26,9 @@ xlink:href="https://github.com/NixOS/nixpkgs/issues">NixOS’ GitHub issue tracker</link>.</para> + <note><para>Commands prefixed with <literal>#</literal> have to be run as + root, either requiring to login as root user or temporarily switching + to it using <literal>sudo</literal> for example.</para></note> </preface> <xi:include href="installation/installation.xml" /> diff --git a/nixos/doc/manual/options-to-docbook.xsl b/nixos/doc/manual/options-to-docbook.xsl index cd30ae36ae59..5387546b5982 100644 --- a/nixos/doc/manual/options-to-docbook.xsl +++ b/nixos/doc/manual/options-to-docbook.xsl @@ -11,6 +11,7 @@ <xsl:output method='xml' encoding="UTF-8" /> <xsl:param name="revision" /> + <xsl:param name="program" /> <xsl:template match="/expr/list"> @@ -188,7 +189,7 @@ </xsl:otherwise> </xsl:choose> </xsl:when> - <xsl:when test="$revision != 'local' and contains(@value, 'nixops') and contains(@value, '/nix/')"> + <xsl:when test="$revision != 'local' and $program = 'nixops' and contains(@value, '/nix/')"> <xsl:attribute name="xlink:href">https://github.com/NixOS/nixops/blob/<xsl:value-of select="$revision"/>/nix/<xsl:value-of select="substring-after(@value, '/nix/')"/></xsl:attribute> </xsl:when> <xsl:otherwise> diff --git a/nixos/doc/manual/release-notes/rl-1603.xml b/nixos/doc/manual/release-notes/rl-1603.xml index 620c3e362a65..c51316bd2808 100644 --- a/nixos/doc/manual/release-notes/rl-1603.xml +++ b/nixos/doc/manual/release-notes/rl-1603.xml @@ -279,7 +279,7 @@ fileSystems."/example" = { <listitem> <para><literal>services.xserver.vaapiDrivers</literal> has been removed. Use - <literal>services.hardware.opengl.extraPackages{,32}</literal> instead. You can + <literal>hardware.opengl.extraPackages{,32}</literal> instead. You can also specify VDPAU drivers there.</para> </listitem> diff --git a/nixos/doc/manual/release-notes/rl-1609.xml b/nixos/doc/manual/release-notes/rl-1609.xml index 22dea8029242..be175a54c232 100644 --- a/nixos/doc/manual/release-notes/rl-1609.xml +++ b/nixos/doc/manual/release-notes/rl-1609.xml @@ -16,6 +16,10 @@ has the following highlights: </para> See <xref linkend="sec-booting-from-pxe" /> for documentation.</para> </listitem> + <listitem> + <para>Xorg-server-1.18.*. If you choose <literal>"ati_unfree"</literal> driver, + 1.17.* is still used due to ABI incompatibility.</para> + </listitem> </itemizedlist> <para>The following new services were added since the last release:</para> @@ -30,7 +34,10 @@ following incompatible changes:</para> <itemizedlist> <listitem> - <para>todo</para> + <para>Shell aliases for systemd sub-commands + <link xlink:href="https://github.com/NixOS/nixpkgs/pull/15598">were dropped</link>: + <command>start</command>, <command>stop</command>, + <command>restart</command>, <command>status</command>.</para> </listitem> </itemizedlist> diff --git a/nixos/lib/test-driver/Logger.pm b/nixos/lib/test-driver/Logger.pm index 6e62fdfd7708..3fe5ef67c144 100644 --- a/nixos/lib/test-driver/Logger.pm +++ b/nixos/lib/test-driver/Logger.pm @@ -3,6 +3,7 @@ package Logger; use strict; use Thread::Queue; use XML::Writer; +use Encode qw(decode encode); sub new { my ($class) = @_; @@ -56,7 +57,8 @@ sub nest { sub sanitise { my ($s) = @_; $s =~ s/[[:cntrl:]\xff]//g; - return $s; + $s = decode('UTF-8', $s, Encode::FB_DEFAULT); + return encode('UTF-8', $s, Encode::FB_CROAK); } sub log { diff --git a/nixos/lib/test-driver/Machine.pm b/nixos/lib/test-driver/Machine.pm index 37d6518fd8d7..1a243918c22f 100644 --- a/nixos/lib/test-driver/Machine.pm +++ b/nixos/lib/test-driver/Machine.pm @@ -382,9 +382,17 @@ sub waitForUnit { 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"); - die "unit ‘$unit’ is inactive and there are no pending jobs\n" - if $jobs =~ /No jobs/; # FIXME: fragile + if ($jobs =~ /No jobs/) { # FIXME: fragile + # Handle the case where the unit may have started + # between the previous getUnitInfo() and + # list-jobs. + my $info2 = $self->getUnitInfo($unit); + die "unit ‘$unit’ is inactive and there are no pending jobs\n" + if $info2->{ActiveState} eq $state; + } } return 1 if $state eq "active"; }; diff --git a/nixos/lib/testing.nix b/nixos/lib/testing.nix index f7159634e4f1..5f463c092846 100644 --- a/nixos/lib/testing.nix +++ b/nixos/lib/testing.nix @@ -113,14 +113,14 @@ rec { --add-flags "$vms" \ ${lib.optionalString enableOCR "--prefix PATH : '${ocrProg}/bin'"} \ --run "testScript=\"\$(cat $out/test-script)\"" \ - --set testScript '"$testScript"' \ - --set VLANS '"${toString vlans}"' + --set testScript '$testScript' \ + --set VLANS '${toString vlans}' ln -s ${testDriver}/bin/nixos-test-driver $out/bin/nixos-run-vms wrapProgram $out/bin/nixos-run-vms \ --add-flags "$vms" \ ${lib.optionalString enableOCR "--prefix PATH : '${ocrProg}/bin'"} \ - --set tests '"startAll; joinAll;"' \ - --set VLANS '"${toString vlans}"' \ + --set tests 'startAll; joinAll;' \ + --set VLANS '${toString vlans}' \ ${lib.optionalString (builtins.length vms == 1) "--set USE_SERIAL 1"} ''; # " diff --git a/nixos/lib/utils.nix b/nixos/lib/utils.nix index 7b8be2050c13..871fbb121d03 100644 --- a/nixos/lib/utils.nix +++ b/nixos/lib/utils.nix @@ -8,4 +8,10 @@ rec { replaceChars ["/" "-" " "] ["-" "\\x2d" "\\x20"] (if hasPrefix "/" s then substring 1 (stringLength s) s else s); + # Returns a system path for a given shell package + toShellPath = shell: + if types.shellPackage.check shell then + "/run/current-system/sw${shell.shellPath}" + else + shell; } diff --git a/nixos/modules/config/fonts/fontdir.nix b/nixos/modules/config/fonts/fontdir.nix index c78b52fe29e1..180e38f81f4f 100644 --- a/nixos/modules/config/fonts/fontdir.nix +++ b/nixos/modules/config/fonts/fontdir.nix @@ -4,47 +4,17 @@ with lib; let - fontDirs = config.fonts.fonts; - - localDefs = with pkgs.builderDefs; pkgs.builderDefs.passthru.function rec { - src = "";/* put a fetchurl here */ - buildInputs = [pkgs.xorg.mkfontdir pkgs.xorg.mkfontscale]; - inherit fontDirs; - installPhase = fullDepEntry (" - list=''; - for i in ${toString fontDirs} ; do - if [ -d \$i/ ]; then - list=\"\$list \$i\"; - fi; - done - list=\$(find \$list -name fonts.dir -o -name '*.ttf' -o -name '*.otf'); - fontDirs=''; - for i in \$list ; do - fontDirs=\"\$fontDirs \$(dirname \$i)\"; - done; - mkdir -p \$out/share/X11-fonts/; - find \$fontDirs -type f -o -type l | while read i; do - j=\"\${i##*/}\" - if ! test -e \"\$out/share/X11-fonts/\${j}\"; then - ln -s \"\$i\" \"\$out/share/X11-fonts/\${j}\"; - fi; - done; - cd \$out/share/X11-fonts/ - rm fonts.dir - rm fonts.scale - rm fonts.alias - mkfontdir - mkfontscale - cat \$( find ${pkgs.xorg.fontalias}/ -name fonts.alias) >fonts.alias - ") ["minInit" "addInputs"]; - }; - - x11Fonts = with localDefs; stdenv.mkDerivation rec { - name = "X11-fonts"; - builder = writeScript (name + "-builder") - (textClosure localDefs - [installPhase doForceShare doPropagate]); - }; + x11Fonts = pkgs.runCommand "X11-fonts" { } '' + mkdir -p "$out/share/X11-fonts" + find ${toString config.fonts.fonts} \ + \( -name fonts.dir -o -name '*.ttf' -o -name '*.otf' \) \ + -exec ln -sf -t "$out/share/X11-fonts" '{}' \; + cd "$out/share/X11-fonts" + rm -f fonts.dir fonts.scale fonts.alias + ${pkgs.xorg.mkfontdir}/bin/mkfontdir + ${pkgs.xorg.mkfontscale}/bin/mkfontscale + cat $(find ${pkgs.xorg.fontalias}/ -name fonts.alias) >fonts.alias + ''; in @@ -70,6 +40,8 @@ in environment.systemPackages = [ x11Fonts ]; + environment.pathsToLink = [ "/share/X11-fonts" ]; + }; } diff --git a/nixos/modules/config/ldap.nix b/nixos/modules/config/ldap.nix index a6657768e061..7064ef64b4c8 100644 --- a/nixos/modules/config/ldap.nix +++ b/nixos/modules/config/ldap.nix @@ -192,7 +192,7 @@ in system.activationScripts = mkIf insertLdapPassword { ldap = stringAfter [ "etc" "groups" "users" ] '' if test -f "${cfg.bind.password}" ; then - echo "bindpw "$(cat ${cfg.bind.password})"" | cat ${ldapConfig} - > /etc/ldap.conf.bindpw + echo "bindpw "$(cat ${cfg.bind.password})"" | cat ${ldapConfig.source} - > /etc/ldap.conf.bindpw mv -fT /etc/ldap.conf.bindpw /etc/ldap.conf chmod 600 /etc/ldap.conf fi diff --git a/nixos/modules/config/networking.nix b/nixos/modules/config/networking.nix index 0c4f4cbfa5c6..8a2e630a917a 100644 --- a/nixos/modules/config/networking.nix +++ b/nixos/modules/config/networking.nix @@ -11,6 +11,9 @@ let config.services.dnsmasq.resolveLocalQueries; hasLocalResolver = config.services.bind.enable || dnsmasqResolve; + resolvconfOptions = cfg.resolvconfOptions + ++ optional cfg.dnsSingleRequest "single-request" + ++ optional cfg.dnsExtensionMechanism "ends0"; in { @@ -59,6 +62,14 @@ in ''; }; + networking.resolvconfOptions = lib.mkOption { + type = types.listOf types.str; + default = []; + example = [ "ndots:1" "rotate" ]; + description = '' + Set the options in <filename>/etc/resolv.conf</filename>. + ''; + }; networking.proxy = { @@ -171,12 +182,9 @@ in # Invalidate the nscd cache whenever resolv.conf is # regenerated. libc_restart='${pkgs.systemd}/bin/systemctl try-restart --no-block nscd.service 2> /dev/null' - '' + optionalString cfg.dnsSingleRequest '' - # only send one DNS request at a time - resolv_conf_options+=' single-request' - '' + optionalString cfg.dnsExtensionMechanism '' - # enable extension mechanisms for DNS - resolv_conf_options+=' edns0' + '' + optionalString (length resolvconfOptions > 0) '' + # Options as described in resolv.conf(5) + resolv_conf_options='${concatStringsSep " " resolvconfOptions}' '' + optionalString hasLocalResolver '' # This hosts runs a full-blown DNS resolver. name_servers='127.0.0.1' diff --git a/nixos/modules/config/shells-environment.nix b/nixos/modules/config/shells-environment.nix index 89b8a04b5e7c..f458bc39adaa 100644 --- a/nixos/modules/config/shells-environment.nix +++ b/nixos/modules/config/shells-environment.nix @@ -1,7 +1,7 @@ # This module defines a global environment configuration and # a common configuration for all shells. -{ config, lib, pkgs, ... }: +{ config, lib, utils, pkgs, ... }: with lib; @@ -135,13 +135,13 @@ in environment.shells = mkOption { default = []; - example = [ "/run/current-system/sw/bin/zsh" ]; + example = literalExample "[ pkgs.bashInteractive pkgs.zsh ]"; description = '' A list of permissible login shells for user accounts. No need to mention <literal>/bin/sh</literal> here, it is placed into this list implicitly. ''; - type = types.listOf types.path; + type = types.listOf (types.either types.shellPackage types.path); }; }; @@ -150,10 +150,6 @@ in system.build.binsh = pkgs.bashInteractive; - # Ensure TERMINFO is set appropriately *before* user shells are run, - # as they may depend on it - environment.sessionVariables.TERMINFO = "/run/current-system/sw/share/terminfo"; - # Set session variables in the shell as well. This is usually # unnecessary, but it allows changes to session variables to take # effect without restarting the session (e.g. by opening a new @@ -162,7 +158,7 @@ in environment.etc."shells".text = '' - ${concatStringsSep "\n" cfg.shells} + ${concatStringsSep "\n" (map utils.toShellPath cfg.shells)} /bin/sh ''; diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix index e643b2d059b5..277a4264137b 100644 --- a/nixos/modules/config/users-groups.nix +++ b/nixos/modules/config/users-groups.nix @@ -1,9 +1,8 @@ -{ config, lib, pkgs, ... }: +{ config, lib, utils, pkgs, ... }: with lib; let - ids = config.ids; cfg = config.users; @@ -103,7 +102,7 @@ let }; home = mkOption { - type = types.str; + type = types.path; default = "/var/empty"; description = "The user's home directory."; }; @@ -118,8 +117,10 @@ let }; shell = mkOption { - type = types.str; - default = "/run/current-system/sw/bin/nologin"; + type = types.either types.shellPackage types.path; + default = pkgs.nologin; + defaultText = "pkgs.nologin"; + example = literalExample "pkgs.bashInteractive"; description = "The path to the user's shell."; }; @@ -359,11 +360,12 @@ let spec = pkgs.writeText "users-groups.json" (builtins.toJSON { inherit (cfg) mutableUsers; - users = mapAttrsToList (n: u: + users = mapAttrsToList (_: u: { inherit (u) - name uid group description home shell createHome isSystemUser + name uid group description home createHome isSystemUser password passwordFile hashedPassword initialPassword initialHashedPassword; + shell = utils.toShellPath u.shell; }) cfg.users; groups = mapAttrsToList (n: g: { inherit (g) name gid; @@ -373,6 +375,12 @@ let }) cfg.groups; }); + systemShells = + let + shells = mapAttrsToList (_: u: u.shell) cfg.users; + in + filter types.shellPackage.check shells; + in { ###### interface @@ -468,7 +476,6 @@ in { home = "/root"; shell = mkDefault cfg.defaultUserShell; group = "root"; - extraGroups = [ "grsecurity" ]; initialHashedPassword = mkDefault config.security.initialRootPassword; }; nobody = { @@ -478,6 +485,9 @@ in { }; }; + # Install all the user shells + environment.systemPackages = systemShells; + users.groups = { root.gid = ids.gids.root; wheel.gid = ids.gids.wheel; @@ -497,7 +507,6 @@ in { nixbld.gid = ids.gids.nixbld; utmp.gid = ids.gids.utmp; adm.gid = ids.gids.adm; - grsecurity.gid = ids.gids.grsecurity; input.gid = ids.gids.input; }; diff --git a/nixos/modules/hardware/video/ati.nix b/nixos/modules/hardware/video/ati.nix index 033e49d2233e..bf91bcf0776b 100644 --- a/nixos/modules/hardware/video/ati.nix +++ b/nixos/modules/hardware/video/ati.nix @@ -18,6 +18,8 @@ in config = mkIf enabled { + nixpkgs.config.xorg.fglrxCompat = true; + services.xserver.drivers = singleton { name = "fglrx"; modules = [ ati_x11 ]; libPath = [ "${ati_x11}/lib" ]; }; diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix index c31ded977e68..4fc8bf5428f8 100644 --- a/nixos/modules/installer/cd-dvd/iso-image.nix +++ b/nixos/modules/installer/cd-dvd/iso-image.nix @@ -64,7 +64,7 @@ let # The EFI boot image. efiDir = pkgs.runCommand "efi-directory" {} '' mkdir -p $out/EFI/boot - cp -v ${pkgs.gummiboot}/lib/gummiboot/gummiboot${targetArch}.efi $out/EFI/boot/boot${targetArch}.efi + cp -v ${pkgs.systemd}/lib/systemd/boot/efi/systemd-boot${targetArch}.efi $out/EFI/boot/boot${targetArch}.efi mkdir -p $out/loader/entries echo "title NixOS Live CD" > $out/loader/entries/nixos-livecd.conf @@ -79,7 +79,7 @@ let echo "options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} nomodeset" >> $out/loader/entries/nixos-livecd-nomodeset.conf echo "default nixos-livecd" > $out/loader/loader.conf - echo "timeout ${builtins.toString config.boot.loader.gummiboot.timeout}" >> $out/loader/loader.conf + echo "timeout ${builtins.toString config.boot.loader.timeout}" >> $out/loader/loader.conf ''; efiImg = pkgs.runCommand "efi-image_eltorito" { buildInputs = [ pkgs.mtools pkgs.libfaketime ]; } diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl index 8e75f8d3c40a..5e576367eb2f 100644 --- a/nixos/modules/installer/tools/nixos-generate-config.pl +++ b/nixos/modules/installer/tools/nixos-generate-config.pl @@ -1,5 +1,6 @@ #! @perl@ +use strict; use Cwd 'abs_path'; use File::Spec; use File::Path; @@ -69,6 +70,7 @@ for (my $n = 0; $n < scalar @ARGV; $n++) { my @attrs = (); my @kernelModules = (); my @initrdKernelModules = (); +my @initrdAvailableKernelModules = (); my @modulePackages = (); my @imports; @@ -379,7 +381,7 @@ EOF # Is this a btrfs filesystem? if ($fsType eq "btrfs") { my ($status, @id_info) = runCommand("btrfs subvol show $rootDir$mountPoint"); - if ($status != 0 || join("", @msg) =~ /ERROR:/) { + if ($status != 0 || join("", @id_info) =~ /ERROR:/) { die "Failed to retrieve subvolume info for $mountPoint\n"; } my @ids = join("", @id_info) =~ m/Subvolume ID:[ \t\n]*([^ \t\n]*)/; @@ -408,7 +410,7 @@ EOF EOF if (scalar @extraOptions > 0) { - $fileSystems .= <<EOF; + $fileSystems .= <<EOF; options = \[ ${\join " ", map { "\"" . $_ . "\"" } uniq(@extraOptions)} \]; EOF } @@ -417,6 +419,25 @@ EOF }; EOF + + # If this filesystem is on a LUKS device, then add a + # boot.initrd.luks.devices entry. + if (-e $device) { + my $deviceName = basename(abs_path($device)); + if (-e "/sys/class/block/$deviceName" + && read_file("/sys/class/block/$deviceName/dm/uuid", err_mode => 'quiet') =~ /^CRYPT-LUKS/) + { + my @slaves = glob("/sys/class/block/$deviceName/slaves/*"); + if (scalar @slaves == 1) { + my $slave = "/dev/" . basename($slaves[0]); + if (-e $slave) { + my $dmName = read_file("/sys/class/block/$deviceName/dm/name"); + chomp $dmName; + $fileSystems .= " boot.initrd.luks.devices.\"$dmName\".device = \"${\(findStableDevPath $slave)}\";\n\n"; + } + } + } + } } @@ -440,7 +461,7 @@ sub toNixList { sub multiLineList { my $indent = shift; return " [ ]" if !@_; - $res = "\n${indent}[ "; + my $res = "\n${indent}[ "; my $first = 1; foreach my $s (@_) { $res .= "$indent " if !$first; @@ -457,7 +478,7 @@ my $modulePackages = toNixList(uniq @modulePackages); my $fsAndSwap = ""; if (!$noFilesystems) { - $fsAndSwap = "\n${fileSystems} "; + $fsAndSwap = "\n$fileSystems "; $fsAndSwap .= "swapDevices =" . multiLineList(" ", @swapDevices) . ";\n"; } @@ -494,11 +515,11 @@ if ($showHardwareConfig) { if ($force || ! -e $fn) { print STDERR "writing $fn...\n"; - my $bootloaderConfig = ""; + my $bootLoaderConfig = ""; if (-e "/sys/firmware/efi/efivars") { $bootLoaderConfig = <<EOF; - # Use the gummiboot efi boot loader. - boot.loader.gummiboot.enable = true; + # Use the systemd-boot EFI boot loader. + boot.loader.systemd-boot.enable = true; boot.loader.efi.canTouchEfiVariables = true; EOF } elsif ($virt ne "systemd-nspawn") { @@ -568,7 +589,7 @@ $bootLoaderConfig # }; # The NixOS release to be compatible with for stateful data such as databases. - system.stateVersion = "@nixosRelease@"; + system.stateVersion = "${\(qw(@nixosRelease@))}"; } EOF diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index b2cb121d1d63..8da421447624 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -147,7 +147,6 @@ foundationdb = 118; newrelic = 119; starbound = 120; - #grsecurity = 121; # unused hydra = 122; spiped = 123; teamspeak = 124; @@ -267,6 +266,10 @@ graylog = 243; sniproxy = 244; nzbget = 245; + mosquitto = 246; + toxvpn = 247; + squeezelite = 248; + turnserver = 249; # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! @@ -394,7 +397,6 @@ foundationdb = 118; newrelic = 119; starbound = 120; - grsecurity = 121; hydra = 122; spiped = 123; teamspeak = 124; @@ -504,6 +506,10 @@ emby = 242; sniproxy = 244; nzbget = 245; + mosquitto = 246; + #toxvpn = 247; # unused + #squeezelite = 248; #unused + turnserver = 249; # When adding a gid, make sure it doesn't match an existing # uid. Users and groups with the same name should have equal diff --git a/nixos/modules/misc/version.nix b/nixos/modules/misc/version.nix index f12ecc1b88ec..9a37f5950930 100644 --- a/nixos/modules/misc/version.nix +++ b/nixos/modules/misc/version.nix @@ -5,9 +5,11 @@ with lib; let cfg = config.system; - releaseFile = "${toString pkgs.path}/.version"; - suffixFile = "${toString pkgs.path}/.version-suffix"; + releaseFile = "${toString pkgs.path}/.version"; + suffixFile = "${toString pkgs.path}/.version-suffix"; revisionFile = "${toString pkgs.path}/.git-revision"; + gitRepo = "${toString pkgs.path}/.git"; + gitCommitId = lib.substring 0 7 (commitIdFromGitRepo gitRepo); in { @@ -102,6 +104,8 @@ in # changing them would not rebuild the manual nixosLabel = mkDefault (maybeEnv "NIXOS_LABEL" cfg.nixosVersion); nixosVersion = mkDefault (maybeEnv "NIXOS_VERSION" (cfg.nixosRelease + cfg.nixosVersionSuffix)); + nixosRevision = mkIf (pathIsDirectory gitRepo) (mkDefault gitCommitId); + nixosVersionSuffix = mkIf (pathIsDirectory gitRepo) (mkDefault (".git." + gitCommitId)); # Note: code names must only increase in alphabetical order. nixosCodeName = "Flounder"; diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 370220d253a5..be72c0ef29c0 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -79,6 +79,7 @@ ./programs/ssh.nix ./programs/ssmtp.nix ./programs/tmux.nix + ./programs/unity3d.nix ./programs/venus.nix ./programs/wvdial.nix ./programs/xfs_quota.nix @@ -109,6 +110,7 @@ ./services/audio/liquidsoap.nix ./services/audio/mpd.nix ./services/audio/mopidy.nix + ./services/audio/squeezelite.nix ./services/backup/almir.nix ./services/backup/bacula.nix ./services/backup/crashplan.nix @@ -124,9 +126,11 @@ ./services/computing/torque/server.nix ./services/computing/torque/mom.nix ./services/computing/slurm/slurm.nix + ./services/continuous-integration/buildkite-agent.nix + ./services/continuous-integration/hydra/default.nix ./services/continuous-integration/jenkins/default.nix - ./services/continuous-integration/jenkins/slave.nix ./services/continuous-integration/jenkins/job-builder.nix + ./services/continuous-integration/jenkins/slave.nix ./services/databases/4store-endpoint.nix ./services/databases/4store.nix ./services/databases/couchdb.nix @@ -216,6 +220,7 @@ ./services/misc/confd.nix ./services/misc/devmon.nix ./services/misc/dictd.nix + ./services/misc/dysnomia.nix ./services/misc/disnix.nix ./services/misc/docker-registry.nix ./services/misc/emby.nix @@ -312,6 +317,7 @@ ./services/networking/cntlm.nix ./services/networking/connman.nix ./services/networking/consul.nix + ./services/networking/coturn.nix ./services/networking/ddclient.nix ./services/networking/dhcpcd.nix ./services/networking/dhcpd.nix @@ -347,6 +353,7 @@ ./services/networking/mjpg-streamer.nix ./services/networking/minidlna.nix ./services/networking/miniupnpd.nix + ./services/networking/mosquitto.nix ./services/networking/mstpd.nix ./services/networking/murmur.nix ./services/networking/namecoind.nix @@ -366,6 +373,7 @@ ./services/networking/ostinato.nix ./services/networking/pdnsd.nix ./services/networking/polipo.nix + ./services/networking/pptpd.nix ./services/networking/prayer.nix ./services/networking/privoxy.nix ./services/networking/prosody.nix @@ -397,6 +405,7 @@ ./services/networking/tftpd.nix ./services/networking/tlsdated.nix ./services/networking/tox-bootstrapd.nix + ./services/networking/toxvpn.nix ./services/networking/tvheadend.nix ./services/networking/unbound.nix ./services/networking/unifi.nix @@ -406,6 +415,7 @@ ./services/networking/wicd.nix ./services/networking/wpa_supplicant.nix ./services/networking/xinetd.nix + ./services/networking/xl2tpd.nix ./services/networking/zerobin.nix ./services/networking/zerotierone.nix ./services/networking/znc.nix @@ -427,6 +437,7 @@ ./services/security/haveged.nix ./services/security/hologram.nix ./services/security/munge.nix + ./services/security/oauth2_proxy.nix ./services/security/physlock.nix ./services/security/torify.nix ./services/security/tor.nix @@ -451,6 +462,7 @@ ./services/web-servers/lighttpd/cgit.nix ./services/web-servers/lighttpd/default.nix ./services/web-servers/lighttpd/gitweb.nix + ./services/web-servers/lighttpd/inginious.nix ./services/web-servers/nginx/default.nix ./services/web-servers/phpfpm.nix ./services/web-servers/shellinabox.nix @@ -486,6 +498,7 @@ ./services/x11/window-managers/windowlab.nix ./services/x11/window-managers/wmii.nix ./services/x11/window-managers/xmonad.nix + ./services/x11/xbanish.nix ./services/x11/xfs.nix ./services/x11/xserver.nix ./system/activation/activation-script.nix @@ -502,10 +515,10 @@ ./system/boot/loader/grub/grub.nix ./system/boot/loader/grub/ipxe.nix ./system/boot/loader/grub/memtest.nix - ./system/boot/loader/gummiboot/gummiboot.nix ./system/boot/loader/init-script/init-script.nix ./system/boot/loader/loader.nix ./system/boot/loader/raspberrypi/raspberrypi.nix + ./system/boot/loader/systemd-boot/systemd-boot.nix ./system/boot/luksroot.nix ./system/boot/modprobe.nix ./system/boot/networkd.nix diff --git a/nixos/modules/programs/bash/bash.nix b/nixos/modules/programs/bash/bash.nix index e4e264ec0036..c09bcfb70e24 100644 --- a/nixos/modules/programs/bash/bash.nix +++ b/nixos/modules/programs/bash/bash.nix @@ -200,7 +200,7 @@ in # Configuration for readline in bash. environment.etc."inputrc".source = ./inputrc; - users.defaultUserShell = mkDefault "/run/current-system/sw/bin/bash"; + users.defaultUserShell = mkDefault pkgs.bashInteractive; environment.pathsToLink = optionals cfg.enableCompletion [ "/etc/bash_completion.d" diff --git a/nixos/modules/programs/fish.nix b/nixos/modules/programs/fish.nix index 7a4b78118ce6..a99c98e166dc 100644 --- a/nixos/modules/programs/fish.nix +++ b/nixos/modules/programs/fish.nix @@ -84,19 +84,19 @@ in set fish_function_path $fish_function_path ${pkgs.fish-foreign-env}/share/fish-foreign-env/functions - fenv source ${config.system.build.setEnvironment} 1> /dev/null - fenv source /etc/fish/foreign-env/shellInit 1> /dev/null + fenv source ${config.system.build.setEnvironment} > /dev/null ^&1 + fenv source /etc/fish/foreign-env/shellInit > /dev/null ${cfg.shellInit} - if builtin status --is-login - fenv source /etc/fish/foreign-env/loginShellInit 1> /dev/null + if status --is-login + fenv source /etc/fish/foreign-env/loginShellInit > /dev/null ${cfg.loginShellInit} end - if builtin status --is-interactive + if status --is-interactive ${fishAliases} - fenv source /etc/fish/foreign-env/interactiveShellInit 1> /dev/null + fenv source /etc/fish/foreign-env/interactiveShellInit > /dev/null ${cfg.interactiveShellInit} end ''; diff --git a/nixos/modules/programs/man.nix b/nixos/modules/programs/man.nix index 201144ccb451..e59ffd6f936d 100644 --- a/nixos/modules/programs/man.nix +++ b/nixos/modules/programs/man.nix @@ -19,7 +19,7 @@ with lib; config = mkIf config.programs.man.enable { - environment.systemPackages = [ pkgs.man ]; + environment.systemPackages = [ pkgs.man-db ]; environment.pathsToLink = [ "/share/man" ]; diff --git a/nixos/modules/programs/shadow.nix b/nixos/modules/programs/shadow.nix index 566398d839fd..6398509357a6 100644 --- a/nixos/modules/programs/shadow.nix +++ b/nixos/modules/programs/shadow.nix @@ -1,6 +1,6 @@ # Configuration for the pwdutils suite of tools: passwd, useradd, etc. -{ config, lib, pkgs, ... }: +{ config, lib, utils, pkgs, ... }: with lib; @@ -43,13 +43,13 @@ in users.defaultUserShell = lib.mkOption { description = '' This option defines the default shell assigned to user - accounts. This must not be a store path, since the path is + accounts. This can be either a full system path or a shell package. + + This must not be a store path, since the path is used outside the store (in particular in /etc/passwd). - Rather, it should be the path of a symlink that points to the - actual shell in the Nix store. ''; - example = "/run/current-system/sw/bin/zsh"; - type = types.path; + example = literalExample "pkgs.zsh"; + type = types.either types.path types.shellPackage; }; }; @@ -60,7 +60,9 @@ in config = { environment.systemPackages = - lib.optional config.users.mutableUsers pkgs.shadow; + lib.optional config.users.mutableUsers pkgs.shadow ++ + lib.optional (types.shellPackage.check config.users.defaultUserShell) + config.users.defaultUserShell; environment.etc = [ { # /etc/login.defs: global configuration for pwdutils. You @@ -74,7 +76,7 @@ in '' GROUP=100 HOME=/home - SHELL=${config.users.defaultUserShell} + SHELL=${utils.toShellPath config.users.defaultUserShell} ''; target = "default/useradd"; } diff --git a/nixos/modules/programs/tmux.nix b/nixos/modules/programs/tmux.nix index 2fc1ed63cb36..cadf8d4ae105 100644 --- a/nixos/modules/programs/tmux.nix +++ b/nixos/modules/programs/tmux.nix @@ -156,8 +156,13 @@ in { config = mkIf cfg.enable { environment = { - systemPackages = [ pkgs.tmux ]; etc."tmux.conf".text = tmuxConf; + + systemPackages = [ pkgs.tmux ]; + + variables = { + TMUX_TMPDIR = ''''${XDG_RUNTIME_DIR:-"/run/user/\$(id -u)"}''; + }; }; }; } diff --git a/nixos/modules/programs/unity3d.nix b/nixos/modules/programs/unity3d.nix new file mode 100644 index 000000000000..3c0ea26d9d56 --- /dev/null +++ b/nixos/modules/programs/unity3d.nix @@ -0,0 +1,25 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let cfg = config.programs.unity3d; +in { + + options = { + programs.unity3d.enable = mkEnableOption "Unity3D, a game development tool"; + }; + + config = mkIf cfg.enable { + security.setuidOwners = [{ + program = "unity-chrome-sandbox"; + source = "${pkgs.unity3d.sandbox}/bin/unity-chrome-sandbox"; + owner = "root"; + #group = "root"; + setuid = true; + #setgid = true; + }]; + + environment.systemPackages = [ pkgs.unity3d ]; + }; + +} diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix index 2f37f180c7ec..634f91a275d3 100644 --- a/nixos/modules/rename.nix +++ b/nixos/modules/rename.nix @@ -34,6 +34,8 @@ with lib; # Old Grub-related options. (mkRenamedOptionModule [ "boot" "initrd" "extraKernelModules" ] [ "boot" "initrd" "kernelModules" ]) (mkRenamedOptionModule [ "boot" "extraKernelParams" ] [ "boot" "kernelParams" ]) + (mkRenamedOptionModule [ "boot" "loader" "grub" "timeout" ] [ "boot" "loader" "timeout" ]) + (mkRenamedOptionModule [ "boot" "loader" "gummiboot" "timeout" ] [ "boot" "loader" "timeout" ]) # smartd (mkRenamedOptionModule [ "services" "smartd" "deviceOpts" ] [ "services" "smartd" "defaults" "monitored" ]) @@ -112,6 +114,26 @@ with lib; (mkRenamedOptionModule [ "services" "iodined" "extraConfig" ] [ "services" "iodine" "server" "extraConfig" ]) (mkRemovedOptionModule [ "services" "iodined" "client" ]) + # Grsecurity + (mkRemovedOptionModule [ "security" "grsecurity" "kernelPatch" ]) + (mkRemovedOptionModule [ "security" "grsecurity" "config" "mode" ]) + (mkRemovedOptionModule [ "security" "grsecurity" "config" "priority" ]) + (mkRemovedOptionModule [ "security" "grsecurity" "config" "system" ]) + (mkRemovedOptionModule [ "security" "grsecurity" "config" "virtualisationConfig" ]) + (mkRemovedOptionModule [ "security" "grsecurity" "config" "hardwareVirtualisation" ]) + (mkRemovedOptionModule [ "security" "grsecurity" "config" "virtualisationSoftware" ]) + (mkRemovedOptionModule [ "security" "grsecurity" "config" "sysctl" ]) + (mkRemovedOptionModule [ "security" "grsecurity" "config" "denyChrootChmod" ]) + (mkRemovedOptionModule [ "security" "grsecurity" "config" "denyChrootCaps" ]) + (mkRemovedOptionModule [ "security" "grsecurity" "config" "denyUSB" ]) + (mkRemovedOptionModule [ "security" "grsecurity" "config" "restrictProc" ]) + (mkRemovedOptionModule [ "security" "grsecurity" "config" "restrictProcWithGroup" ]) + (mkRemovedOptionModule [ "security" "grsecurity" "config" "unrestrictProcGid" ]) + (mkRemovedOptionModule [ "security" "grsecurity" "config" "disableRBAC" ]) + (mkRemovedOptionModule [ "security" "grsecurity" "config" "disableSimultConnect" ]) + (mkRemovedOptionModule [ "security" "grsecurity" "config" "verboseVersion" ]) + (mkRemovedOptionModule [ "security" "grsecurity" "config" "kernelExtraConfig" ]) + # Options that are obsolete and have no replacement. (mkRemovedOptionModule [ "boot" "initrd" "luks" "enable" ]) (mkRemovedOptionModule [ "programs" "bash" "enable" ]) diff --git a/nixos/modules/security/acme.nix b/nixos/modules/security/acme.nix index cb5410a5f15d..f646602221a4 100644 --- a/nixos/modules/security/acme.nix +++ b/nixos/modules/security/acme.nix @@ -114,6 +114,19 @@ in ''; }; + preliminarySelfsigned = mkOption { + type = types.bool; + default = true; + description = '' + Whether a preliminary self-signed certificate should be generated before + doing ACME requests. This can be useful when certificates are required in + a webserver, but ACME needs the webserver to make its requests. + + With preliminary self-signed certificate the webserver can be started and + can later reload the correct ACME certificates. + ''; + }; + certs = mkOption { default = { }; type = types.loaOf types.optionSet; @@ -140,54 +153,126 @@ in config = mkMerge [ (mkIf (cfg.certs != { }) { - systemd.services = flip mapAttrs' cfg.certs (cert: data: - let - cpath = "${cfg.directory}/${cert}"; - rights = if data.allowKeysForGroup then "750" else "700"; - cmdline = [ "-v" "-d" cert "--default_root" data.webroot "--valid_min" cfg.validMin ] - ++ optionals (data.email != null) [ "--email" data.email ] - ++ concatMap (p: [ "-f" p ]) data.plugins - ++ concatLists (mapAttrsToList (name: root: [ "-d" (if root == null then name else "${name}:${root}")]) data.extraDomains); + systemd.services = let + services = concatLists servicesLists; + servicesLists = mapAttrsToList certToServices cfg.certs; + certToServices = cert: data: + let + cpath = "${cfg.directory}/${cert}"; + rights = if data.allowKeysForGroup then "750" else "700"; + cmdline = [ "-v" "-d" cert "--default_root" data.webroot "--valid_min" cfg.validMin ] + ++ optionals (data.email != null) [ "--email" data.email ] + ++ concatMap (p: [ "-f" p ]) data.plugins + ++ concatLists (mapAttrsToList (name: root: [ "-d" (if root == null then name else "${name}:${root}")]) data.extraDomains); + acmeService = { + description = "Renew ACME Certificate for ${cert}"; + after = [ "network.target" ]; + serviceConfig = { + Type = "oneshot"; + SuccessExitStatus = [ "0" "1" ]; + PermissionsStartOnly = true; + User = data.user; + Group = data.group; + PrivateTmp = true; + }; + path = [ pkgs.simp_le ]; + preStart = '' + mkdir -p '${cfg.directory}' + if [ ! -d '${cpath}' ]; then + mkdir '${cpath}' + fi + chmod ${rights} '${cpath}' + chown -R '${data.user}:${data.group}' '${cpath}' + ''; + script = '' + cd '${cpath}' + set +e + simp_le ${escapeShellArgs cmdline} + EXITCODE=$? + set -e + echo "$EXITCODE" > /tmp/lastExitCode + exit "$EXITCODE" + ''; + postStop = '' + if [ -e /tmp/lastExitCode ] && [ "$(cat /tmp/lastExitCode)" = "0" ]; then + echo "Executing postRun hook..." + ${data.postRun} + fi + ''; - in nameValuePair - ("acme-${cert}") - ({ - description = "Renew ACME Certificate for ${cert}"; - after = [ "network.target" ]; - serviceConfig = { - Type = "oneshot"; - SuccessExitStatus = [ "0" "1" ]; - PermissionsStartOnly = true; - User = data.user; - Group = data.group; - PrivateTmp = true; + before = [ "acme-certificates.target" ]; + wantedBy = [ "acme-certificates.target" ]; + }; + selfsignedService = { + description = "Create preliminary self-signed certificate for ${cert}"; + preStart = '' + if [ ! -d '${cpath}' ] + then + mkdir -p '${cpath}' + chmod ${rights} '${cpath}' + chown '${data.user}:${data.group}' '${cpath}' + fi + ''; + script = + '' + # Create self-signed key + workdir="/run/acme-selfsigned-${cert}" + ${pkgs.openssl.bin}/bin/openssl genrsa -des3 -passout pass:x -out $workdir/server.pass.key 2048 + ${pkgs.openssl.bin}/bin/openssl rsa -passin pass:x -in $workdir/server.pass.key -out $workdir/server.key + ${pkgs.openssl.bin}/bin/openssl req -new -key $workdir/server.key -out $workdir/server.csr \ + -subj "/C=UK/ST=Warwickshire/L=Leamington/O=OrgName/OU=IT Department/CN=example.com" + ${pkgs.openssl.bin}/bin/openssl x509 -req -days 1 -in $workdir/server.csr -signkey $workdir/server.key -out $workdir/server.crt + + # Move key to destination + mv $workdir/server.key ${cpath}/key.pem + mv $workdir/server.crt ${cpath}/fullchain.pem + + # Clean up working directory + rm $workdir/server.csr + rm $workdir/server.pass.key + + # Give key acme permissions + chmod ${rights} '${cpath}/key.pem' + chown '${data.user}:${data.group}' '${cpath}/key.pem' + chmod ${rights} '${cpath}/fullchain.pem' + chown '${data.user}:${data.group}' '${cpath}/fullchain.pem' + ''; + serviceConfig = { + Type = "oneshot"; + RuntimeDirectory = "acme-selfsigned-${cert}"; + PermissionsStartOnly = true; + User = data.user; + Group = data.group; + }; + unitConfig = { + # Do not create self-signed key when key already exists + ConditionPathExists = "!${cpath}/key.pem"; + }; + before = [ + "acme-selfsigned-certificates.target" + ]; + wantedBy = [ + "acme-selfsigned-certificates.target" + ]; + }; + in ( + [ { name = "acme-${cert}"; value = acmeService; } ] + ++ + (if cfg.preliminarySelfsigned + then [ { name = "acme-selfsigned-${cert}"; value = selfsignedService; } ] + else [] + ) + ); + servicesAttr = listToAttrs services; + nginxAttr = { + nginx = { + after = [ "acme-selfsigned-certificates.target" ]; + wants = [ "acme-selfsigned-certificates.target" "acme-certificates.target" ]; + }; }; - path = [ pkgs.simp_le ]; - preStart = '' - mkdir -p '${cfg.directory}' - if [ ! -d '${cpath}' ]; then - mkdir '${cpath}' - fi - chmod ${rights} '${cpath}' - chown -R '${data.user}:${data.group}' '${cpath}' - ''; - script = '' - cd '${cpath}' - set +e - simp_le ${concatMapStringsSep " " (arg: escapeShellArg (toString arg)) cmdline} - EXITCODE=$? - set -e - echo "$EXITCODE" > /tmp/lastExitCode - exit "$EXITCODE" - ''; - postStop = '' - if [ -e /tmp/lastExitCode ] && [ "$(cat /tmp/lastExitCode)" = "0" ]; then - echo "Executing postRun hook..." - ${data.postRun} - fi - ''; - }) - ); + in + servicesAttr // + (if config.services.nginx.enable then nginxAttr else {}); systemd.timers = flip mapAttrs' cfg.certs (cert: data: nameValuePair ("acme-${cert}") @@ -200,6 +285,9 @@ in }; }) ); + + systemd.targets."acme-selfsigned-certificates" = mkIf cfg.preliminarySelfsigned {}; + systemd.targets."acme-certificates" = {}; }) { meta.maintainers = with lib.maintainers; [ abbradar fpletz globin ]; diff --git a/nixos/modules/security/acme.xml b/nixos/modules/security/acme.xml index e32fa72c9393..15ed4c04a23d 100644 --- a/nixos/modules/security/acme.xml +++ b/nixos/modules/security/acme.xml @@ -66,4 +66,32 @@ options for the <literal>security.acme</literal> module.</para> </section> +<section><title>Using ACME certificates in Nginx</title> +<para>In practice ACME is mostly used for retrieval and renewal of + certificates that will be used in a webserver like Nginx. A configuration for + Nginx that uses the certificates from ACME for + <literal>foo.example.com</literal> will look similar to: +</para> + +<programlisting> +services.nginx.httpConfig = '' + server { + server_name foo.example.com; + listen 443 ssl; + ssl_certificate ${config.security.acme.directory}/foo.example.com/fullchain.pem; + ssl_certificate_key ${config.security.acme.directory}/foo.example.com/key.pem; + root /var/www/foo.example.com/; + } +''; +</programlisting> + +<para>Now Nginx will try to use the certificates that will be retrieved by ACME. + ACME needs Nginx (or any other webserver) to function and Nginx needs + the certificates to actually start. For this reason the ACME module + automatically generates self-signed certificates that will be used by Nginx to + start. After that Nginx is used by ACME to retrieve the actual ACME + certificates. <literal>security.acme.preliminarySelfsigned</literal> can be + used to control whether to generate the self-signed certificates. +</para> +</section> </chapter> diff --git a/nixos/modules/security/grsecurity.nix b/nixos/modules/security/grsecurity.nix index 3f24118ea1cb..9d0249820d5d 100644 --- a/nixos/modules/security/grsecurity.nix +++ b/nixos/modules/security/grsecurity.nix @@ -1,312 +1,122 @@ -{ config, lib, pkgs, ... }: +{ config, pkgs, lib, ... }: with lib; let cfg = config.security.grsecurity; - - customGrsecPkg = - (import ../../../pkgs/build-support/grsecurity { - grsecOptions = cfg; - inherit pkgs lib; - }).grsecPackage; + grsecLockPath = "/proc/sys/kernel/grsecurity/grsec_lock"; + + # Ascertain whether ZFS is required for booting the system; grsecurity is + # currently incompatible with ZFS, rendering the system unbootable. + zfsNeededForBoot = filter + (fs: (fs.neededForBoot + || elem fs.mountPoint [ "/" "/nix" "/nix/store" "/var" "/var/log" "/var/lib" "/etc" ]) + && fs.fsType == "zfs") + (attrValues config.fileSystems) != []; in -{ - options = { - security.grsecurity = { - enable = mkOption { - type = types.bool; - default = false; - description = '' - Enable grsecurity support. This enables advanced exploit - hardening for the Linux kernel, and adds support for - administrative Role-Based Acess Control (RBAC) via - <literal>gradm</literal>. It also includes traditional - utilities for PaX. - ''; - }; - - kernelPatch = mkOption { - type = types.attrs; - example = lib.literalExample "pkgs.kernelPatches.grsecurity_4_1"; - description = '' - Grsecurity patch to use. - ''; - }; - - config = { - mode = mkOption { - type = types.enum [ "auto" "custom" ]; - default = "auto"; - description = '' - grsecurity configuration mode. This specifies whether - grsecurity is auto-configured or otherwise completely - manually configured. - ''; - }; - - priority = mkOption { - type = types.enum [ "security" "performance" ]; - default = "security"; - description = '' - grsecurity configuration priority. This specifies whether - the kernel configuration should emphasize speed or - security. - ''; - }; - - system = mkOption { - type = types.enum [ "desktop" "server" ]; - default = "desktop"; - description = '' - grsecurity system configuration. - ''; - }; - virtualisationConfig = mkOption { - type = types.nullOr (types.enum [ "host" "guest" ]); - default = null; - description = '' - grsecurity virtualisation configuration. This specifies - the virtualisation role of the machine - that is, whether - it will be a virtual machine guest, a virtual machine - host, or neither. - ''; - }; - - hardwareVirtualisation = mkOption { - type = types.nullOr types.bool; - default = null; - example = true; - description = '' - grsecurity hardware virtualisation configuration. Set to - <literal>true</literal> if your machine supports hardware - accelerated virtualisation. - ''; - }; - - virtualisationSoftware = mkOption { - type = types.nullOr (types.enum [ "kvm" "xen" "vmware" "virtualbox" ]); - default = null; - description = '' - Configure grsecurity for use with this virtualisation software. - ''; - }; - - sysctl = mkOption { - type = types.bool; - default = false; - description = '' - If true, then set <literal>GRKERN_SYSCTL y</literal>. If - enabled then grsecurity can be controlled using sysctl - (and turned off). You are advised to *never* enable this, - but if you do, make sure to always set the sysctl - <literal>kernel.grsecurity.grsec_lock</literal> to - non-zero as soon as all sysctl options are set. *THIS IS - EXTREMELY IMPORTANT*! - ''; - }; - - denyChrootChmod = mkOption { - type = types.bool; - default = false; - description = '' - If true, then set <literal>GRKERN_CHROOT_CHMOD - y</literal>. If enabled, this denies processes inside a - chroot from setting the suid or sgid bits using - <literal>chmod</literal> or <literal>fchmod</literal>. - - By default this protection is disabled - it makes it - impossible to use Nix to build software on your system, - which is what most users want. +{ + options.security.grsecurity = { + + enable = mkEnableOption "Grsecurity/PaX"; + + lockTunables = mkOption { + type = types.bool; + example = false; + default = true; + description = '' + Whether to automatically lock grsecurity tunables + (<option>boot.kernel.sysctl."kernel.grsecurity.*"</option>). Disable + this to allow configuration of grsecurity features while the system is + running. The lock can be manually engaged by activating the + <literal>grsec-lock</literal> service unit. + ''; + }; - If you are using NixOps to deploy your software to a - remote machine, you're encouraged to enable this as you - won't need to compile code. - ''; - }; + }; - denyChrootCaps = mkOption { - type = types.bool; - default = false; - description = '' - Whether to lower capabilities of all processes within a chroot, - preventing commands that require <literal>CAP_SYS_ADMIN</literal>. + config = mkIf cfg.enable { - This protection is disabled by default because it breaks - <literal>nixos-rebuild</literal>. Whenever possible, it is - highly recommended to enable this protection. - ''; - }; + # Allow the user to select a different package set, subject to the stated + # required kernel config + boot.kernelPackages = mkDefault pkgs.linuxPackages_grsec_nixos; - denyUSB = mkOption { - type = types.bool; - default = false; - description = '' - If true, then set <literal>GRKERNSEC_DENYUSB y</literal>. + system.requiredKernelConfig = with config.lib.kernelConfig; + [ (isEnabled "GRKERNSEC") + (isEnabled "PAX") + (isYES "GRKERNSEC_SYSCTL") + (isYES "GRKERNSEC_SYSCTL_DISTRO") + ]; - This enables a sysctl with name - <literal>kernel.grsecurity.deny_new_usb</literal>. Setting - its value to <literal>1</literal> will prevent any new USB - devices from being recognized by the OS. Any attempted - USB device insertion will be logged. + # Crashing on an overflow in kernel land is user unfriendly and may prevent + # the system from booting, which is too severe for our use case. + boot.kernelParams = [ "pax_size_overflow_report_only" ]; - This option is intended to be used against custom USB - devices designed to exploit vulnerabilities in various USB - device drivers. - ''; - }; + # Install PaX related utillities into the system profile. Eventually, we + # also want to include gradm here. + environment.systemPackages = with pkgs; [ paxctl pax-utils ]; - restrictProc = mkOption { - type = types.bool; - default = false; - description = '' - If true, then set <literal>GRKERN_PROC_USER - y</literal>. This restricts non-root users to only viewing - their own processes and restricts network-related - information, kernel symbols, and module information. - ''; - }; + # Install rules for the grsec device node + services.udev.packages = [ pkgs.gradm ]; - restrictProcWithGroup = mkOption { - type = types.bool; - default = true; - description = '' - If true, then set <literal>GRKERN_PROC_USERGROUP - y</literal>. This is similar to - <literal>restrictProc</literal> except it allows a special - group (specified by <literal>unrestrictProcGid</literal>) - to still access otherwise classified information in - <literal>/proc</literal>. - ''; - }; + # This service unit is responsible for locking the Grsecurity tunables. The + # unit is always defined, but only activated on bootup if lockTunables is + # toggled. When lockTunables is toggled, failure to activate the unit will + # enter emergency mode. The intent is to make it difficult to silently + # enter multi-user mode without having locked the tunables. Some effort is + # made to ensure that starting the unit is an idempotent operation. + systemd.services.grsec-lock = { + description = "Lock grsecurity tunables"; - unrestrictProcGid = mkOption { - type = types.int; - default = config.ids.gids.grsecurity; - description = '' - If set, specifies a GID which is exempt from - <literal>/proc</literal> restrictions (set by - <literal>GRKERN_PROC_USERGROUP</literal>). By default, - this is set to the GID for <literal>grsecurity</literal>, - a predefined NixOS group, which the - <literal>root</literal> account is a member of. You may - conveniently add other users to this group if you need - access to <literal>/proc</literal> - ''; - }; + wantedBy = optional cfg.lockTunables "multi-user.target"; - disableRBAC = mkOption { - type = types.bool; - default = false; - description = '' - If true, then set <literal>GRKERN_NO_RBAC - y</literal>. This disables the - <literal>/dev/grsec</literal> device, which in turn - disables the RBAC system (and <literal>gradm</literal>). - ''; - }; + wants = [ "local-fs.target" "systemd-sysctl.service" ]; + after = [ "local-fs.target" "systemd-sysctl.service" ]; + conflicts = [ "shutdown.target" ]; - disableSimultConnect = mkOption { - type = types.bool; - default = false; - description = '' - Disable TCP simultaneous connect. The TCP simultaneous connect - feature allows two clients to connect without either of them - entering the listening state. This feature of the TCP specification - is claimed to enable an attacker to deny the target access to a given - server by guessing the source port the target would use to make the - connection. + restartIfChanged = false; - This option is OFF by default because TCP simultaneous connect has - some legitimate uses. Enable this option if you know what this TCP - feature is for and know that you do not need it. - ''; - }; + script = '' + if ${pkgs.gnugrep}/bin/grep -Fq 0 ${grsecLockPath} ; then + echo -n 1 > ${grsecLockPath} + fi + ''; - verboseVersion = mkOption { - type = types.bool; - default = false; - description = "Use verbose version in kernel localversion."; - }; + unitConfig = { + ConditionPathIsReadWrite = grsecLockPath; + DefaultDependencies = false; + } // optionalAttrs cfg.lockTunables { + OnFailure = "emergency.target"; + }; - kernelExtraConfig = mkOption { - type = types.str; - default = ""; - description = "Extra kernel configuration parameters."; - }; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; }; }; - }; - config = mkIf cfg.enable { - assertions = - [ - { assertion = (cfg.config.restrictProc -> !cfg.config.restrictProcWithGroup) || - (cfg.config.restrictProcWithGroup -> !cfg.config.restrictProc); - message = "You cannot enable both restrictProc and restrictProcWithGroup"; - } - { assertion = config.boot.kernelPackages.kernel.features ? grsecurity - && config.boot.kernelPackages.kernel.features.grsecurity; - message = "grsecurity enabled, but kernel doesn't have grsec support"; - } - { assertion = (cfg.config.mode == "auto" && (cfg.config.virtualisationConfig != null)) -> - cfg.config.hardwareVirtualisation != null; - message = "when using auto grsec mode with virtualisation, you must specify if your hardware has virtualisation extensions"; - } - { assertion = (cfg.config.mode == "auto" && (cfg.config.virtualisationConfig != null)) -> - cfg.config.virtualisationSoftware != null; - message = "grsecurity configured for virtualisation but no virtualisation software specified"; - } - ]; - - security.grsecurity.kernelPatch = lib.mkDefault pkgs.kernelPatches.grsecurity_latest; - - systemd.services.grsec-lock = mkIf cfg.config.sysctl { - description = "grsecurity sysctl-lock Service"; - wants = [ "systemd-sysctl.service" ]; - after = [ "systemd-sysctl.service" ]; - wantedBy = [ "multi-user.target" ]; - serviceConfig.Type = "oneshot"; - serviceConfig.RemainAfterExit = "yes"; - unitConfig.ConditionPathIsReadWrite = "/proc/sys/kernel/grsecurity/grsec_lock"; - script = '' - locked=`cat /proc/sys/kernel/grsecurity/grsec_lock` - if [ "$locked" == "0" ]; then - echo 1 > /proc/sys/kernel/grsecurity/grsec_lock - echo grsecurity sysctl lock - enabled - else - echo grsecurity sysctl lock already enabled - doing nothing - fi - ''; + # Configure system tunables + boot.kernel.sysctl = { + # Removed under grsecurity + "kernel.kptr_restrict" = mkForce null; + } // optionalAttrs config.nix.useSandbox { + # chroot(2) restrictions that conflict with sandboxed Nix builds + "kernel.grsecurity.chroot_caps" = mkForce 0; + "kernel.grsecurity.chroot_deny_chroot" = mkForce 0; + "kernel.grsecurity.chroot_deny_mount" = mkForce 0; + "kernel.grsecurity.chroot_deny_pivot" = mkForce 0; + } // optionalAttrs config.boot.enableContainers { + # chroot(2) restrictions that conflict with NixOS lightweight containers + "kernel.grsecurity.chroot_deny_chmod" = mkForce 0; + "kernel.grsecurity.chroot_deny_mount" = mkForce 0; + "kernel.grsecurity.chroot_restrict_nice" = mkForce 0; }; -# systemd.services.grsec-learn = { -# description = "grsecurity learning Service"; -# wantedBy = [ "local-fs.target" ]; -# serviceConfig = { -# Type = "oneshot"; -# RemainAfterExit = "yes"; -# ExecStart = "${pkgs.gradm}/sbin/gradm -VFL /etc/grsec/learning.logs"; -# ExecStop = "${pkgs.gradm}/sbin/gradm -D"; -# }; -# }; - - system.activationScripts = lib.optionalAttrs (!cfg.config.disableRBAC) { grsec = '' - mkdir -p /etc/grsec - if [ ! -f /etc/grsec/learn_config ]; then - cp ${pkgs.gradm}/etc/grsec/learn_config /etc/grsec - fi - if [ ! -f /etc/grsec/policy ]; then - cp ${pkgs.gradm}/etc/grsec/policy /etc/grsec - fi - chmod -R 0600 /etc/grsec - ''; }; + assertions = [ + { assertion = !zfsNeededForBoot; + message = "grsecurity is currently incompatible with ZFS"; + } + ]; - # Enable AppArmor, gradm udev rules, and utilities - security.apparmor.enable = true; - boot.kernelPackages = customGrsecPkg; - services.udev.packages = lib.optional (!cfg.config.disableRBAC) pkgs.gradm; - environment.systemPackages = [ pkgs.paxctl pkgs.pax-utils ] ++ lib.optional (!cfg.config.disableRBAC) pkgs.gradm; }; } diff --git a/nixos/modules/security/setuid-wrappers.nix b/nixos/modules/security/setuid-wrappers.nix index 7d69f9b1183d..99dd514feea3 100644 --- a/nixos/modules/security/setuid-wrappers.nix +++ b/nixos/modules/security/setuid-wrappers.nix @@ -96,7 +96,7 @@ in }: '' - if ! source=${if source != "" then source else "$(PATH=$SETUID_PATH type -tP ${program})"}; then + if ! source=${if source != "" then source else "$(readlink -f $(PATH=$SETUID_PATH type -tP ${program}))"}; then # If we can't find the program, fall back to the # system profile. source=/nix/var/nix/profiles/default/bin/${program} diff --git a/nixos/modules/services/audio/squeezelite.nix b/nixos/modules/services/audio/squeezelite.nix new file mode 100644 index 000000000000..f1a60be992d8 --- /dev/null +++ b/nixos/modules/services/audio/squeezelite.nix @@ -0,0 +1,67 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + uid = config.ids.uids.squeezelite; + cfg = config.services.squeezelite; + +in { + + ###### interface + + options = { + + services.squeezelite= { + + enable = mkEnableOption "Squeezelite, a software Squeezebox emulator"; + + dataDir = mkOption { + default = "/var/lib/squeezelite"; + type = types.str; + description = '' + The directory where Squeezelite stores its name file. + ''; + }; + + extraArguments = mkOption { + default = ""; + type = types.str; + description = '' + Additional command line arguments to pass to Squeezelite. + ''; + }; + + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + systemd.services.squeezelite= { + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" "sound.target" ]; + description = "Software Squeezebox emulator"; + preStart = "mkdir -p ${cfg.dataDir} && chown -R squeezelite ${cfg.dataDir}"; + serviceConfig = { + ExecStart = "${pkgs.squeezelite}/bin/squeezelite -N ${cfg.dataDir}/player-name ${cfg.extraArguments}"; + User = "squeezelite"; + PermissionsStartOnly = true; + }; + }; + + users.extraUsers.squeezelite= { + inherit uid; + group = "nogroup"; + extraGroups = [ "audio" ]; + description = "Squeezelite user"; + home = "${cfg.dataDir}"; + }; + + }; + +} diff --git a/nixos/modules/services/computing/slurm/slurm.nix b/nixos/modules/services/computing/slurm/slurm.nix index ad8836f40094..ee38a42199ee 100644 --- a/nixos/modules/services/computing/slurm/slurm.nix +++ b/nixos/modules/services/computing/slurm/slurm.nix @@ -40,7 +40,7 @@ in defaultText = "pkgs.slurm-llnl"; example = literalExample "pkgs.slurm-llnl-full"; description = '' - The packge to use for slurm binaries. + The package to use for slurm binaries. ''; }; @@ -111,7 +111,7 @@ in builder = pkgs.writeText "builder.sh" '' source $stdenv/setup mkdir -p $out/bin - find ${cfg.package}/bin -type f -executable | while read EXE + find ${getBin cfg.package}/bin -type f -executable | while read EXE do exename="$(basename $EXE)" wrappername="$out/bin/$exename" diff --git a/nixos/modules/services/continuous-integration/buildkite-agent.nix b/nixos/modules/services/continuous-integration/buildkite-agent.nix new file mode 100644 index 000000000000..b1449882b04f --- /dev/null +++ b/nixos/modules/services/continuous-integration/buildkite-agent.nix @@ -0,0 +1,100 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.buildkite-agent; + configFile = pkgs.writeText "buildkite-agent.cfg" + '' + token="${cfg.token}" + name="${cfg.name}" + meta-data="${cfg.meta-data}" + hooks-path="${pkgs.buildkite-agent}/share/hooks" + build-path="/var/lib/buildkite-agent/builds" + bootstrap-script="${pkgs.buildkite-agent}/share/bootstrap.sh" + ''; +in + +{ + options = { + services.buildkite-agent = { + enable = mkEnableOption "buildkite-agent"; + + token = mkOption { + type = types.str; + description = '' + The token from your Buildkite "Agents" page. + ''; + }; + + name = mkOption { + type = types.str; + description = '' + The name of the agent. + ''; + }; + + meta-data = mkOption { + type = types.str; + default = ""; + description = '' + Meta data for the agent. + ''; + }; + + openssh = + { privateKey = mkOption { + type = types.str; + description = '' + Private agent key. + ''; + }; + publicKey = mkOption { + type = types.str; + description = '' + Public agent key. + ''; + }; + }; + }; + }; + + config = mkIf config.services.buildkite-agent.enable { + users.extraUsers.buildkite-agent = + { name = "buildkite-agent"; + home = "/var/lib/buildkite-agent"; + createHome = true; + description = "Buildkite agent user"; + }; + + environment.systemPackages = [ pkgs.buildkite-agent ]; + + systemd.services.buildkite-agent = + { description = "Buildkite Agent"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + environment.HOME = "/var/lib/buildkite-agent"; + preStart = '' + ${pkgs.coreutils}/bin/mkdir -m 0700 -p /var/lib/buildkite-agent/.ssh + + if ! [ -f /var/lib/buildkite-agent/.ssh/id_rsa ]; then + echo "${cfg.openssh.privateKey}" > /var/lib/buildkite-agent/.ssh/id_rsa + ${pkgs.coreutils}/bin/chmod 600 /var/lib/buildkite-agent/.ssh/id_rsa + fi + + if ! [ -f /var/lib/buildkite-agent/.ssh/id_rsa.pub ]; then + echo "${cfg.openssh.publicKey}" > /var/lib/buildkite-agent/.ssh/id_rsa.pub + ${pkgs.coreutils}/bin/chmod 600 /var/lib/buildkite-agent/.ssh/id_rsa.pub + fi + ''; + + serviceConfig = + { ExecStart = "${pkgs.buildkite-agent}/bin/buildkite-agent start --config ${configFile}"; + User = "buildkite-agent"; + RestartSec = 5; + Restart = "on-failure"; + TimeoutSec = 10; + }; + }; + }; +} diff --git a/nixos/modules/services/continuous-integration/hydra/default.nix b/nixos/modules/services/continuous-integration/hydra/default.nix new file mode 100644 index 000000000000..c8edfaf18537 --- /dev/null +++ b/nixos/modules/services/continuous-integration/hydra/default.nix @@ -0,0 +1,418 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + + cfg = config.services.hydra; + + baseDir = "/var/lib/hydra"; + + hydraConf = pkgs.writeScript "hydra.conf" cfg.extraConfig; + + hydraEnv = + { HYDRA_DBI = cfg.dbi; + HYDRA_CONFIG = "${baseDir}/hydra.conf"; + HYDRA_DATA = "${baseDir}"; + }; + + env = + { NIX_REMOTE = "daemon"; + SSL_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt"; # Remove in 16.03 + PGPASSFILE = "${baseDir}/pgpass"; + NIX_REMOTE_SYSTEMS = concatStringsSep ":" cfg.buildMachinesFiles; + } // optionalAttrs (cfg.smtpHost != null) { + EMAIL_SENDER_TRANSPORT = "SMTP"; + EMAIL_SENDER_TRANSPORT_host = cfg.smtpHost; + } // hydraEnv // cfg.extraEnv; + + serverEnv = env // + { HYDRA_TRACKER = cfg.tracker; + COLUMNS = "80"; + PGPASSFILE = "${baseDir}/pgpass-www"; # grrr + } // (optionalAttrs cfg.debugServer { DBIC_TRACE = "1"; }); + + localDB = "dbi:Pg:dbname=hydra;user=hydra;"; + + haveLocalDB = cfg.dbi == localDB; + +in + +{ + ###### interface + options = { + + services.hydra = rec { + + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to run Hydra services. + ''; + }; + + dbi = mkOption { + type = types.str; + default = localDB; + example = "dbi:Pg:dbname=hydra;host=postgres.example.org;user=foo;"; + description = '' + The DBI string for Hydra database connection. + ''; + }; + + package = mkOption { + type = types.path; + default = pkgs.hydra; + defaultText = "pkgs.hydra"; + description = "The Hydra package."; + }; + + hydraURL = mkOption { + type = types.str; + description = '' + The base URL for the Hydra webserver instance. Used for links in emails. + ''; + }; + + listenHost = mkOption { + type = types.str; + default = "*"; + example = "localhost"; + description = '' + The hostname or address to listen on or <literal>*</literal> to listen + on all interfaces. + ''; + }; + + port = mkOption { + type = types.int; + default = 3000; + description = '' + TCP port the web server should listen to. + ''; + }; + + minimumDiskFree = mkOption { + type = types.int; + default = 0; + description = '' + Threshold of minimum disk space (GiB) to determine if the queue runner should run or not. + ''; + }; + + minimumDiskFreeEvaluator = mkOption { + type = types.int; + default = 0; + description = '' + Threshold of minimum disk space (GiB) to determine if the evaluator should run or not. + ''; + }; + + notificationSender = mkOption { + type = types.str; + description = '' + Sender email address used for email notifications. + ''; + }; + + smtpHost = mkOption { + type = types.nullOr types.str; + default = null; + example = ["localhost"]; + description = '' + Hostname of the SMTP server to use to send email. + ''; + }; + + tracker = mkOption { + type = types.str; + default = ""; + description = '' + Piece of HTML that is included on all pages. + ''; + }; + + logo = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + Path to a file containing the logo of your Hydra instance. + ''; + }; + + debugServer = mkOption { + type = types.bool; + default = false; + description = "Whether to run the server in debug mode."; + }; + + extraConfig = mkOption { + type = types.lines; + description = "Extra lines for the Hydra configuration."; + }; + + extraEnv = mkOption { + type = types.attrsOf types.str; + default = {}; + description = "Extra environment variables for Hydra."; + }; + + gcRootsDir = mkOption { + type = types.path; + default = "/nix/var/nix/gcroots/hydra"; + description = "Directory that holds Hydra garbage collector roots."; + }; + + buildMachinesFiles = mkOption { + type = types.listOf types.path; + default = []; + example = [ "/etc/nix/machines" "/var/lib/hydra/provisioner/machines" ]; + description = "List of files containing build machines."; + }; + + useSubstitutes = mkOption { + type = types.bool; + default = false; + description = '' + Whether to use binary caches for downloading store paths. Note that + binary substitutions trigger (a potentially large number of) additional + HTTP requests that slow down the queue monitor thread significantly. + Also, this Hydra instance will serve those downloaded store paths to + its users with its own signature attached as if it had built them + itself, so don't enable this feature unless your active binary caches + are absolute trustworthy. + ''; + }; + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + users.extraGroups.hydra = { }; + + users.extraUsers.hydra = + { description = "Hydra"; + group = "hydra"; + createHome = true; + home = baseDir; + useDefaultShell = true; + }; + + users.extraUsers.hydra-queue-runner = + { description = "Hydra queue runner"; + group = "hydra"; + useDefaultShell = true; + home = "${baseDir}/queue-runner"; # really only to keep SSH happy + }; + + users.extraUsers.hydra-www = + { description = "Hydra web server"; + group = "hydra"; + useDefaultShell = true; + }; + + nix.trustedUsers = [ "hydra-queue-runner" ]; + + services.hydra.extraConfig = + '' + using_frontend_proxy 1 + base_uri ${cfg.hydraURL} + notification_sender ${cfg.notificationSender} + max_servers 25 + ${optionalString (cfg.logo != null) '' + hydra_logo ${cfg.logo} + ''} + gc_roots_dir ${cfg.gcRootsDir} + ''; + + environment.systemPackages = [ cfg.package ]; + + environment.variables = hydraEnv; + + nix.extraOptions = '' + gc-keep-outputs = true + gc-keep-derivations = true + + # The default (`true') slows Nix down a lot since the build farm + # has so many GC roots. + gc-check-reachability = false + ''; + + systemd.services.hydra-init = + { wantedBy = [ "multi-user.target" ]; + requires = optional haveLocalDB "postgresql.service"; + after = optional haveLocalDB "postgresql.service"; + environment = env; + preStart = '' + mkdir -p ${baseDir} + chown hydra.hydra ${baseDir} + chmod 0750 ${baseDir} + + ln -sf ${hydraConf} ${baseDir}/hydra.conf + + mkdir -m 0700 -p ${baseDir}/www + chown hydra-www.hydra ${baseDir}/www + + mkdir -m 0700 -p ${baseDir}/queue-runner + mkdir -m 0750 -p ${baseDir}/build-logs + chown hydra-queue-runner.hydra ${baseDir}/queue-runner ${baseDir}/build-logs + + ${optionalString haveLocalDB '' + if ! [ -e ${baseDir}/.db-created ]; then + ${config.services.postgresql.package}/bin/createuser hydra + ${config.services.postgresql.package}/bin/createdb -O hydra hydra + touch ${baseDir}/.db-created + fi + ''} + + if [ ! -e ${cfg.gcRootsDir} ]; then + + # Move legacy roots directory. + if [ -e /nix/var/nix/gcroots/per-user/hydra/hydra-roots ]; then + mv /nix/var/nix/gcroots/per-user/hydra/hydra-roots ${cfg.gcRootsDir} + fi + + mkdir -p ${cfg.gcRootsDir} + fi + + # Move legacy hydra-www roots. + if [ -e /nix/var/nix/gcroots/per-user/hydra-www/hydra-roots ]; then + find /nix/var/nix/gcroots/per-user/hydra-www/hydra-roots/ -type f \ + | xargs -r mv -f -t ${cfg.gcRootsDir}/ + rmdir /nix/var/nix/gcroots/per-user/hydra-www/hydra-roots + fi + + chown hydra.hydra ${cfg.gcRootsDir} + chmod 2775 ${cfg.gcRootsDir} + ''; + serviceConfig.ExecStart = "${cfg.package}/bin/hydra-init"; + serviceConfig.PermissionsStartOnly = true; + serviceConfig.User = "hydra"; + serviceConfig.Type = "oneshot"; + serviceConfig.RemainAfterExit = true; + }; + + systemd.services.hydra-server = + { wantedBy = [ "multi-user.target" ]; + requires = [ "hydra-init.service" ]; + after = [ "hydra-init.service" ]; + environment = serverEnv; + serviceConfig = + { ExecStart = + "@${cfg.package}/bin/hydra-server hydra-server -f -h '${cfg.listenHost}' " + + "-p ${toString cfg.port} --max_spare_servers 5 --max_servers 25 " + + "--max_requests 100 ${optionalString cfg.debugServer "-d"}"; + User = "hydra-www"; + PermissionsStartOnly = true; + Restart = "always"; + }; + }; + + systemd.services.hydra-queue-runner = + { wantedBy = [ "multi-user.target" ]; + requires = [ "hydra-init.service" ]; + after = [ "hydra-init.service" "network.target" ]; + path = [ cfg.package pkgs.nettools pkgs.openssh pkgs.bzip2 config.nix.package ]; + environment = env // { + PGPASSFILE = "${baseDir}/pgpass-queue-runner"; # grrr + IN_SYSTEMD = "1"; # to get log severity levels + }; + serviceConfig = + { ExecStart = "@${cfg.package}/bin/hydra-queue-runner hydra-queue-runner -v --option build-use-substitutes ${if cfg.useSubstitutes then "true" else "false"}"; + ExecStopPost = "${cfg.package}/bin/hydra-queue-runner --unlock"; + User = "hydra-queue-runner"; + Restart = "always"; + + # Ensure we can get core dumps. + LimitCORE = "infinity"; + WorkingDirectory = "${baseDir}/queue-runner"; + }; + }; + + systemd.services.hydra-evaluator = + { wantedBy = [ "multi-user.target" ]; + requires = [ "hydra-init.service" ]; + after = [ "hydra-init.service" "network.target" ]; + path = [ pkgs.nettools ]; + environment = env; + serviceConfig = + { ExecStart = "@${cfg.package}/bin/hydra-evaluator hydra-evaluator"; + User = "hydra"; + Restart = "always"; + WorkingDirectory = baseDir; + }; + }; + + systemd.services.hydra-update-gc-roots = + { requires = [ "hydra-init.service" ]; + after = [ "hydra-init.service" ]; + environment = env; + serviceConfig = + { ExecStart = "@${cfg.package}/bin/hydra-update-gc-roots hydra-update-gc-roots"; + User = "hydra"; + }; + startAt = "2,14:15"; + }; + + systemd.services.hydra-send-stats = + { wantedBy = [ "multi-user.target" ]; + after = [ "hydra-init.service" ]; + environment = env; + serviceConfig = + { ExecStart = "@${cfg.package}/bin/hydra-send-stats hydra-send-stats"; + User = "hydra"; + }; + }; + + # If there is less than a certain amount of free disk space, stop + # the queue/evaluator to prevent builds from failing or aborting. + systemd.services.hydra-check-space = + { script = + '' + if [ $(($(stat -f -c '%a' /nix/store) * $(stat -f -c '%S' /nix/store))) -lt $((${toString cfg.minimumDiskFree} * 1024**3)) ]; then + echo "stopping Hydra queue runner due to lack of free space..." + systemctl stop hydra-queue-runner + fi + if [ $(($(stat -f -c '%a' /nix/store) * $(stat -f -c '%S' /nix/store))) -lt $((${toString cfg.minimumDiskFreeEvaluator} * 1024**3)) ]; then + echo "stopping Hydra evaluator due to lack of free space..." + systemctl stop hydra-evaluator + fi + ''; + startAt = "*:0/5"; + }; + + # Periodically compress build logs. The queue runner compresses + # logs automatically after a step finishes, but this doesn't work + # if the queue runner is stopped prematurely. + systemd.services.hydra-compress-logs = + { path = [ pkgs.bzip2 ]; + script = + '' + find /var/lib/hydra/build-logs -type f -name "*.drv" -mtime +3 -size +0c | xargs -r bzip2 -v -f + ''; + startAt = "Sun 01:45"; + }; + + services.postgresql.enable = mkIf haveLocalDB true; + + services.postgresql.identMap = optionalString haveLocalDB + '' + hydra-users hydra hydra + hydra-users hydra-queue-runner hydra + hydra-users hydra-www hydra + hydra-users root hydra + ''; + + services.postgresql.authentication = optionalString haveLocalDB + '' + local hydra all ident map=hydra-users + ''; + + }; + +} diff --git a/nixos/modules/services/databases/openldap.nix b/nixos/modules/services/databases/openldap.nix index 9e86559dda04..9f22aa7c92b2 100644 --- a/nixos/modules/services/databases/openldap.nix +++ b/nixos/modules/services/databases/openldap.nix @@ -40,6 +40,13 @@ in description = "Group account under which slapd runs."; }; + urlList = mkOption { + type = types.listOf types.string; + default = [ "ldap:///" ]; + description = "URL list slapd should listen on."; + example = [ "ldaps:///" ]; + }; + dataDir = mkOption { type = types.string; default = "/var/db/openldap"; @@ -50,13 +57,14 @@ in type = types.lines; default = ""; description = " - sldapd.conf configuration + slapd.conf configuration "; - example = '' - include ''${pkgs.openldap}/etc/openldap/schema/core.schema - include ''${pkgs.openldap}/etc/openldap/schema/cosine.schema - include ''${pkgs.openldap}/etc/openldap/schema/inetorgperson.schema - include ''${pkgs.openldap}/etc/openldap/schema/nis.schema + example = literalExample '' + ''' + include ${pkgs.openldap.out}/etc/openldap/schema/core.schema + include ${pkgs.openldap.out}/etc/openldap/schema/cosine.schema + include ${pkgs.openldap.out}/etc/openldap/schema/inetorgperson.schema + include ${pkgs.openldap.out}/etc/openldap/schema/nis.schema database bdb suffix dc=example,dc=org @@ -64,6 +72,7 @@ in # NOTE: change after first start rootpw secret directory /var/db/openldap + ''' ''; }; }; @@ -87,7 +96,7 @@ in mkdir -p ${cfg.dataDir} chown -R ${cfg.user}:${cfg.group} ${cfg.dataDir} ''; - serviceConfig.ExecStart = "${openldap.out}/libexec/slapd -u ${cfg.user} -g ${cfg.group} -d 0 -f ${configFile}"; + serviceConfig.ExecStart = "${openldap.out}/libexec/slapd -u ${cfg.user} -g ${cfg.group} -d 0 -h \"${concatStringsSep " " cfg.urlList}\" -f ${configFile}"; }; users.extraUsers.openldap = diff --git a/nixos/modules/services/databases/redis.nix b/nixos/modules/services/databases/redis.nix index 6323d2c8ce4e..480e1184ffa3 100644 --- a/nixos/modules/services/databases/redis.nix +++ b/nixos/modules/services/databases/redis.nix @@ -68,6 +68,22 @@ in description = "The port for Redis to listen to."; }; + vmOverCommit = mkOption { + type = types.bool; + default = false; + description = '' + Set vm.overcommit_memory to 1 (Suggested for Background Saving: http://redis.io/topics/faq) + ''; + }; + + openFirewall = mkOption { + type = types.bool; + default = false; + description = '' + Whether to open ports in the firewall for the server. + ''; + }; + bind = mkOption { type = with types; nullOr str; default = null; # All interfaces @@ -193,6 +209,14 @@ in config = mkIf config.services.redis.enable { + boot.kernel.sysctl = mkIf cfg.vmOverCommit { + "vm.overcommit_memory" = "1"; + }; + + networking.firewall = mkIf cfg.openFirewall { + allowedTCPPorts = [ cfg.port ]; + }; + users.extraUsers.redis = { name = cfg.user; uid = config.ids.uids.redis; diff --git a/nixos/modules/services/desktops/gnome3/gnome-keyring.nix b/nixos/modules/services/desktops/gnome3/gnome-keyring.nix index a8f1bcc28fbe..a36643a1cfb3 100644 --- a/nixos/modules/services/desktops/gnome3/gnome-keyring.nix +++ b/nixos/modules/services/desktops/gnome3/gnome-keyring.nix @@ -36,7 +36,7 @@ in environment.systemPackages = [ gnome3.gnome_keyring ]; - services.dbus.packages = [ gnome3.gnome_keyring ]; + services.dbus.packages = [ gnome3.gnome_keyring gnome3.gcr ]; }; diff --git a/nixos/modules/services/hardware/pcscd.nix b/nixos/modules/services/hardware/pcscd.nix index 6e30dfb752d2..fa97e8bf746b 100644 --- a/nixos/modules/services/hardware/pcscd.nix +++ b/nixos/modules/services/hardware/pcscd.nix @@ -1,29 +1,51 @@ { config, lib, pkgs, ... }: +with lib; + let - cfgFile = pkgs.writeText "reader.conf" ""; -in + cfgFile = pkgs.writeText "reader.conf" config.services.pcscd.readerConfig; -with lib; + pluginEnv = pkgs.buildEnv { + name = "pcscd-plugins"; + paths = map (p: "${p}/pcsc/drivers") config.services.pcscd.plugins; + }; -{ +in { ###### interface options = { services.pcscd = { - - enable = mkOption { - default = false; - description = "Whether to enable the PCSC-Lite daemon."; + enable = mkEnableOption "PCSC-Lite daemon"; + + plugins = mkOption { + type = types.listOf types.package; + default = [ pkgs.ccid ]; + defaultText = "[ pkgs.ccid ]"; + example = literalExample "[ pkgs.pcsc-cyberjack ]"; + description = "Plugin packages to be used for PCSC-Lite."; }; + readerConfig = mkOption { + type = types.lines; + default = ""; + example = '' + FRIENDLYNAME "Some serial reader" + DEVICENAME /dev/ttyS0 + LIBPATH /path/to/serial_reader.so + CHANNELID 1 + ''; + description = '' + Configuration for devices that aren't hotpluggable. + + See <citerefentry><refentrytitle>reader.conf</refentrytitle> + <manvolnum>5</manvolnum></citerefentry> for valid options. + ''; + }; }; - }; - ###### implementation config = mkIf config.services.pcscd.enable { @@ -37,18 +59,11 @@ with lib; systemd.services.pcscd = { description = "PCSC-Lite daemon"; - preStart = '' - mkdir -p /var/lib/pcsc - rm -Rf /var/lib/pcsc/drivers - ln -s ${pkgs.ccid}/pcsc/drivers /var/lib/pcsc/ - ''; + environment.PCSCLITE_HP_DROPDIR = pluginEnv; serviceConfig = { - Type = "forking"; - ExecStart = "${pkgs.pcsclite}/sbin/pcscd --auto-exit -c ${cfgFile}"; - ExecReload = "${pkgs.pcsclite}/sbin/pcscd --hotplug"; + ExecStart = "${pkgs.pcsclite}/sbin/pcscd -f -x -c ${cfgFile}"; + ExecReload = "${pkgs.pcsclite}/sbin/pcscd -H"; }; }; - }; - } diff --git a/nixos/modules/services/mail/opendkim.nix b/nixos/modules/services/mail/opendkim.nix index af996758f41f..f065208ddfc1 100644 --- a/nixos/modules/services/mail/opendkim.nix +++ b/nixos/modules/services/mail/opendkim.nix @@ -101,7 +101,7 @@ in { wantedBy = [ "multi-user.target" ]; serviceConfig = { - ExecStart = "${pkgs.opendkim}/bin/opendkim ${concatMapStringsSep " " escapeShellArg args}"; + ExecStart = "${pkgs.opendkim}/bin/opendkim ${escapeShellArgs args}"; User = cfg.user; Group = cfg.group; RuntimeDirectory = optional (cfg.socket == defaultSock) "opendkim"; diff --git a/nixos/modules/services/mail/opensmtpd.nix b/nixos/modules/services/mail/opensmtpd.nix index 42a1244cde57..e773cdedaea2 100644 --- a/nixos/modules/services/mail/opensmtpd.nix +++ b/nixos/modules/services/mail/opensmtpd.nix @@ -107,7 +107,16 @@ in { wantedBy = [ "multi-user.target" ]; wants = [ "network.target" ]; after = [ "network.target" ]; - preStart = "mkdir -p /var/spool"; + preStart = '' + mkdir -p /var/spool/smtpd + + mkdir -p /var/spool/smtpd/offline + chown root.smtpq /var/spool/smtpd/offline + chmod 770 /var/spool/smtpd/offline + + mkdir -p /var/spool/smtpd/purge + chmod 700 /var/spool/smtpd/purge + ''; serviceConfig.ExecStart = "${opensmtpd}/sbin/smtpd -d -f ${conf} ${args}"; environment.OPENSMTPD_PROC_PATH = "${procEnv}/libexec/opensmtpd"; }; diff --git a/nixos/modules/services/mail/postfix.nix b/nixos/modules/services/mail/postfix.nix index bad9d527f9a1..cdde41446224 100644 --- a/nixos/modules/services/mail/postfix.nix +++ b/nixos/modules/services/mail/postfix.nix @@ -127,11 +127,11 @@ let # (yes) (yes) (no) (never) (100) # ========================================================================== smtp inet n - n - - smtpd - #submission inet n - n - - smtpd - # -o smtpd_tls_security_level=encrypt - # -o smtpd_sasl_auth_enable=yes - # -o smtpd_client_restrictions=permit_sasl_authenticated,reject - # -o milter_macro_daemon_name=ORIGINATING + '' + optionalString cfg.enableSubmission '' + submission inet n - n - - smtpd + ${concatStringsSep "\n " (mapAttrsToList (x: y: "-o " + x + "=" + y) cfg.submissionOptions)} + '' + + '' pickup unix n - n 60 1 pickup cleanup unix n - n - 0 cleanup qmgr unix n - n 300 1 qmgr @@ -201,6 +201,28 @@ in default = true; description = "Whether to enable smtp in master.cf."; }; + + enableSubmission = mkOption { + type = types.bool; + default = false; + description = "Whether to enable smtp submission"; + }; + + submissionOptions = mkOption { + type = types.attrs; + default = { "smtpd_tls_security_level" = "encrypt"; + "smtpd_sasl_auth_enable" = "yes"; + "smtpd_client_restrictions" = "permit_sasl_authenticated,reject"; + "milter_macro_daemon_name" = "ORIGINATING"; + }; + description = "Options for the submission config in master.cf"; + example = { "smtpd_tls_security_level" = "encrypt"; + "smtpd_sasl_auth_enable" = "yes"; + "smtpd_sasl_type" = "dovecot"; + "smtpd_client_restrictions" = "permit_sasl_authenticated,reject"; + "milter_macro_daemon_name" = "ORIGINATING"; + }; + }; setSendmail = mkOption { type = types.bool; diff --git a/nixos/modules/services/misc/confd.nix b/nixos/modules/services/misc/confd.nix index c0fbf06e6c4c..72ec68dee6b3 100644 --- a/nixos/modules/services/misc/confd.nix +++ b/nixos/modules/services/misc/confd.nix @@ -75,7 +75,7 @@ in { wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; serviceConfig = { - ExecStart = "${cfg.package}/bin/confd"; + ExecStart = "${cfg.package.bin}/bin/confd"; }; }; diff --git a/nixos/modules/services/misc/disnix.nix b/nixos/modules/services/misc/disnix.nix index 218802e0cf00..e5a125ad3245 100644 --- a/nixos/modules/services/misc/disnix.nix +++ b/nixos/modules/services/misc/disnix.nix @@ -36,49 +36,32 @@ in default = false; description = "Whether to enable the DisnixWebService interface running on Apache Tomcat"; }; - - publishInfrastructure = { - enable = mkOption { - default = false; - description = "Whether to publish capabilities/properties of this machine in as attributes in the infrastructure option"; - }; - - enableAuthentication = mkOption { - default = false; - description = "Whether to publish authentication credentials through the infrastructure attribute (not recommended in combination with Avahi)"; - }; - }; - - infrastructure = mkOption { - default = {}; - description = "List of name value pairs containing properties for the infrastructure model"; - }; - - publishAvahi = mkOption { - default = false; - description = "Whether to publish capabilities/properties as a Disnix service through Avahi"; + + package = mkOption { + type = types.path; + description = "The Disnix package"; + default = pkgs.disnix; }; }; }; - ###### implementation config = mkIf cfg.enable { - environment.systemPackages = [ pkgs.disnix pkgs.dysnomia ] ++ optional cfg.useWebServiceInterface pkgs.DisnixWebService; + dysnomia.enable = true; + + environment.systemPackages = [ pkgs.disnix ] ++ optional cfg.useWebServiceInterface pkgs.DisnixWebService; services.dbus.enable = true; services.dbus.packages = [ pkgs.disnix ]; - services.avahi.enable = cfg.publishAvahi; - services.tomcat.enable = cfg.useWebServiceInterface; services.tomcat.extraGroups = [ "disnix" ]; services.tomcat.javaOpts = "${optionalString cfg.useWebServiceInterface "-Djava.library.path=${pkgs.libmatthew_java}/lib/jni"} "; services.tomcat.sharedLibs = optional cfg.useWebServiceInterface "${pkgs.DisnixWebService}/share/java/DisnixConnection.jar" - ++ optional cfg.useWebServiceInterface "${pkgs.dbus_java}/share/java/dbus.jar"; + ++ optional cfg.useWebServiceInterface "${pkgs.dbus_java}/share/java/dbus.jar"; services.tomcat.webapps = optional cfg.useWebServiceInterface pkgs.DisnixWebService; users.extraGroups = singleton @@ -86,38 +69,6 @@ in gid = config.ids.gids.disnix; }; - services.disnix.infrastructure = - optionalAttrs (cfg.publishInfrastructure.enable) - ( { hostname = config.networking.hostName; - #targetHost = config.deployment.targetHost; - system = if config.nixpkgs.system == "" then builtins.currentSystem else config.nixpkgs.system; - - supportedTypes = (import "${pkgs.stdenv.mkDerivation { - name = "supportedtypes"; - buildCommand = '' - ( echo -n "[ " - cd ${dysnomia}/libexec/dysnomia - for i in * - do - echo -n "\"$i\" " - done - echo -n " ]") > $out - ''; - }}"); - } - #// optionalAttrs (cfg.useWebServiceInterface) { targetEPR = "http://${config.deployment.targetHost}:8080/DisnixWebService/services/DisnixWebService"; } - // optionalAttrs (config.services.httpd.enable) { documentRoot = config.services.httpd.documentRoot; } - // optionalAttrs (config.services.mysql.enable) { mysqlPort = config.services.mysql.port; } - // optionalAttrs (config.services.tomcat.enable) { tomcatPort = 8080; } - // optionalAttrs (config.services.svnserve.enable) { svnBaseDir = config.services.svnserve.svnBaseDir; } - // optionalAttrs (config.services.ejabberd.enable) { ejabberdUser = config.services.ejabberd.user; } - // optionalAttrs (cfg.publishInfrastructure.enableAuthentication) ( - optionalAttrs (config.services.mysql.enable) { mysqlUsername = "root"; mysqlPassword = readFile config.services.mysql.rootPassword; }) - ) - ; - - services.disnix.publishInfrastructure.enable = cfg.publishAvahi; - systemd.services = { disnix = { description = "Disnix server"; @@ -133,46 +84,17 @@ in restartIfChanged = false; - path = [ pkgs.nix pkgs.disnix dysnomia "/run/current-system/sw" ]; + path = [ config.nix.package cfg.package config.dysnomia.package "/run/current-system/sw" ]; environment = { HOME = "/root"; - }; - - preStart = '' - mkdir -p /etc/systemd-mutable/system - if [ ! -f /etc/systemd-mutable/system/dysnomia.target ] - then - ( echo "[Unit]" - echo "Description=Services that are activated and deactivated by Dysnomia" - echo "After=final.target" - ) > /etc/systemd-mutable/system/dysnomia.target - fi - ''; - - script = "disnix-service"; + } + // (if config.environment.variables ? DYSNOMIA_CONTAINERS_PATH then { inherit (config.environment.variables) DYSNOMIA_CONTAINERS_PATH; } else {}) + // (if config.environment.variables ? DYSNOMIA_MODULES_PATH then { inherit (config.environment.variables) DYSNOMIA_MODULES_PATH; } else {}); + + serviceConfig.ExecStart = "${cfg.package}/bin/disnix-service"; }; - } // optionalAttrs cfg.publishAvahi { - disnixAvahi = { - description = "Disnix Avahi publisher"; - wants = [ "avahi-daemon.service" ]; - wantedBy = [ "multi-user.target" ]; - script = '' - ${pkgs.avahi}/bin/avahi-publish-service disnix-${config.networking.hostName} _disnix._tcp 22 \ - "mem=$(grep 'MemTotal:' /proc/meminfo | sed -e 's/kB//' -e 's/MemTotal://' -e 's/ //g')" \ - ${concatMapStrings (infrastructureAttrName: - let infrastructureAttrValue = getAttr infrastructureAttrName (cfg.infrastructure); - in - if isInt infrastructureAttrValue then - ''${infrastructureAttrName}=${toString infrastructureAttrValue} \ - '' - else - ''${infrastructureAttrName}=\"${infrastructureAttrValue}\" \ - '' - ) (attrNames (cfg.infrastructure))} - ''; - }; }; }; } diff --git a/nixos/modules/services/misc/dysnomia.nix b/nixos/modules/services/misc/dysnomia.nix new file mode 100644 index 000000000000..df44d0a54866 --- /dev/null +++ b/nixos/modules/services/misc/dysnomia.nix @@ -0,0 +1,217 @@ +{pkgs, lib, config, ...}: + +with lib; + +let + cfg = config.dysnomia; + + printProperties = properties: + concatMapStrings (propertyName: + let + property = properties."${propertyName}"; + in + if isList property then "${propertyName}=(${lib.concatMapStrings (elem: "\"${toString elem}\" ") (properties."${propertyName}")})\n" + else "${propertyName}=\"${toString property}\"\n" + ) (builtins.attrNames properties); + + properties = pkgs.stdenv.mkDerivation { + name = "dysnomia-properties"; + buildCommand = '' + cat > $out << "EOF" + ${printProperties cfg.properties} + EOF + ''; + }; + + containersDir = pkgs.stdenv.mkDerivation { + name = "dysnomia-containers"; + buildCommand = '' + mkdir -p $out + cd $out + + ${concatMapStrings (containerName: + let + containerProperties = cfg.containers."${containerName}"; + in + '' + cat > ${containerName} <<EOF + ${printProperties containerProperties} + type=${containerName} + EOF + '' + ) (builtins.attrNames cfg.containers)} + ''; + }; + + linkMutableComponents = {containerName}: + '' + mkdir ${containerName} + + ${concatMapStrings (componentName: + let + component = cfg.components."${containerName}"."${componentName}"; + in + "ln -s ${component} ${containerName}/${componentName}\n" + ) (builtins.attrNames (cfg.components."${containerName}" or {}))} + ''; + + componentsDir = pkgs.stdenv.mkDerivation { + name = "dysnomia-components"; + buildCommand = '' + mkdir -p $out + cd $out + + ${concatMapStrings (containerName: + let + components = cfg.components."${containerName}"; + in + linkMutableComponents { inherit containerName; } + ) (builtins.attrNames cfg.components)} + ''; + }; +in +{ + options = { + dysnomia = { + + enable = mkOption { + type = types.bool; + default = false; + description = "Whether to enable Dysnomia"; + }; + + enableAuthentication = mkOption { + type = types.bool; + default = false; + description = "Whether to publish privacy-sensitive authentication credentials"; + }; + + package = mkOption { + type = types.path; + description = "The Dysnomia package"; + }; + + properties = mkOption { + description = "An attribute set in which each attribute represents a machine property. Optionally, these values can be shell substitutions."; + default = {}; + }; + + containers = mkOption { + description = "An attribute set in which each key represents a container and each value an attribute set providing its configuration properties"; + default = {}; + }; + + components = mkOption { + description = "An atttribute set in which each key represents a container and each value an attribute set in which each key represents a component and each value a derivation constructing its initial state"; + default = {}; + }; + + extraContainerProperties = mkOption { + description = "An attribute set providing additional container settings in addition to the default properties"; + default = {}; + }; + + extraContainerPaths = mkOption { + description = "A list of paths containing additional container configurations that are added to the search folders"; + default = []; + }; + + extraModulePaths = mkOption { + description = "A list of paths containing additional modules that are added to the search folders"; + default = []; + }; + }; + }; + + config = mkIf cfg.enable { + + environment.etc = { + "dysnomia/containers" = { + source = containersDir; + }; + "dysnomia/components" = { + source = componentsDir; + }; + "dysnomia/properties" = { + source = properties; + }; + }; + + environment.variables = { + DYSNOMIA_STATEDIR = "/var/state/dysnomia-nixos"; + DYSNOMIA_CONTAINERS_PATH = "${lib.concatMapStrings (containerPath: "${containerPath}:") cfg.extraContainerPaths}/etc/dysnomia/containers"; + DYSNOMIA_MODULES_PATH = "${lib.concatMapStrings (modulePath: "${modulePath}:") cfg.extraModulePaths}/etc/dysnomia/modules"; + }; + + environment.systemPackages = [ cfg.package ]; + + dysnomia.package = pkgs.dysnomia.override (origArgs: { + enableApacheWebApplication = config.services.httpd.enable; + enableAxis2WebService = config.services.tomcat.axis2.enable; + enableEjabberdDump = config.services.ejabberd.enable; + enableMySQLDatabase = config.services.mysql.enable; + enablePostgreSQLDatabase = config.services.postgresql.enable; + enableSubversionRepository = config.services.svnserve.enable; + enableTomcatWebApplication = config.services.tomcat.enable; + enableMongoDatabase = config.services.mongodb.enable; + }); + + dysnomia.properties = { + hostname = config.networking.hostName; + system = if config.nixpkgs.system == "" then builtins.currentSystem else config.nixpkgs.system; + + supportedTypes = (import "${pkgs.stdenv.mkDerivation { + name = "supportedtypes"; + buildCommand = '' + ( echo -n "[ " + cd ${cfg.package}/libexec/dysnomia + for i in * + do + echo -n "\"$i\" " + done + echo -n " ]") > $out + ''; + }}"); + }; + + dysnomia.containers = lib.recursiveUpdate ({ + process = {}; + wrapper = {}; + } + // lib.optionalAttrs (config.services.httpd.enable) { apache-webapplication = { + documentRoot = config.services.httpd.documentRoot; + }; } + // lib.optionalAttrs (config.services.tomcat.axis2.enable) { axis2-webservice = {}; } + // lib.optionalAttrs (config.services.ejabberd.enable) { ejabberd-dump = { + ejabberdUser = config.services.ejabberd.user; + }; } + // lib.optionalAttrs (config.services.mysql.enable) { mysql-database = { + mysqlPort = config.services.mysql.port; + } // lib.optionalAttrs cfg.enableAuthentication { + mysqlUsername = "root"; + mysqlPassword = builtins.readFile (config.services.mysql.rootPassword); + }; + } + // lib.optionalAttrs (config.services.postgresql.enable && cfg.enableAuthentication) { postgresql-database = { + postgresqlUsername = "root"; + }; } + // lib.optionalAttrs (config.services.tomcat.enable) { tomcat-webapplication = { + tomcatPort = 8080; + }; } + // lib.optionalAttrs (config.services.mongodb.enable) { mongo-database = {}; } + // lib.optionalAttrs (config.services.svnserve.enable) { subversion-repository = { + svnBaseDir = config.services.svnserve.svnBaseDir; + }; }) cfg.extraContainerProperties; + + system.activationScripts.dysnomia = '' + mkdir -p /etc/systemd-mutable/system + if [ ! -f /etc/systemd-mutable/system/dysnomia.target ] + then + ( echo "[Unit]" + echo "Description=Services that are activated and deactivated by Dysnomia" + echo "After=final.target" + ) > /etc/systemd-mutable/system/dysnomia.target + fi + ''; + }; +} diff --git a/nixos/modules/services/misc/etcd.nix b/nixos/modules/services/misc/etcd.nix index bc8064e3c879..0d6ed8eb9043 100644 --- a/nixos/modules/services/misc/etcd.nix +++ b/nixos/modules/services/misc/etcd.nix @@ -115,7 +115,7 @@ in { serviceConfig = { Type = "notify"; - ExecStart = "${pkgs.etcd}/bin/etcd"; + ExecStart = "${pkgs.etcd.bin}/bin/etcd"; User = "etcd"; PermissionsStartOnly = true; }; diff --git a/nixos/modules/services/misc/matrix-synapse.nix b/nixos/modules/services/misc/matrix-synapse.nix index 0ae0516769c0..1a95e2d9367d 100644 --- a/nixos/modules/services/misc/matrix-synapse.nix +++ b/nixos/modules/services/misc/matrix-synapse.nix @@ -5,17 +5,31 @@ with lib; let cfg = config.services.matrix-synapse; logConfigFile = pkgs.writeText "log_config.yaml" cfg.logConfig; + mkResource = r: ''{names: ${builtins.toJSON r.names}, compress: ${if r.compress then "true" else "false"}}''; + mkListener = l: ''{port: ${toString l.port}, bind_address: "${l.bind_address}", type: ${l.type}, tls: ${if l.tls then "true" else "false"}, x_forwarded: ${if l.x_forwarded then "true" else "false"}, resources: [${concatStringsSep "," (map mkResource l.resources)}]}''; configFile = pkgs.writeText "homeserver.yaml" '' tls_certificate_path: "${cfg.tls_certificate_path}" +${optionalString (cfg.tls_private_key_path != null) '' tls_private_key_path: "${cfg.tls_private_key_path}" +''} tls_dh_params_path: "${cfg.tls_dh_params_path}" no_tls: ${if cfg.no_tls then "true" else "false"} +${optionalString (cfg.bind_port != null) '' bind_port: ${toString cfg.bind_port} +''} +${optionalString (cfg.unsecure_port != null) '' unsecure_port: ${toString cfg.unsecure_port} +''} +${optionalString (cfg.bind_host != null) '' bind_host: "${cfg.bind_host}" +''} server_name: "${cfg.server_name}" pid_file: "/var/run/matrix-synapse.pid" web_client: ${if cfg.web_client then "true" else "false"} +${optionalString (cfg.public_baseurl != null) '' +public_baseurl: "${cfg.public_baseurl}" +''} +listeners: [${concatStringsSep "," (map mkListener cfg.listeners)}] database: { name: "${cfg.database_type}", args: { @@ -24,21 +38,41 @@ database: { )} } } +event_cache_size: "${cfg.event_cache_size}" +verbose: ${cfg.verbose} log_file: "/var/log/matrix-synapse/homeserver.log" log_config: "${logConfigFile}" +rc_messages_per_second: ${cfg.rc_messages_per_second} +rc_message_burst_count: ${cfg.rc_message_burst_count} +federation_rc_window_size: ${cfg.federation_rc_window_size} +federation_rc_sleep_limit: ${cfg.federation_rc_sleep_limit} +federation_rc_sleep_delay: ${cfg.federation_rc_sleep_delay} +federation_rc_reject_limit: ${cfg.federation_rc_reject_limit} +federation_rc_concurrent: ${cfg.federation_rc_concurrent} media_store_path: "/var/lib/matrix-synapse/media" +uploads_path: "/var/lib/matrix-synapse/uploads" +max_upload_size: "${cfg.max_upload_size}" +max_image_pixels: "${cfg.max_image_pixels}" +dynamic_thumbnails: ${if cfg.dynamic_thumbnails then "true" else "false"} +url_preview_enabled: False recaptcha_private_key: "${cfg.recaptcha_private_key}" recaptcha_public_key: "${cfg.recaptcha_public_key}" enable_registration_captcha: ${if cfg.enable_registration_captcha then "true" else "false"} -turn_uris: ${if (length cfg.turn_uris) == 0 then "[]" else ("\n" + (concatStringsSep "\n" (map (s: "- " + s) cfg.turn_uris)))} +turn_uris: ${builtins.toJSON cfg.turn_uris} turn_shared_secret: "${cfg.turn_shared_secret}" enable_registration: ${if cfg.enable_registration then "true" else "false"} -${optionalString (cfg.registration_shared_secret != "") '' +${optionalString (cfg.registration_shared_secret != null) '' registration_shared_secret: "${cfg.registration_shared_secret}" ''} +recaptcha_siteverify_api: "https://www.google.com/recaptcha/api/siteverify" +turn_user_lifetime: "${cfg.turn_user_lifetime}" +user_creation_max_duration: ${cfg.user_creation_max_duration} +bcrypt_rounds: ${cfg.bcrypt_rounds} +allow_guest_access: {if cfg.allow_guest_access then "true" else "false"} enable_metrics: ${if cfg.enable_metrics then "true" else "false"} report_stats: ${if cfg.report_stats then "true" else "false"} signing_key_path: "/var/lib/matrix-synapse/homeserver.signing.key" +key_refresh_interval: "${cfg.key_refresh_interval}" perspectives: servers: { ${concatStringsSep "},\n" (mapAttrsToList (n: v: '' @@ -52,6 +86,8 @@ perspectives: '') cfg.servers)} } } +app_service_config_files: ${builtins.toJSON cfg.app_service_config_files} + ${cfg.extraConfig} ''; in { @@ -73,53 +109,65 @@ in { Don't bind to the https port ''; }; - tls_certificate_path = mkOption { - type = types.path; - default = "/var/lib/matrix-synapse/homeserver.tls.crt"; + bind_port = mkOption { + type = types.nullOr types.int; + default = null; + example = 8448; description = '' - PEM encoded X509 certificate for TLS + DEPRECATED: Use listeners instead. + The port to listen for HTTPS requests on. + For when matrix traffic is sent directly to synapse. ''; }; - tls_private_key_path = mkOption { - type = types.path; - default = "/var/lib/matrix-synapse/homeserver.tls.key"; + unsecure_port = mkOption { + type = types.nullOr types.int; + default = null; + example = 8008; description = '' - PEM encoded private key for TLS + DEPRECATED: Use listeners instead. + The port to listen for HTTP requests on. + For when matrix traffic passes through loadbalancer that unwraps TLS. ''; }; - tls_dh_params_path = mkOption { - type = types.path; - default = "/var/lib/matrix-synapse/homeserver.tls.dh"; + bind_host = mkOption { + type = types.nullOr types.str; + default = null; description = '' - PEM dh parameters for ephemeral keys + DEPRECATED: Use listeners instead. + Local interface to listen on. + The empty string will cause synapse to listen on all interfaces. ''; }; - bind_port = mkOption { - type = types.int; - default = 8448; + tls_certificate_path = mkOption { + type = types.str; + default = "/var/lib/matrix-synapse/homeserver.tls.crt"; description = '' - The port to listen for HTTPS requests on. - For when matrix traffic is sent directly to synapse. + PEM encoded X509 certificate for TLS. + You can replace the self-signed certificate that synapse + autogenerates on launch with your own SSL certificate + key pair + if you like. Any required intermediary certificates can be + appended after the primary certificate in hierarchical order. ''; }; - unsecure_port = mkOption { - type = types.int; - default = 8008; + tls_private_key_path = mkOption { + type = types.nullOr types.str; + default = "/var/lib/matrix-synapse/homeserver.tls.key"; + example = null; description = '' - The port to listen for HTTP requests on. - For when matrix traffic passes through loadbalancer that unwraps TLS. + PEM encoded private key for TLS. Specify null if synapse is not + speaking TLS directly. ''; }; - bind_host = mkOption { + tls_dh_params_path = mkOption { type = types.str; - default = ""; + default = "/var/lib/matrix-synapse/homeserver.tls.dh"; description = '' - Local interface to listen on. - The empty string will cause synapse to listen on all interfaces. + PEM dh parameters for ephemeral keys ''; }; server_name = mkOption { type = types.str; + example = "example.com"; description = '' The domain name of the server, with optional explicit port. This is used by remote servers to connect to this server, @@ -134,6 +182,145 @@ in { Whether to serve a web client from the HTTP/HTTPS root resource. ''; }; + public_baseurl = mkOption { + type = types.nullOr types.str; + default = null; + example = "https://example.com:8448/"; + description = '' + The public-facing base URL for the client API (not including _matrix/...) + ''; + }; + listeners = mkOption { + type = types.listOf (types.submodule { + options = { + port = mkOption { + type = types.int; + example = 8448; + description = '' + The port to listen for HTTP(S) requests on. + ''; + }; + bind_address = mkOption { + type = types.str; + default = ""; + example = "203.0.113.42"; + description = '' + Local interface to listen on. + The empty string will cause synapse to listen on all interfaces. + ''; + }; + type = mkOption { + type = types.str; + default = "http"; + description = '' + Type of listener. + ''; + }; + tls = mkOption { + type = types.bool; + default = true; + description = '' + Whether to listen for HTTPS connections rather than HTTP. + ''; + }; + x_forwarded = mkOption { + type = types.bool; + default = false; + description = '' + Use the X-Forwarded-For (XFF) header as the client IP and not the + actual client IP. + ''; + }; + resources = mkOption { + type = types.listOf (types.submodule { + options = { + names = mkOption { + type = types.listOf types.str; + description = '' + List of resources to host on this listener. + ''; + example = ["client" "webclient" "federation"]; + }; + compress = mkOption { + type = types.bool; + description = '' + Should synapse compress HTTP responses to clients that support it? + This should be disabled if running synapse behind a load balancer + that can do automatic compression. + ''; + }; + }; + }); + description = '' + List of HTTP resources to serve on this listener. + ''; + }; + }; + }); + default = [{ + port = 8448; + bind_address = ""; + type = "http"; + tls = true; + x_forwarded = false; + resources = [ + { names = ["client" "webclient"]; compress = true; } + { names = ["federation"]; compress = false; } + ]; + }]; + description = '' + List of ports that Synapse should listen on, their purpose and their configuration. + ''; + }; + verbose = mkOption { + type = types.str; + default = "0"; + description = "Logging verbosity level."; + }; + rc_messages_per_second = mkOption { + type = types.str; + default = "0.2"; + description = "Number of messages a client can send per second"; + }; + rc_message_burst_count = mkOption { + type = types.str; + default = "10.0"; + description = "Number of message a client can send before being throttled"; + }; + federation_rc_window_size = mkOption { + type = types.str; + default = "1000"; + description = "The federation window size in milliseconds"; + }; + federation_rc_sleep_limit = mkOption { + type = types.str; + default = "10"; + description = '' + The number of federation requests from a single server in a window + before the server will delay processing the request. + ''; + }; + federation_rc_sleep_delay = mkOption { + type = types.str; + default = "500"; + description = '' + The duration in milliseconds to delay processing events from + remote servers by if they go over the sleep limit. + ''; + }; + federation_rc_reject_limit = mkOption { + type = types.str; + default = "50"; + description = '' + The maximum number of concurrent federation requests allowed + from a single server + ''; + }; + federation_rc_concurrent = mkOption { + type = types.str; + default = "3"; + description = "The number of federation requests to concurrently process from a single server"; + }; database_type = mkOption { type = types.enum [ "sqlite3" "psycopg2" ]; default = "sqlite3"; @@ -150,6 +337,11 @@ in { Arguments to pass to the engine. ''; }; + event_cache_size = mkOption { + type = types.str; + default = "10K"; + description = "Number of events to cache in memory."; + }; recaptcha_private_key = mkOption { type = types.str; default = ""; @@ -187,6 +379,11 @@ in { The shared secret used to compute passwords for the TURN server ''; }; + turn_user_lifetime = mkOption { + type = types.str; + default = "1h"; + description = "How long generated TURN credentials last"; + }; enable_registration = mkOption { type = types.bool; default = false; @@ -195,8 +392,8 @@ in { ''; }; registration_shared_secret = mkOption { - type = types.str; - default = ""; + type = types.nullOr types.str; + default = null; description = '' If set, allows registration by anyone who also has the shared secret, even if registration is otherwise disabled. @@ -216,7 +413,7 @@ in { ''; }; servers = mkOption { - type = types.attrs; + type = types.attrsOf (types.attrsOf types.str); default = { "matrix.org" = { "ed25519:auto" = "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw"; @@ -226,6 +423,69 @@ in { The trusted servers to download signing keys from. ''; }; + max_upload_size = mkOption { + type = types.str; + default = "10M"; + description = "The largest allowed upload size in bytes"; + }; + max_image_pixels = mkOption { + type = types.str; + default = "32M"; + description = "Maximum number of pixels that will be thumbnailed"; + }; + dynamic_thumbnails = mkOption { + type = types.bool; + default = false; + description = '' + Whether to generate new thumbnails on the fly to precisely match + the resolution requested by the client. If true then whenever + a new resolution is requested by the client the server will + generate a new thumbnail. If false the server will pick a thumbnail + from a precalculated list. + ''; + }; + user_creation_max_duration = mkOption { + type = types.str; + default = "1209600000"; + description = '' + Sets the expiry for the short term user creation in + milliseconds. The default value is two weeks. + ''; + }; + bcrypt_rounds = mkOption { + type = types.str; + default = "12"; + description = '' + Set the number of bcrypt rounds used to generate password hash. + Larger numbers increase the work factor needed to generate the hash. + ''; + }; + allow_guest_access = mkOption { + type = types.bool; + default = false; + description = '' + Allows users to register as guests without a password/email/etc, and + participate in rooms hosted on this server which have been made + accessible to anonymous users. + ''; + }; + key_refresh_interval = mkOption { + type = types.str; + default = "1d"; + description = '' + How long key response published by this server is valid for. + Used to set the valid_until_ts in /key/v2 APIs. + Determines how quickly servers will query to check which keys + are still valid. + ''; + }; + app_service_config_files = mkOption { + type = types.listOf types.path; + default = [ ]; + description = '' + A list of application service config file to use + ''; + }; extraConfig = mkOption { type = types.lines; default = ""; @@ -265,7 +525,7 @@ in { mkdir -p /var/lib/matrix-synapse chmod 700 /var/lib/matrix-synapse chown -R matrix-synapse:matrix-synapse /var/lib/matrix-synapse - ${cfg.package}/bin/homeserver --config-path ${configFile} --generate-keys + ${cfg.package}/bin/homeserver --config-path ${configFile} --keys-directory /var/lib/matrix-synapse/ --generate-keys ''; serviceConfig = { Type = "simple"; diff --git a/nixos/modules/services/misc/parsoid.nix b/nixos/modules/services/misc/parsoid.nix index ea97d6e30e83..0844190a5490 100644 --- a/nixos/modules/services/misc/parsoid.nix +++ b/nixos/modules/services/misc/parsoid.nix @@ -91,7 +91,7 @@ in wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; serviceConfig = { - ExecStart = "${pkgs.nodePackages_0_10.parsoid}/lib/node_modules/parsoid/api/server.js -c ${confFile} -n ${toString cfg.workers}"; + ExecStart = "${pkgs.nodePackages.parsoid}/lib/node_modules/parsoid/api/server.js -c ${confFile} -n ${toString cfg.workers}"; }; }; diff --git a/nixos/modules/services/misc/taskserver/default.nix b/nixos/modules/services/misc/taskserver/default.nix index b7d14e90a2b7..c846ffd04551 100644 --- a/nixos/modules/services/misc/taskserver/default.nix +++ b/nixos/modules/services/misc/taskserver/default.nix @@ -152,8 +152,6 @@ let }; }; - mkShellStr = val: "'${replaceStrings ["'"] ["'\\''"] val}'"; - certtool = "${pkgs.gnutls.bin}/bin/certtool"; nixos-taskserver = pkgs.buildPythonPackage { diff --git a/nixos/modules/services/monitoring/bosun.nix b/nixos/modules/services/monitoring/bosun.nix index 51d38e8db4de..9a1e790d3ab6 100644 --- a/nixos/modules/services/monitoring/bosun.nix +++ b/nixos/modules/services/monitoring/bosun.nix @@ -148,7 +148,7 @@ in { User = cfg.user; Group = cfg.group; ExecStart = '' - ${cfg.package}/bin/bosun -c ${configFile} + ${cfg.package.bin}/bin/bosun -c ${configFile} ''; }; }; diff --git a/nixos/modules/services/monitoring/grafana.nix b/nixos/modules/services/monitoring/grafana.nix index defbd9289dcd..0b7f3ce0a29b 100644 --- a/nixos/modules/services/monitoring/grafana.nix +++ b/nixos/modules/services/monitoring/grafana.nix @@ -228,7 +228,7 @@ in { after = ["networking.target"]; environment = mapAttrs' (n: v: nameValuePair "GF_${n}" (toString v)) envOptions; serviceConfig = { - ExecStart = "${cfg.package}/bin/grafana-server -homepath ${cfg.dataDir}"; + ExecStart = "${cfg.package.bin}/bin/grafana-server -homepath ${cfg.dataDir}"; WorkingDirectory = cfg.dataDir; User = "grafana"; }; diff --git a/nixos/modules/services/monitoring/scollector.nix b/nixos/modules/services/monitoring/scollector.nix index 1e397435e600..2684482c6184 100644 --- a/nixos/modules/services/monitoring/scollector.nix +++ b/nixos/modules/services/monitoring/scollector.nix @@ -119,7 +119,7 @@ in { PermissionsStartOnly = true; User = cfg.user; Group = cfg.group; - ExecStart = "${cfg.package}/bin/scollector -conf=${conf} ${lib.concatStringsSep " " cfg.extraOpts}"; + ExecStart = "${cfg.package.bin}/bin/scollector -conf=${conf} ${lib.concatStringsSep " " cfg.extraOpts}"; }; }; diff --git a/nixos/modules/services/network-filesystems/diod.nix b/nixos/modules/services/network-filesystems/diod.nix index 7de7acaa4a08..556fad4d8ab4 100644 --- a/nixos/modules/services/network-filesystems/diod.nix +++ b/nixos/modules/services/network-filesystems/diod.nix @@ -153,7 +153,7 @@ in after = [ "network.target" ]; serviceConfig = { ExecStart = "${pkgs.diod}/sbin/diod -f -c ${diodConfig}"; - Capabilities = "cap_net_bind_service+=ep"; + CapabilityBoundingSet = "cap_net_bind_service+=ep"; }; }; }; diff --git a/nixos/modules/services/networking/chrony.nix b/nixos/modules/services/networking/chrony.nix index 1cd678e7c621..a38142b4a08f 100644 --- a/nixos/modules/services/networking/chrony.nix +++ b/nixos/modules/services/networking/chrony.nix @@ -64,7 +64,7 @@ in ###### implementation - config = mkIf config.services.chrony.enable { + config = mkIf cfg.enable { # Make chronyc available in the system path environment.systemPackages = [ pkgs.chrony ]; @@ -101,12 +101,14 @@ in home = stateDir; }; - systemd.services.ntpd.enable = false; + systemd.services.ntpd.enable = mkForce false; systemd.services.chronyd = { description = "chrony NTP daemon"; wantedBy = [ "multi-user.target" ]; + wants = [ "time-sync.target" ]; + before = [ "time-sync.target" ]; after = [ "network.target" ]; conflicts = [ "ntpd.service" "systemd-timesyncd.service" ]; diff --git a/nixos/modules/services/networking/consul.nix b/nixos/modules/services/networking/consul.nix index 2aa101f980da..166ee7732375 100644 --- a/nixos/modules/services/networking/consul.nix +++ b/nixos/modules/services/networking/consul.nix @@ -178,14 +178,14 @@ in (filterAttrs (n: _: hasPrefix "consul.d/" n) config.environment.etc); serviceConfig = { - ExecStart = "@${cfg.package}/bin/consul consul agent -config-dir /etc/consul.d" + ExecStart = "@${cfg.package.bin}/bin/consul consul agent -config-dir /etc/consul.d" + concatMapStrings (n: " -config-file ${n}") configFiles; - ExecReload = "${cfg.package}/bin/consul reload"; + ExecReload = "${cfg.package.bin}/bin/consul reload"; PermissionsStartOnly = true; User = if cfg.dropPrivileges then "consul" else null; TimeoutStartSec = "0"; } // (optionalAttrs (cfg.leaveOnStop) { - ExecStop = "${cfg.package}/bin/consul leave"; + ExecStop = "${cfg.package.bin}/bin/consul leave"; }); path = with pkgs; [ iproute gnugrep gawk consul ]; @@ -236,7 +236,7 @@ in serviceConfig = { ExecStart = '' - ${cfg.alerts.package}/bin/consul-alerts start \ + ${cfg.alerts.package.bin}/bin/consul-alerts start \ --alert-addr=${cfg.alerts.listenAddr} \ --consul-addr=${cfg.alerts.consulAddr} \ ${optionalString cfg.alerts.watchChecks "--watch-checks"} \ diff --git a/nixos/modules/services/networking/coturn.nix b/nixos/modules/services/networking/coturn.nix new file mode 100644 index 000000000000..14e6932d868b --- /dev/null +++ b/nixos/modules/services/networking/coturn.nix @@ -0,0 +1,327 @@ +{ config, lib, pkgs, ... }: +with lib; +let + cfg = config.services.coturn; + pidfile = "/run/turnserver/turnserver.pid"; + configFile = pkgs.writeText "turnserver.conf" '' +listening-port=${toString cfg.listening-port} +tls-listening-port=${toString cfg.tls-listening-port} +alt-listening-port=${toString cfg.alt-listening-port} +alt-tls-listening-port=${toString cfg.alt-tls-listening-port} +${concatStringsSep "\n" (map (x: "listening-ip=${x}") cfg.listening-ips)} +${concatStringsSep "\n" (map (x: "relay-ip=${x}") cfg.relay-ips)} +min-port=${toString cfg.min-port} +max-port=${toString cfg.max-port} +${lib.optionalString cfg.lt-cred-mech "lt-cred-mech"} +${lib.optionalString cfg.no-auth "no-auth"} +${lib.optionalString cfg.use-auth-secret "use-auth-secret"} +${lib.optionalString (cfg.static-auth-secret != null) ("static-auth-secret=${cfg.static-auth-secret}")} +realm=${cfg.realm} +${lib.optionalString cfg.no-udp "no-udp"} +${lib.optionalString cfg.no-tcp "no-tcp"} +${lib.optionalString cfg.no-tls "no-tls"} +${lib.optionalString cfg.no-dtls "no-dtls"} +${lib.optionalString cfg.no-udp-relay "no-udp-relay"} +${lib.optionalString cfg.no-tcp-relay "no-tcp-relay"} +${lib.optionalString (cfg.cert != null) "cert=${cfg.cert}"} +${lib.optionalString (cfg.pkey != null) "pkey=${cfg.pkey}"} +${lib.optionalString (cfg.dh-file != null) ("dh-file=${cfg.dh-file}")} +no-stdout-log +syslog +pidfile=${pidfile} +${lib.optionalString cfg.secure-stun "secure-stun"} +${lib.optionalString cfg.no-cli "no-cli"} +cli-ip=${cfg.cli-ip} +cli-port=${toString cfg.cli-port} +${lib.optionalString (cfg.cli-password != null) ("cli-password=${cfg.cli-password}")} +${cfg.extraConfig} +''; +in { + options = { + services.coturn = { + enable = mkEnableOption "coturn TURN server"; + listening-port = mkOption { + type = types.int; + default = 3478; + description = '' + TURN listener port for UDP and TCP. + Note: actually, TLS and DTLS sessions can connect to the + "plain" TCP and UDP port(s), too - if allowed by configuration. + ''; + }; + tls-listening-port = mkOption { + type = types.int; + default = 5349; + description = '' + TURN listener port for TLS. + Note: actually, "plain" TCP and UDP sessions can connect to the TLS and + DTLS port(s), too - if allowed by configuration. The TURN server + "automatically" recognizes the type of traffic. Actually, two listening + endpoints (the "plain" one and the "tls" one) are equivalent in terms of + functionality; but we keep both endpoints to satisfy the RFC 5766 specs. + For secure TCP connections, we currently support SSL version 3 and + TLS version 1.0, 1.1 and 1.2. + For secure UDP connections, we support DTLS version 1. + ''; + }; + alt-listening-port = mkOption { + type = types.int; + default = cfg.listening-port + 1; + defaultText = "listening-port + 1"; + description = '' + Alternative listening port for UDP and TCP listeners; + default (or zero) value means "listening port plus one". + This is needed for RFC 5780 support + (STUN extension specs, NAT behavior discovery). The TURN Server + supports RFC 5780 only if it is started with more than one + listening IP address of the same family (IPv4 or IPv6). + RFC 5780 is supported only by UDP protocol, other protocols + are listening to that endpoint only for "symmetry". + ''; + }; + alt-tls-listening-port = mkOption { + type = types.int; + default = cfg.tls-listening-port + 1; + defaultText = "tls-listening-port + 1"; + description = '' + Alternative listening port for TLS and DTLS protocols. + ''; + }; + listening-ips = mkOption { + type = types.listOf types.str; + default = []; + example = [ "203.0.113.42" "2001:DB8::42" ]; + description = '' + Listener IP addresses of relay server. + If no IP(s) specified in the config file or in the command line options, + then all IPv4 and IPv6 system IPs will be used for listening. + ''; + }; + relay-ips = mkOption { + type = types.listOf types.str; + default = []; + example = [ "203.0.113.42" "2001:DB8::42" ]; + description = '' + Relay address (the local IP address that will be used to relay the + packets to the peer). + Multiple relay addresses may be used. + The same IP(s) can be used as both listening IP(s) and relay IP(s). + + If no relay IP(s) specified, then the turnserver will apply the default + policy: it will decide itself which relay addresses to be used, and it + will always be using the client socket IP address as the relay IP address + of the TURN session (if the requested relay address family is the same + as the family of the client socket). + ''; + }; + min-port = mkOption { + type = types.int; + default = 49152; + description = '' + Lower bound of UDP relay endpoints + ''; + }; + max-port = mkOption { + type = types.int; + default = 65535; + description = '' + Upper bound of UDP relay endpoints + ''; + }; + lt-cred-mech = mkOption { + type = types.bool; + default = false; + description = '' + Use long-term credential mechanism. + ''; + }; + no-auth = mkOption { + type = types.bool; + default = false; + description = '' + This option is opposite to lt-cred-mech. + (TURN Server with no-auth option allows anonymous access). + If neither option is defined, and no users are defined, + then no-auth is default. If at least one user is defined, + in this file or in command line or in usersdb file, then + lt-cred-mech is default. + ''; + }; + use-auth-secret = mkOption { + type = types.bool; + default = false; + description = '' + TURN REST API flag. + Flag that sets a special authorization option that is based upon authentication secret. + This feature can be used with the long-term authentication mechanism, only. + This feature purpose is to support "TURN Server REST API", see + "TURN REST API" link in the project's page + https://github.com/coturn/coturn/ + + This option is used with timestamp: + + usercombo -> "timestamp:userid" + turn user -> usercombo + turn password -> base64(hmac(secret key, usercombo)) + + This allows TURN credentials to be accounted for a specific user id. + If you don't have a suitable id, the timestamp alone can be used. + This option is just turning on secret-based authentication. + The actual value of the secret is defined either by option static-auth-secret, + or can be found in the turn_secret table in the database. + ''; + }; + static-auth-secret = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + 'Static' authentication secret value (a string) for TURN REST API only. + If not set, then the turn server + will try to use the 'dynamic' value in turn_secret table + in user database (if present). The database-stored value can be changed on-the-fly + by a separate program, so this is why that other mode is 'dynamic'. + ''; + }; + realm = mkOption { + type = types.str; + default = config.networking.hostName; + example = "example.com"; + description = '' + The default realm to be used for the users when no explicit + origin/realm relationship was found in the database, or if the TURN + server is not using any database (just the commands-line settings + and the userdb file). Must be used with long-term credentials + mechanism or with TURN REST API. + ''; + }; + cert = mkOption { + type = types.nullOr types.str; + default = null; + example = "/var/lib/acme/example.com/fullchain.pem"; + description = '' + Certificate file in PEM format. + ''; + }; + pkey = mkOption { + type = types.nullOr types.str; + default = null; + example = "/var/lib/acme/example.com/key.pem"; + description = '' + Private key file in PEM format. + ''; + }; + dh-file = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Use custom DH TLS key, stored in PEM format in the file. + ''; + }; + secure-stun = mkOption { + type = types.bool; + default = false; + description = '' + Require authentication of the STUN Binding request. + By default, the clients are allowed anonymous access to the STUN Binding functionality. + ''; + }; + no-cli = mkOption { + type = types.bool; + default = false; + description = '' + Turn OFF the CLI support. + ''; + }; + cli-ip = mkOption { + type = types.str; + default = "127.0.0.1"; + description = '' + Local system IP address to be used for CLI server endpoint. + ''; + }; + cli-port = mkOption { + type = types.int; + default = 5766; + description = '' + CLI server port. + ''; + }; + cli-password = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + CLI access password. + For the security reasons, it is recommended to use the encrypted + for of the password (see the -P command in the turnadmin utility). + ''; + }; + no-udp = mkOption { + type = types.bool; + default = false; + description = "Disable UDP client listener"; + }; + no-tcp = mkOption { + type = types.bool; + default = false; + description = "Disable TCP client listener"; + }; + no-tls = mkOption { + type = types.bool; + default = false; + description = "Disable TLS client listener"; + }; + no-dtls = mkOption { + type = types.bool; + default = false; + description = "Disable DTLS client listener"; + }; + no-udp-relay = mkOption { + type = types.bool; + default = false; + description = "Disable UDP relay endpoints"; + }; + no-tcp-relay = mkOption { + type = types.bool; + default = false; + description = "Disable TCP relay endpoints"; + }; + extraConfig = mkOption { + type = types.lines; + default = ""; + description = "Additional configuration options"; + }; + }; + }; + + config = mkIf cfg.enable { + users.extraUsers = [ + { name = "turnserver"; + uid = config.ids.uids.turnserver; + description = "coturn TURN server user"; + } ]; + users.extraGroups = [ + { name = "turnserver"; + gid = config.ids.gids.turnserver; + members = [ "turnserver" ]; + } ]; + + systemd.services.coturn = { + description = "coturn TURN server"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + + unitConfig = { + Documentation = "man:coturn(1) man:turnadmin(1) man:turnserver(1)"; + }; + + serviceConfig = { + Type = "simple"; + ExecStart = "${pkgs.coturn}/bin/turnserver -c ${configFile}"; + RuntimeDirectory = "turnserver"; + User = "turnserver"; + Group = "turnserver"; + Restart = "on-abort"; + }; + }; + }; +} diff --git a/nixos/modules/services/networking/dnscrypt-proxy.nix b/nixos/modules/services/networking/dnscrypt-proxy.nix index bb0dc756ba47..227e38acc4a6 100644 --- a/nixos/modules/services/networking/dnscrypt-proxy.nix +++ b/nixos/modules/services/networking/dnscrypt-proxy.nix @@ -89,8 +89,8 @@ in ''; example = literalExample "${pkgs.dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv"; default = pkgs.fetchurl { - url = "https://raw.githubusercontent.com/jedisct1/dnscrypt-proxy/master/dnscrypt-resolvers.csv"; - sha256 = "07kbbisrvrqdxif3061hxj3whin3llg4nh50ln7prisi2vbd76xd"; + url = https://raw.githubusercontent.com/jedisct1/dnscrypt-proxy/master/dnscrypt-resolvers.csv; + sha256 = "171zvdqcqqvcw3zr7wl9h1wmdmk6m3h55xr4gq2z1j7a0x0ba2in"; }; defaultText = "pkgs.fetchurl { url = ...; sha256 = ...; }"; }; diff --git a/nixos/modules/services/networking/ejabberd.nix b/nixos/modules/services/networking/ejabberd.nix index 9868f303ab2b..8ecc16257db8 100644 --- a/nixos/modules/services/networking/ejabberd.nix +++ b/nixos/modules/services/networking/ejabberd.nix @@ -13,7 +13,7 @@ let ectl = ''${cfg.package}/bin/ejabberdctl ${if cfg.configFile == null then "" else "--config ${cfg.configFile}"} --ctl-config "${ctlcfg}" --spool "${cfg.spoolDir}" --logs "${cfg.logsDir}"''; - dumps = lib.concatMapStringsSep " " lib.escapeShellArg cfg.loadDumps; + dumps = lib.escapeShellArgs cfg.loadDumps; in { diff --git a/nixos/modules/services/networking/mosquitto.nix b/nixos/modules/services/networking/mosquitto.nix new file mode 100644 index 000000000000..f926cd710c8d --- /dev/null +++ b/nixos/modules/services/networking/mosquitto.nix @@ -0,0 +1,219 @@ +{ config, lib, pkgs, ...}: + +with lib; + +let + cfg = config.services.mosquitto; + + listenerConf = optionalString cfg.ssl.enable '' + listener ${toString cfg.ssl.port} ${cfg.ssl.host} + cafile ${cfg.ssl.cafile} + certfile ${cfg.ssl.certfile} + keyfile ${cfg.ssl.keyfile} + ''; + + mosquittoConf = pkgs.writeText "mosquitto.conf" '' + pid_file /run/mosquitto/pid + acl_file ${aclFile} + persistence true + allow_anonymous ${if cfg.allowAnonymous then "true" else "false"} + bind_address ${cfg.host} + port ${toString cfg.port} + ${listenerConf} + ${cfg.extraConf} + ''; + + userAcl = (concatStringsSep "\n\n" (mapAttrsToList (n: c: + "user ${n}\n" + (concatStringsSep "\n" c.acl)) cfg.users + )); + + aclFile = pkgs.writeText "mosquitto.acl" '' + ${cfg.aclExtraConf} + ${userAcl} + ''; + +in + +{ + + ###### Interface + + options = { + services.mosquitto = { + enable = mkEnableOption "Enable the MQTT Mosquitto broker."; + + host = mkOption { + default = "127.0.0.1"; + example = "0.0.0.0"; + type = types.string; + description = '' + Host to listen on without SSL. + ''; + }; + + port = mkOption { + default = 1883; + example = 1883; + type = types.int; + description = '' + Port on which to listen without SSL. + ''; + }; + + ssl = { + enable = mkEnableOption "Enable SSL listener."; + + cafile = mkOption { + type = types.nullOr types.path; + default = null; + description = "Path to PEM encoded CA certificates."; + }; + + certfile = mkOption { + type = types.nullOr types.path; + default = null; + description = "Path to PEM encoded server certificate."; + }; + + keyfile = mkOption { + type = types.nullOr types.path; + default = null; + description = "Path to PEM encoded server key."; + }; + + host = mkOption { + default = "0.0.0.0"; + example = "localhost"; + type = types.string; + description = '' + Host to listen on with SSL. + ''; + }; + + port = mkOption { + default = 8883; + example = 8883; + type = types.int; + description = '' + Port on which to listen with SSL. + ''; + }; + }; + + dataDir = mkOption { + default = "/var/lib/mosquitto"; + type = types.path; + description = '' + The data directory. + ''; + }; + + users = mkOption { + type = types.attrsOf (types.submodule { + options = { + password = mkOption { + type = with types; uniq (nullOr str); + default = null; + description = '' + Specifies the (clear text) password for the MQTT User. + ''; + }; + + hashedPassword = mkOption { + type = with types; uniq (nullOr str); + default = null; + description = '' + Specifies the hashed password for the MQTT User. + <option>hashedPassword</option> overrides <option>password</option>. + To generate hashed password install <literal>mkpasswd</literal> + package and run <literal>mkpasswd -m sha-512</literal>. + ''; + }; + + acl = mkOption { + type = types.listOf types.string; + example = [ "topic read A/B" "topic A/#" ]; + description = '' + Control client access to topics on the broker. + ''; + }; + }; + }); + example = { john = { password = "123456"; acl = [ "topic readwrite john/#" ]; }; }; + description = '' + A set of users and their passwords and ACLs. + ''; + }; + + allowAnonymous = mkOption { + default = false; + example = true; + type = types.bool; + description = '' + Allow clients to connect without authentication. + ''; + }; + + extraConf = mkOption { + default = ""; + type = types.lines; + description = '' + Extra config to append to `mosquitto.conf` file. + ''; + }; + + aclExtraConf = mkOption { + default = ""; + type = types.lines; + description = '' + Extra config to prepend to the ACL file. + ''; + }; + + }; + }; + + + ###### Implementation + + config = mkIf cfg.enable { + + systemd.services.mosquitto = { + description = "Mosquitto MQTT Broker Daemon"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + serviceConfig = { + Type = "forking"; + User = "mosquitto"; + Group = "mosquitto"; + RuntimeDirectory = "mosquitto"; + WorkingDirectory = cfg.dataDir; + Restart = "on-failure"; + ExecStart = "${pkgs.mosquitto}/bin/mosquitto -c ${mosquittoConf} -d"; + ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + PIDFile = "/run/mosquitto/pid"; + }; + preStart = '' + rm -f ${cfg.dataDir}/passwd + touch ${cfg.dataDir}/passwd + '' + concatStringsSep "\n" ( + mapAttrsToList (n: c: + if c.hashedPassword != null then + "echo '${n}:${c.hashedPassword}' > ${cfg.dataDir}/passwd" + else optionalString (c.password != null) + "${pkgs.mosquitto}/bin/mosquitto_passwd -b ${cfg.dataDir}/passwd ${n} ${c.password}" + ) cfg.users); + }; + + users.extraUsers.mosquitto = { + description = "Mosquitto MQTT Broker Daemon owner"; + group = "mosquitto"; + uid = config.ids.uids.mosquitto; + home = cfg.dataDir; + createHome = true; + }; + + users.extraGroups.mosquitto.gid = config.ids.gids.mosquitto; + + }; +} diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix index e9eea6a2cae1..9912ad9ae3fc 100644 --- a/nixos/modules/services/networking/networkmanager.nix +++ b/nixos/modules/services/networking/networkmanager.nix @@ -114,12 +114,10 @@ in { # Ugly hack for using the correct gnome3 packageSet basePackages = mkOption { type = types.attrsOf types.package; - default = { inherit modemmanager wpa_supplicant + default = { inherit networkmanager modemmanager wpa_supplicant networkmanager_openvpn networkmanager_vpnc networkmanager_openconnect - networkmanager_pptp networkmanager_l2tp; - networkmanager = networkmanager.out; - }; + networkmanager_pptp networkmanager_l2tp; }; internal = true; }; @@ -189,7 +187,7 @@ in { boot.kernelModules = [ "ppp_mppe" ]; # Needed for most (all?) PPTP VPN connections. - environment.etc = with mapAttrs (name: getBin) cfg.basePackages; [ + environment.etc = with cfg.basePackages; [ { source = ipUpScript; target = "NetworkManager/dispatcher.d/01nixos-ip-up"; } diff --git a/nixos/modules/services/networking/ntpd.nix b/nixos/modules/services/networking/ntpd.nix index 5256fc9bc071..c8a085679280 100644 --- a/nixos/modules/services/networking/ntpd.nix +++ b/nixos/modules/services/networking/ntpd.nix @@ -82,6 +82,8 @@ in { description = "NTP Daemon"; wantedBy = [ "multi-user.target" ]; + wants = [ "time-sync.target" ]; + before = [ "time-sync.target" ]; preStart = '' diff --git a/nixos/modules/services/networking/openntpd.nix b/nixos/modules/services/networking/openntpd.nix index e53fc574fbea..a8625fa2fa91 100644 --- a/nixos/modules/services/networking/openntpd.nix +++ b/nixos/modules/services/networking/openntpd.nix @@ -64,7 +64,8 @@ in systemd.services.openntpd = { description = "OpenNTP Server"; wantedBy = [ "multi-user.target" ]; - wants = [ "network-online.target" ]; + wants = [ "network-online.target" "time-sync.target" ]; + before = [ "time-sync.target" ]; after = [ "dnsmasq.service" "bind.service" "network-online.target" ]; serviceConfig.ExecStart = "${package}/sbin/ntpd -d -f ${cfgFile} ${cfg.extraOptions}"; }; diff --git a/nixos/modules/services/networking/openvpn.nix b/nixos/modules/services/networking/openvpn.nix index a96888dec864..82173a841a3f 100644 --- a/nixos/modules/services/networking/openvpn.nix +++ b/nixos/modules/services/networking/openvpn.nix @@ -29,21 +29,27 @@ let done ${cfg.up} + ${optionalString cfg.updateResolvConf + "${pkgs.update-resolv-conf}/libexec/openvpn/update-resolv-conf"} ''; downScript = '' #! /bin/sh export PATH=${path} + ${optionalString cfg.updateResolvConf + "${pkgs.update-resolv-conf}/libexec/openvpn/update-resolv-conf"} ${cfg.down} ''; configFile = pkgs.writeText "openvpn-config-${name}" '' errors-to-stderr - ${optionalString (cfg.up != "" || cfg.down != "") "script-security 2"} + ${optionalString (cfg.up != "" || cfg.down != "" || cfg.updateResolvConf) "script-security 2"} ${cfg.config} - ${optionalString (cfg.up != "") "up ${pkgs.writeScript "openvpn-${name}-up" upScript}"} - ${optionalString (cfg.down != "") "down ${pkgs.writeScript "openvpn-${name}-down" downScript}"} + ${optionalString (cfg.up != "" || cfg.updateResolvConf) + "up ${pkgs.writeScript "openvpn-${name}-up" upScript}"} + ${optionalString (cfg.down != "" || cfg.updateResolvConf) + "down ${pkgs.writeScript "openvpn-${name}-down" downScript}"} ''; in { @@ -145,6 +151,16 @@ in description = "Whether this OpenVPN instance should be started automatically."; }; + updateResolvConf = mkOption { + default = false; + type = types.bool; + description = '' + Use the script from the update-resolv-conf package to automatically + update resolv.conf with the DNS information provided by openvpn. The + script will be run after the "up" commands and before the "down" commands. + ''; + }; + }; }; diff --git a/nixos/modules/services/networking/pptpd.nix b/nixos/modules/services/networking/pptpd.nix new file mode 100644 index 000000000000..513e6174752c --- /dev/null +++ b/nixos/modules/services/networking/pptpd.nix @@ -0,0 +1,124 @@ +{ config, stdenv, pkgs, lib, ... }: + +with lib; + +{ + options = { + services.pptpd = { + enable = mkEnableOption "Whether pptpd should be run on startup."; + + serverIp = mkOption { + type = types.string; + description = "The server-side IP address."; + default = "10.124.124.1"; + }; + + clientIpRange = mkOption { + type = types.string; + description = "The range from which client IPs are drawn."; + default = "10.124.124.2-11"; + }; + + maxClients = mkOption { + type = types.int; + description = "The maximum number of simultaneous connections."; + default = 10; + }; + + extraPptpdOptions = mkOption { + type = types.lines; + description = "Adds extra lines to the pptpd configuration file."; + default = ""; + }; + + extraPppdOptions = mkOption { + type = types.lines; + description = "Adds extra lines to the pppd options file."; + default = ""; + example = '' + ms-dns 8.8.8.8 + ms-dns 8.8.4.4 + ''; + }; + }; + }; + + config = mkIf config.services.pptpd.enable { + systemd.services.pptpd = let + cfg = config.services.pptpd; + + pptpd-conf = pkgs.writeText "pptpd.conf" '' + # Inspired from pptpd-1.4.0/samples/pptpd.conf + ppp ${ppp-pptpd-wrapped}/bin/pppd + option ${pppd-options} + pidfile /run/pptpd.pid + localip ${cfg.serverIp} + remoteip ${cfg.clientIpRange} + connections ${toString cfg.maxClients} # (Will get harmless warning if inconsistent with IP range) + + # Extra + ${cfg.extraPptpdOptions} + ''; + + pppd-options = pkgs.writeText "ppp-options-pptpd.conf" '' + # From: cat pptpd-1.4.0/samples/options.pptpd | grep -v ^# | grep -v ^$ + name pptpd + refuse-pap + refuse-chap + refuse-mschap + require-mschap-v2 + require-mppe-128 + proxyarp + lock + nobsdcomp + novj + novjccomp + nologfd + + # Extra: + ${cfg.extraPppdOptions} + ''; + + ppp-pptpd-wrapped = pkgs.stdenv.mkDerivation { + name = "ppp-pptpd-wrapped"; + phases = [ "installPhase" ]; + buildInputs = with pkgs; [ makeWrapper ]; + installPhase = '' + mkdir -p $out/bin + makeWrapper ${pkgs.ppp}/bin/pppd $out/bin/pppd \ + --set LD_PRELOAD "${pkgs.libredirect}/lib/libredirect.so" \ + --set NIX_REDIRECTS "/etc/ppp=/etc/ppp-pptpd" + ''; + }; + in { + description = "pptpd server"; + + requires = [ "network-online.target" ]; + wantedBy = [ "multi-user.target" ]; + + preStart = '' + mkdir -p -m 700 /etc/ppp-pptpd + + secrets="/etc/ppp-pptpd/chap-secrets" + + [ -f "$secrets" ] || cat > "$secrets" << EOF + # From: pptpd-1.4.0/samples/chap-secrets + # Secrets for authentication using CHAP + # client server secret IP addresses + #username pptpd password * + EOF + + chown root.root "$secrets" + chmod 600 "$secrets" + ''; + + serviceConfig = { + ExecStart = "${pkgs.pptpd}/bin/pptpd --conf ${pptpd-conf}"; + KillMode = "process"; + Restart = "on-success"; + Type = "forking"; + PIDFile = "/run/pptpd.pid"; + }; + }; + }; +} diff --git a/nixos/modules/services/networking/skydns.nix b/nixos/modules/services/networking/skydns.nix index 39ebaa45a794..ba913482e3cb 100644 --- a/nixos/modules/services/networking/skydns.nix +++ b/nixos/modules/services/networking/skydns.nix @@ -83,7 +83,7 @@ in { SKYDNS_NAMESERVERS = concatStringsSep "," cfg.nameservers; }; serviceConfig = { - ExecStart = "${cfg.package}/bin/skydns"; + ExecStart = "${cfg.package.bin}/bin/skydns"; }; }; diff --git a/nixos/modules/services/networking/syncthing.nix b/nixos/modules/services/networking/syncthing.nix index 514c17c6e5d2..ef05e71ce076 100644 --- a/nixos/modules/services/networking/syncthing.nix +++ b/nixos/modules/services/networking/syncthing.nix @@ -121,7 +121,7 @@ in User = cfg.user; Group = cfg.group; PermissionsStartOnly = true; - ExecStart = "${pkgs.syncthing}/bin/syncthing -no-browser -home=${cfg.dataDir}"; + ExecStart = "${cfg.package}/bin/syncthing -no-browser -home=${cfg.dataDir}"; }; }; }; @@ -129,7 +129,7 @@ in systemd.user.services = { syncthing = header // { serviceConfig = service // { - ExecStart = "${pkgs.syncthing}/bin/syncthing -no-browser"; + ExecStart = "${cfg.package}/bin/syncthing -no-browser"; }; }; }; diff --git a/nixos/modules/services/networking/toxvpn.nix b/nixos/modules/services/networking/toxvpn.nix new file mode 100644 index 000000000000..c38424c8e273 --- /dev/null +++ b/nixos/modules/services/networking/toxvpn.nix @@ -0,0 +1,54 @@ +{ config, stdenv, pkgs, lib, ... }: + +with lib; + +{ + options = { + services.toxvpn = { + enable = mkEnableOption "enable toxvpn running on startup"; + + localip = mkOption { + type = types.string; + default = "10.123.123.1"; + description = "your ip on the vpn"; + }; + + port = mkOption { + type = types.int; + default = 33445; + description = "udp port for toxcore, port-forward to help with connectivity if you run many nodes behind one NAT"; + }; + }; + }; + + config = mkIf config.services.toxvpn.enable { + systemd.services.toxvpn = { + description = "toxvpn daemon"; + + requires = [ "network-online.target" ]; # consider replacing by NetworkManager-wait-online.service + wantedBy = [ "multi-user.target" ]; + + preStart = '' + mkdir -p /run/toxvpn || true + chown toxvpn /run/toxvpn + ''; + + serviceConfig = { + ExecStart = "${pkgs.toxvpn}/bin/toxvpn -i ${config.services.toxvpn.localip} -l /run/toxvpn/control -u toxvpn -p ${toString config.services.toxvpn.port}"; + KillMode = "process"; + Restart = "on-success"; + Type = "notify"; + }; + + restartIfChanged = false; # Likely to be used for remote admin + }; + + users.extraUsers = { + toxvpn = { + uid = config.ids.uids.toxvpn; + home = "/var/lib/toxvpn"; + createHome = true; + }; + }; + }; +} diff --git a/nixos/modules/services/networking/unbound.nix b/nixos/modules/services/networking/unbound.nix index 89762fe52488..0dd24478f409 100644 --- a/nixos/modules/services/networking/unbound.nix +++ b/nixos/modules/services/networking/unbound.nix @@ -106,8 +106,10 @@ in preStart = '' mkdir -m 0755 -p ${stateDir}/dev/ cp ${confFile} ${stateDir}/unbound.conf + ${optionalString cfg.enableRootTrustAnchor '' ${pkgs.unbound}/bin/unbound-anchor -a ${rootTrustAnchorFile} chown unbound ${stateDir} ${rootTrustAnchorFile} + ''} touch ${stateDir}/dev/random ${pkgs.utillinux}/bin/mount --bind -n /dev/random ${stateDir}/dev/random ''; diff --git a/nixos/modules/services/networking/wpa_supplicant.nix b/nixos/modules/services/networking/wpa_supplicant.nix index 53648aef1e04..8d22c10d3f78 100644 --- a/nixos/modules/services/networking/wpa_supplicant.nix +++ b/nixos/modules/services/networking/wpa_supplicant.nix @@ -129,7 +129,7 @@ in { in { description = "WPA Supplicant"; - after = [ "network-interfaces.target" ]; + after = [ "network-interfaces.target" ] ++ lib.concatMap deviceUnit ifaces; requires = lib.concatMap deviceUnit ifaces; wantedBy = [ "network.target" ]; diff --git a/nixos/modules/services/networking/xl2tpd.nix b/nixos/modules/services/networking/xl2tpd.nix new file mode 100644 index 000000000000..5e006c13f0d0 --- /dev/null +++ b/nixos/modules/services/networking/xl2tpd.nix @@ -0,0 +1,143 @@ +{ config, stdenv, pkgs, lib, ... }: + +with lib; + +{ + options = { + services.xl2tpd = { + enable = mkEnableOption "Whether xl2tpd should be run on startup."; + + serverIp = mkOption { + type = types.string; + description = "The server-side IP address."; + default = "10.125.125.1"; + }; + + clientIpRange = mkOption { + type = types.string; + description = "The range from which client IPs are drawn."; + default = "10.125.125.2-11"; + }; + + extraXl2tpOptions = mkOption { + type = types.lines; + description = "Adds extra lines to the xl2tpd configuration file."; + default = ""; + }; + + extraPppdOptions = mkOption { + type = types.lines; + description = "Adds extra lines to the pppd options file."; + default = ""; + example = '' + ms-dns 8.8.8.8 + ms-dns 8.8.4.4 + ''; + }; + }; + }; + + config = mkIf config.services.xl2tpd.enable { + systemd.services.xl2tpd = let + cfg = config.services.xl2tpd; + + # Config files from https://help.ubuntu.com/community/L2TPServer + xl2tpd-conf = pkgs.writeText "xl2tpd.conf" '' + [global] + ipsec saref = no + + [lns default] + local ip = ${cfg.serverIp} + ip range = ${cfg.clientIpRange} + pppoptfile = ${pppd-options} + length bit = yes + + ; Extra + ${cfg.extraXl2tpOptions} + ''; + + pppd-options = pkgs.writeText "ppp-options-xl2tpd.conf" '' + refuse-pap + refuse-chap + refuse-mschap + require-mschap-v2 + # require-mppe-128 + asyncmap 0 + auth + crtscts + idle 1800 + mtu 1200 + mru 1200 + lock + hide-password + local + # debug + name xl2tpd + # proxyarp + lcp-echo-interval 30 + lcp-echo-failure 4 + + # Extra: + ${cfg.extraPppdOptions} + ''; + + xl2tpd-ppp-wrapped = pkgs.stdenv.mkDerivation { + name = "xl2tpd-ppp-wrapped"; + phases = [ "installPhase" ]; + buildInputs = with pkgs; [ makeWrapper ]; + installPhase = '' + mkdir -p $out/bin + + makeWrapper ${pkgs.ppp}/sbin/pppd $out/bin/pppd \ + --set LD_PRELOAD "${pkgs.libredirect}/lib/libredirect.so" \ + --set NIX_REDIRECTS "/etc/ppp=/etc/xl2tpd/ppp" + + makeWrapper ${pkgs.xl2tpd}/bin/xl2tpd $out/bin/xl2tpd \ + --set LD_PRELOAD "${pkgs.libredirect}/lib/libredirect.so" \ + --set NIX_REDIRECTS "${pkgs.ppp}/sbin/pppd=$out/bin/pppd" + ''; + }; + in { + description = "xl2tpd server"; + + requires = [ "network-online.target" ]; + wantedBy = [ "multi-user.target" ]; + + preStart = '' + mkdir -p -m 700 /etc/xl2tpd + + pushd /etc/xl2tpd > /dev/null + + mkdir -p -m 700 ppp + + [ -f ppp/chap-secrets ] || cat > ppp/chap-secrets << EOF + # Secrets for authentication using CHAP + # client server secret IP addresses + #username xl2tpd password * + EOF + + chown root.root ppp/chap-secrets + chmod 600 ppp/chap-secrets + + # The documentation says this file should be present but doesn't explain why and things work even if not there: + [ -f l2tp-secrets ] || (echo -n "* * "; ${pkgs.apg}/bin/apg -n 1 -m 32 -x 32 -a 1 -M LCN) > l2tp-secrets + chown root.root l2tp-secrets + chmod 600 l2tp-secrets + + popd > /dev/null + + mkdir -p /run/xl2tpd + chown root.root /run/xl2tpd + chmod 700 /run/xl2tpd + ''; + + serviceConfig = { + ExecStart = "${xl2tpd-ppp-wrapped}/bin/xl2tpd -D -c ${xl2tpd-conf} -s /etc/xl2tpd/l2tp-secrets -p /run/xl2tpd/pid -C /run/xl2tpd/control"; + KillMode = "process"; + Restart = "on-success"; + Type = "simple"; + PIDFile = "/run/xl2tpd/pid"; + }; + }; + }; +} diff --git a/nixos/modules/services/security/fail2ban.nix b/nixos/modules/services/security/fail2ban.nix index 33c4910fc0ce..22e3bb0066cc 100644 --- a/nixos/modules/services/security/fail2ban.nix +++ b/nixos/modules/services/security/fail2ban.nix @@ -102,7 +102,7 @@ in partOf = optional config.networking.firewall.enable "firewall.service"; restartTriggers = [ fail2banConf jailConf ]; - path = [ pkgs.fail2ban pkgs.iptables ]; + path = [ pkgs.fail2ban pkgs.iptables pkgs.iproute ]; preStart = '' diff --git a/nixos/modules/services/security/hologram.nix b/nixos/modules/services/security/hologram.nix index 58f308df7a21..e267fed27955 100644 --- a/nixos/modules/services/security/hologram.nix +++ b/nixos/modules/services/security/hologram.nix @@ -95,7 +95,7 @@ in { wantedBy = [ "multi-user.target" ]; serviceConfig = { - ExecStart = "${pkgs.hologram}/bin/hologram-server --debug --conf ${cfgFile}"; + ExecStart = "${pkgs.hologram.bin}/bin/hologram-server --debug --conf ${cfgFile}"; }; }; }; diff --git a/nixos/modules/services/security/oauth2_proxy.nix b/nixos/modules/services/security/oauth2_proxy.nix new file mode 100644 index 000000000000..4c20392214fc --- /dev/null +++ b/nixos/modules/services/security/oauth2_proxy.nix @@ -0,0 +1,523 @@ +# NixOS module for oauth2_proxy. + +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.services.oauth2_proxy; + + # Use like: + # repeatedArgs (arg: "--arg=${arg}") args + repeatedArgs = concatMapStringsSep " "; + + # 'toString' doesn't quite do what we want for bools. + fromBool = x: if x then "true" else "false"; + + # oauth2_proxy provides many options that are only relevant if you are using + # a certain provider. This set maps from provider name to a function that + # takes the configuration and returns a string that can be inserted into the + # command-line to launch oauth2_proxy. + providerSpecificOptions = { + azure = cfg: '' + --azure-tenant=${cfg.azure.tenant} \ + --resource=${cfg.azure.resource} \ + ''; + + github = cfg: '' + $(optionalString (!isNull cfg.github.org) "--github-org=${cfg.github.org}") \ + $(optionalString (!isNull cfg.github.team) "--github-org=${cfg.github.team}") \ + ''; + + google = cfg: '' + --google-admin-email=${cfg.google.adminEmail} \ + --google-service-account=${cfg.google.serviceAccountJSON} \ + $(repeatedArgs (group: "--google-group=${group}") cfg.google.groups) \ + ''; + }; + + authenticatedEmailsFile = pkgs.writeText "authenticated-emails" cfg.email.addresses; + + getProviderOptions = cfg: provider: + if providerSpecificOptions ? provider then providerSpecificOptions.provider cfg else ""; + + mkCommandLine = cfg: '' + --provider='${cfg.provider}' \ + ${optionalString (!isNull cfg.email.addresses) "--authenticated-emails-file='${authenticatedEmailsFile}'"} \ + --approval-prompt='${cfg.approvalPrompt}' \ + ${optionalString (cfg.passBasicAuth && !isNull cfg.basicAuthPassword) "--basic-auth-password='${cfg.basicAuthPassword}'"} \ + --client-id='${cfg.clientID}' \ + --client-secret='${cfg.clientSecret}' \ + ${optionalString (!isNull cfg.cookie.domain) "--cookie-domain='${cfg.cookie.domain}'"} \ + --cookie-expire='${cfg.cookie.expire}' \ + --cookie-httponly=${fromBool cfg.cookie.httpOnly} \ + --cookie-name='${cfg.cookie.name}' \ + --cookie-secret='${cfg.cookie.secret}' \ + --cookie-secure=${fromBool cfg.cookie.secure} \ + ${optionalString (!isNull cfg.cookie.refresh) "--cookie-refresh='${cfg.cookie.refresh}'"} \ + ${optionalString (!isNull cfg.customTemplatesDir) "--custom-templates-dir='${cfg.customTemplatesDir}'"} \ + ${repeatedArgs (x: "--email-domain='${x}'") cfg.email.domains} \ + --http-address='${cfg.httpAddress}' \ + ${optionalString (!isNull cfg.htpasswd.file) "--htpasswd-file='${cfg.htpasswd.file}' --display-htpasswd-form=${fromBool cfg.htpasswd.displayForm}"} \ + ${optionalString (!isNull cfg.loginURL) "--login-url='${cfg.loginURL}'"} \ + --pass-access-token=${fromBool cfg.passAccessToken} \ + --pass-basic-auth=${fromBool cfg.passBasicAuth} \ + --pass-host-header=${fromBool cfg.passHostHeader} \ + --proxy-prefix='${cfg.proxyPrefix}' \ + ${optionalString (!isNull cfg.profileURL) "--profile-url='${cfg.profileURL}'"} \ + ${optionalString (!isNull cfg.redeemURL) "--redeem-url='${cfg.redeemURL}'"} \ + ${optionalString (!isNull cfg.redirectURL) "--redirect-url='${cfg.redirectURL}'"} \ + --request-logging=${fromBool cfg.requestLogging} \ + ${optionalString (!isNull cfg.scope) "--scope='${cfg.scope}'"} \ + ${repeatedArgs (x: "--skip-auth-regex='${x}'") cfg.skipAuthRegexes} \ + ${optionalString (!isNull cfg.signatureKey) "--signature-key='${cfg.signatureKey}'"} \ + --upstream='${cfg.upstream}' \ + ${optionalString (!isNull cfg.validateURL) "--validate-url='${cfg.validateURL}'"} \ + ${optionalString cfg.tls.enable "--tls-cert='${cfg.tls.certificate}' --tls-key='${cfg.tls.key}' --https-address='${cfg.tls.httpsAddress}'"} \ + '' + getProviderOptions cfg cfg.provider; +in +{ + options.services.oauth2_proxy = { + enable = mkEnableOption "oauth2_proxy"; + + package = mkOption { + type = types.package; + default = pkgs.oauth2_proxy; + defaultText = "pkgs.oauth2_proxy"; + description = '' + The package that provides oauth2_proxy. + ''; + }; + + ############################################## + # PROVIDER configuration + provider = mkOption { + type = types.enum [ + "google" + "github" + "azure" + "gitlab" + "linkedin" + "myusa" + ]; + default = "google"; + description = '' + OAuth provider. + ''; + }; + + approvalPrompt = mkOption { + type = types.enum ["force" "auto"]; + default = "force"; + description = '' + OAuth approval_prompt. + ''; + }; + + clientID = mkOption { + type = types.str; + description = '' + The OAuth Client ID. + ''; + example = "123456.apps.googleusercontent.com"; + }; + + clientSecret = mkOption { + type = types.str; + description = '' + The OAuth Client Secret. + ''; + }; + + skipAuthRegexes = mkOption { + type = types.listOf types.str; + default = []; + description = '' + Skip authentication for requests matching any of these regular + expressions. + ''; + }; + + # XXX: Not clear whether these two options are mutually exclusive or not. + email = { + domains = mkOption { + type = types.listOf types.str; + default = []; + description = '' + Authenticate emails with the specified domains. Use + <literal>*</literal> to authenticate any email. + ''; + }; + + addresses = mkOption { + type = types.nullOr types.lines; + default = null; + description = '' + Line-separated email addresses that are allowed to authenticate. + ''; + }; + }; + + loginURL = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Authentication endpoint. + + You only need to set this if you are using a self-hosted provider (e.g. + Github Enterprise). If you're using a publicly hosted provider + (e.g github.com), then the default works. + ''; + example = "https://provider.example.com/oauth/authorize"; + }; + + redeemURL = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Token redemption endpoint. + + You only need to set this if you are using a self-hosted provider (e.g. + Github Enterprise). If you're using a publicly hosted provider + (e.g github.com), then the default works. + ''; + example = "https://provider.example.com/oauth/token"; + }; + + validateURL = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Access token validation endpoint. + + You only need to set this if you are using a self-hosted provider (e.g. + Github Enterprise). If you're using a publicly hosted provider + (e.g github.com), then the default works. + ''; + example = "https://provider.example.com/user/emails"; + }; + + redirectURL = mkOption { + # XXX: jml suspects this is always necessary, but the command-line + # doesn't require it so making it optional. + type = types.nullOr types.str; + default = null; + description = '' + The OAuth2 redirect URL. + ''; + example = "https://internalapp.yourcompany.com/oauth2/callback"; + }; + + azure = { + tenant = mkOption { + type = types.str; + default = "common"; + description = '' + Go to a tenant-specific or common (tenant-independent) endpoint. + ''; + }; + + resource = mkOption { + type = types.str; + description = '' + The resource that is protected. + ''; + }; + }; + + google = { + adminEmail = mkOption { + type = types.str; + description = '' + The Google Admin to impersonate for API calls. + + Only users with access to the Admin APIs can access the Admin SDK + Directory API, thus the service account needs to impersonate one of + those users to access the Admin SDK Directory API. + + See <link xlink:href="https://developers.google.com/admin-sdk/directory/v1/guides/delegation#delegate_domain-wide_authority_to_your_service_account" />. + ''; + }; + + groups = mkOption { + type = types.listOf types.str; + default = []; + description = '' + Restrict logins to members of these Google groups. + ''; + }; + + serviceAccountJSON = mkOption { + type = types.path; + description = '' + The path to the service account JSON credentials. + ''; + }; + }; + + github = { + org = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Restrict logins to members of this organisation. + ''; + }; + + team = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Restrict logins to members of this team. + ''; + }; + }; + + + #################################################### + # UPSTREAM Configuration + upstream = mkOption { + type = types.commas; + description = '' + The http url(s) of the upstream endpoint or <literal>file://</literal> + paths for static files. Routing is based on the path. + ''; + }; + + passAccessToken = mkOption { + type = types.bool; + default = false; + description = '' + Pass OAuth access_token to upstream via X-Forwarded-Access-Token header. + ''; + }; + + passBasicAuth = mkOption { + type = types.bool; + default = true; + description = '' + Pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream. + ''; + }; + + basicAuthPassword = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The password to set when passing the HTTP Basic Auth header. + ''; + }; + + passHostHeader = mkOption { + type = types.bool; + default = true; + description = '' + Pass the request Host Header to upstream. + ''; + }; + + signatureKey = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + GAP-Signature request signature key. + ''; + example = "sha1:secret0"; + }; + + cookie = { + domain = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + An optional cookie domain to force cookies to. + ''; + example = ".yourcompany.com"; + }; + + expire = mkOption { + type = types.str; + default = "168h0m0s"; + description = '' + Expire timeframe for cookie. + ''; + }; + + httpOnly = mkOption { + type = types.bool; + default = true; + description = '' + Set HttpOnly cookie flag. + ''; + }; + + name = mkOption { + type = types.str; + default = "_oauth2_proxy"; + description = '' + The name of the cookie that the oauth_proxy creates. + ''; + }; + + refresh = mkOption { + # XXX: Unclear what the behavior is when this is not specified. + type = types.nullOr types.str; + default = null; + description = '' + Refresh the cookie after this duration; 0 to disable. + ''; + example = "168h0m0s"; + }; + + secret = mkOption { + type = types.str; + description = '' + The seed string for secure cookies. + ''; + }; + + secure = mkOption { + type = types.bool; + default = true; + description = '' + Set secure (HTTPS) cookie flag. + ''; + }; + }; + + #################################################### + # OAUTH2 PROXY configuration + + httpAddress = mkOption { + type = types.str; + default = "127.0.0.1:4180"; + description = '' + HTTPS listening address. This module does not expose the port by + default. If you want this URL to be accessible to other machines, please + add the port to <literal>networking.firewall.allowedTCPPorts</literal>. + ''; + }; + + htpasswd = { + file = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + Additionally authenticate against a htpasswd file. Entries must be + created with <literal>htpasswd -s</literal> for SHA encryption. + ''; + }; + + displayForm = mkOption { + type = types.bool; + default = true; + description = '' + Display username / password login form if an htpasswd file is provided. + ''; + }; + }; + + customTemplatesDir = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + Path to custom HTML templates. + ''; + }; + + proxyPrefix = mkOption { + type = types.str; + default = "/oauth2"; + description = '' + The url root path that this proxy should be nested under. + ''; + }; + + tls = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to serve over TLS. + ''; + }; + + certificate = mkOption { + type = types.path; + description = '' + Path to certificate file. + ''; + }; + + key = mkOption { + type = types.path; + description = '' + Path to private key file. + ''; + }; + + httpsAddress = mkOption { + type = types.str; + default = ":443"; + description = '' + <literal>addr:port</literal> to listen on for HTTPS clients. + + Remember to add <literal>port</literal> to + <literal>allowedTCPPorts</literal> if you want other machines to be + able to connect to it. + ''; + }; + }; + + requestLogging = mkOption { + type = types.bool; + default = true; + description = '' + Log requests to stdout. + ''; + }; + + #################################################### + # UNKNOWN + + # XXX: Is this mandatory? Is it part of another group? Is it part of the provider specification? + scope = mkOption { + # XXX: jml suspects this is always necessary, but the command-line + # doesn't require it so making it optional. + type = types.nullOr types.str; + default = null; + description = '' + OAuth scope specification. + ''; + }; + + profileURL = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Profile access endpoint. + ''; + }; + + }; + + config = mkIf cfg.enable { + + users.extraUsers.oauth2_proxy = { + description = "OAuth2 Proxy"; + }; + + systemd.services.oauth2_proxy = { + description = "OAuth2 Proxy"; + path = [ cfg.package ]; + wantedBy = [ "multi-user.target" ]; + after = [ "network-interfaces.target" ]; + + serviceConfig = { + User = "oauth2_proxy"; + Restart = "always"; + ExecStart = "${cfg.package.bin}/bin/oauth2_proxy ${mkCommandLine cfg}"; + }; + }; + + }; +} diff --git a/nixos/modules/services/torrent/transmission.nix b/nixos/modules/services/torrent/transmission.nix index 32203a522b0c..5154aaca3bc2 100644 --- a/nixos/modules/services/torrent/transmission.nix +++ b/nixos/modules/services/torrent/transmission.nix @@ -113,22 +113,22 @@ in #include <abstractions/base> #include <abstractions/nameservice> - ${pkgs.glibc.out}/lib/*.so mr, - ${pkgs.libevent.out}/lib/libevent*.so* mr, - ${pkgs.curl.out}/lib/libcurl*.so* mr, - ${pkgs.openssl.out}/lib/libssl*.so* mr, - ${pkgs.openssl.out}/lib/libcrypto*.so* mr, - ${pkgs.zlib.out}/lib/libz*.so* mr, - ${pkgs.libssh2.out}/lib/libssh2*.so* mr, - ${pkgs.systemd}/lib/libsystemd*.so* mr, - ${pkgs.xz.out}/lib/liblzma*.so* mr, - ${pkgs.libgcrypt.out}/lib/libgcrypt*.so* mr, - ${pkgs.libgpgerror.out}/lib/libgpg-error*.so* mr, - ${pkgs.nghttp2.lib}/lib/libnghttp2*.so* mr, - ${pkgs.c-ares.out}/lib/libcares*.so* mr, - ${pkgs.libcap.lib}/lib/libcap*.so* mr, - ${pkgs.attr.out}/lib/libattr*.so* mr, - ${pkgs.lz4}/lib/liblz4*.so* mr, + ${getLib pkgs.glibc}/lib/*.so mr, + ${getLib pkgs.libevent}/lib/libevent*.so* mr, + ${getLib pkgs.curl}/lib/libcurl*.so* mr, + ${getLib pkgs.openssl}/lib/libssl*.so* mr, + ${getLib pkgs.openssl}/lib/libcrypto*.so* mr, + ${getLib pkgs.zlib}/lib/libz*.so* mr, + ${getLib pkgs.libssh2}/lib/libssh2*.so* mr, + ${getLib pkgs.systemd}/lib/libsystemd*.so* mr, + ${getLib pkgs.xz}/lib/liblzma*.so* mr, + ${getLib pkgs.libgcrypt}/lib/libgcrypt*.so* mr, + ${getLib pkgs.libgpgerror}/lib/libgpg-error*.so* mr, + ${getLib pkgs.nghttp2}/lib/libnghttp2*.so* mr, + ${getLib pkgs.c-ares}/lib/libcares*.so* mr, + ${getLib pkgs.libcap}/lib/libcap*.so* mr, + ${getLib pkgs.attr}/lib/libattr*.so* mr, + ${getLib pkgs.lz4}/lib/liblz4*.so* mr, @{PROC}/sys/kernel/random/uuid r, @{PROC}/sys/vm/overcommit_memory r, diff --git a/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixos/modules/services/web-servers/apache-httpd/default.nix index c23897192b4c..9844e3c435d1 100644 --- a/nixos/modules/services/web-servers/apache-httpd/default.nix +++ b/nixos/modules/services/web-servers/apache-httpd/default.nix @@ -337,6 +337,7 @@ let allModules = concatMap (svc: svc.extraModulesPre) allSubservices ++ map (name: {inherit name; path = "${httpd}/modules/mod_${name}.so";}) apacheModules + ++ optional mainCfg.enableMellon { name = "auth_mellon"; path = "${pkgs.apacheHttpdPackages.mod_auth_mellon}/modules/mod_auth_mellon.so"; } ++ optional enablePHP { name = "php5"; path = "${php}/modules/libphp5.so"; } ++ concatMap (svc: svc.extraModules) allSubservices ++ extraForeignModules; @@ -541,6 +542,12 @@ in ''; }; + enableMellon = mkOption { + type = types.bool; + default = false; + description = "Whether to enable the mod_auth_mellon module."; + }; + enablePHP = mkOption { type = types.bool; default = false; @@ -650,6 +657,7 @@ in environment = optionalAttrs enablePHP { PHPRC = phpIni; } + // optionalAttrs mainCfg.enableMellon { LD_LIBRARY_PATH = "${pkgs.xmlsec}/lib"; } // (listToAttrs (concatMap (svc: svc.globalEnvVars) allSubservices)); preStart = diff --git a/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix b/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix index 0fe8d1a89cf3..b4b5a6fdc07e 100644 --- a/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix +++ b/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix @@ -43,7 +43,7 @@ let # Paths to external programs. $wgDiff3 = "${pkgs.diffutils}/bin/diff3"; $wgDiff = "${pkgs.diffutils}/bin/diff"; - $wgImageMagickConvertCommand = "${pkgs.imagemagick}/bin/convert"; + $wgImageMagickConvertCommand = "${pkgs.imagemagick.out}/bin/convert"; #$wgDebugLogFile = "/tmp/mediawiki_debug_log.txt"; diff --git a/nixos/modules/services/web-servers/lighttpd/inginious.nix b/nixos/modules/services/web-servers/lighttpd/inginious.nix new file mode 100644 index 000000000000..43deccb6aef8 --- /dev/null +++ b/nixos/modules/services/web-servers/lighttpd/inginious.nix @@ -0,0 +1,262 @@ +{ config, lib, pkgs, ... }: +with lib; + +let + cfg = config.services.lighttpd.inginious; + inginious = pkgs.inginious; + execName = "inginious-${if cfg.useLTI then "lti" else "webapp"}"; + + inginiousConfigFile = if cfg.configFile != null then cfg.configFile else pkgs.writeText "inginious.yaml" '' + # Backend; can be: + # - "local" (run containers on the same machine) + # - "remote" (connect to distant docker daemon and auto start agents) (choose this if you use boot2docker) + # - "remote_manual" (connect to distant and manually installed agents) + backend: "${cfg.backendType}" + + ## TODO (maybe): Add an option for the "remote" backend in this NixOS module. + # List of remote docker daemon to which the backend will try + # to connect (backend: remote only) + #docker_daemons: + # - # Host of the docker daemon *from the webapp* + # remote_host: "some.remote.server" + # # Port of the distant docker daemon *from the webapp* + # remote_docker_port: "2375" + # # A mandatory port used by the backend and the agent that will be automatically started. + # # Needs to be available on the remote host, and to be open in the firewall. + # remote_agent_port: "63456" + # # Does the remote docker requires tls? Defaults to false. + # # Parameter can be set to true or path to the certificates + # #use_tls: false + # # Link to the docker daemon *from the host that runs the docker daemon*. Defaults to: + # #local_location: "unix:///var/run/docker.sock" + # # Path to the cgroups "mount" *from the host that runs the docker daemon*. Defaults to: + # #cgroups_location: "/sys/fs/cgroup" + # # Name that will be used to reference the agent + # #"agent_name": "inginious-agent" + + # List of remote agents to which the backend will try + # to connect (backend: remote_manual only) + # Example: + #agents: + # - host: "192.168.59.103" + # port: 5001 + agents: + ${lib.concatMapStrings (agent: + " - host: \"${agent.host}\"\n" + + " port: ${agent.port}\n" + ) cfg.remoteAgents} + + # Location of the task directory + tasks_directory: "${cfg.tasksDirectory}" + + # Super admins: list of user names that can do everything in the backend + superadmins: + ${lib.concatMapStrings (x: " - \"${x}\"\n") cfg.superadmins} + + # Aliases for containers + # Only containers listed here can be used by tasks + containers: + ${lib.concatStrings (lib.mapAttrsToList (name: fullname: + " ${name}: \"${fullname}\"\n" + ) cfg.containers)} + + # Use single minified javascript file (production) or multiple files (dev) ? + use_minified_js: true + + ## TODO (maybe): Add NixOS options for these parameters. + + # MongoDB options + #mongo_opt: + # host: localhost + # database: INGInious + + # Disable INGInious? + #maintenance: false + + #smtp: + # sendername: 'INGInious <no-reply@inginious.org>' + # host: 'smtp.gmail.com' + # port: 587 + # username: 'configme@gmail.com' + # password: 'secret' + # starttls: True + + ## NixOS extra config + + ${cfg.extraConfig} + ''; +in +{ + options.services.lighttpd.inginious = { + enable = mkEnableOption "INGInious, an automated code testing and grading system."; + + configFile = mkOption { + type = types.nullOr types.path; + default = null; + example = literalExample ''pkgs.writeText "configuration.yaml" "# custom config options ...";''; + description = ''The path to an INGInious configuration file.''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = '' + # Load the dummy auth plugin. + plugins: + - plugin_module: inginious.frontend.webapp.plugins.auth.demo_auth + users: + # register the user "test" with the password "someverycomplexpassword" + test: someverycomplexpassword + ''; + description = ''Extra option in YaML format, to be appended to the config file.''; + }; + + tasksDirectory = mkOption { + type = types.path; + default = "${inginious}/lib/python2.7/site-packages/inginious/tasks"; + example = "/var/lib/INGInious/tasks"; + description = '' + Path to the tasks folder. + Defaults to the provided test tasks folder (readonly). + ''; + }; + + useLTI = mkOption { + type = types.bool; + default = false; + description = ''Whether to start the LTI frontend in place of the webapp.''; + }; + + superadmins = mkOption { + type = types.uniq (types.listOf types.str); + default = [ "admin" ]; + example = [ "john" "pepe" "emilia" ]; + description = ''List of user logins allowed to administrate the whole server.''; + }; + + containers = mkOption { + type = types.attrsOf types.str; + default = { + default = "ingi/inginious-c-default"; + }; + example = { + default = "ingi/inginious-c-default"; + sekexe = "ingi/inginious-c-sekexe"; + java = "ingi/inginious-c-java"; + oz = "ingi/inginious-c-oz"; + pythia1compat = "ingi/inginious-c-pythia1compat"; + }; + description = '' + An attrset describing the required containers + These containers will be available in INGInious using their short name (key) + and will be automatically downloaded before INGInious starts. + ''; + }; + + hostPattern = mkOption { + type = types.str; + default = "^inginious."; + example = "^inginious.mydomain.xyz$"; + description = '' + The domain that serves INGInious. + INGInious uses absolute paths which makes it difficult to relocate in its own subdir. + The default configuration will serve INGInious when the server is accessed with a hostname starting with "inginious.". + If left blank, INGInious will take the precedence over all the other lighttpd sites, which is probably not what you want. + ''; + }; + + backendType = mkOption { + type = types.enum [ "local" "remote_manual" ]; # TODO: support backend "remote" + default = "local"; + description = '' + Select how INGINious accesses to grading containers. + The default "local" option ensures that Docker is started and provisioned. + Fore more information, see http://inginious.readthedocs.io/en/latest/install_doc/config_reference.html + Not all backends are supported. Use services.inginious.configFile for full flexibility. + ''; + }; + + remoteAgents = mkOption { + type = types.listOf (types.attrsOf types.str); + default = []; + example = [ { host = "192.0.2.25"; port = "1345"; } ]; + description = ''A list of remote agents, used only when services.inginious.backendType is "remote_manual".''; + }; + }; + + config = mkIf cfg.enable ( + mkMerge [ + # For a local install, we need docker. + (mkIf (cfg.backendType == "local") { + virtualisation.docker = { + enable = true; + # We need docker to listen on port 2375. + extraOptions = "-H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock"; + storageDriver = mkDefault "overlay"; + socketActivation = false; + }; + + users.extraUsers."lighttpd".extraGroups = [ "docker" ]; + + # Ensure that docker has pulled the required images. + systemd.services.inginious-prefetch = { + script = let + images = lib.unique ( + [ "centos" "ingi/inginious-agent" ] + ++ lib.mapAttrsToList (_: image: image) cfg.containers + ); + in lib.concatMapStrings (image: '' + ${pkgs.docker}/bin/docker pull ${image} + '') images; + + serviceConfig.Type = "oneshot"; + wants = [ "docker.service" ]; + after = [ "docker.service" ]; + wantedBy = [ "lighttpd.service" ]; + before = [ "lighttpd.service" ]; + }; + }) + + # Common + { + # To access inginous tools (like inginious-test-task) + environment.systemPackages = [ inginious ]; + + services.mongodb.enable = true; + + services.lighttpd.enable = true; + services.lighttpd.enableModules = [ "mod_access" "mod_alias" "mod_fastcgi" "mod_redirect" "mod_rewrite" ]; + services.lighttpd.extraConfig = '' + $HTTP["host"] =~ "${cfg.hostPattern}" { + fastcgi.server = ( "/${execName}" => + (( + "socket" => "/run/lighttpd/inginious-fastcgi.socket", + "bin-path" => "${inginious}/bin/${execName} --config=${inginiousConfigFile}", + "max-procs" => 1, + "bin-environment" => ( "REAL_SCRIPT_NAME" => "" ), + "check-local" => "disable" + )) + ) + url.rewrite-once = ( + "^/.well-known/.*" => "$0", + "^/static/.*" => "$0", + "^/.*$" => "/${execName}$0", + "^/favicon.ico$" => "/static/common/favicon.ico", + ) + alias.url += ( + "/static/webapp/" => "${inginious}/lib/python2.7/site-packages/inginious/frontend/webapp/static/", + "/static/common/" => "${inginious}/lib/python2.7/site-packages/inginious/frontend/common/static/" + ) + } + ''; + + systemd.services.lighttpd.preStart = '' + mkdir -p /run/lighttpd + chown lighttpd.lighttpd /run/lighttpd + ''; + + systemd.services.lighttpd.wants = [ "mongodb.service" "docker.service" ]; + systemd.services.lighttpd.after = [ "mongodb.service" "docker.service" ]; + } + ]); +} diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix index 16996b9f96c1..68579a1af836 100644 --- a/nixos/modules/services/x11/desktop-managers/gnome3.nix +++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix @@ -44,7 +44,7 @@ let ${cfg.extraGSettingsOverrides} EOF - ${pkgs.glib}/bin/glib-compile-schemas $out/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas/ + ${pkgs.glib.dev}/bin/glib-compile-schemas $out/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas/ ''; }; @@ -78,10 +78,11 @@ in { type = types.listOf types.path; description = "List of packages for which gsettings are overridden."; }; + + debug = mkEnableOption "gnome-session debug messages"; }; environment.gnome3.packageSet = mkOption { - type = types.nullOr types.package; default = null; example = literalExample "pkgs.gnome3_18"; description = "Which GNOME 3 package set to use."; @@ -118,6 +119,7 @@ in { services.telepathy.enable = mkDefault true; networking.networkmanager.enable = mkDefault true; services.upower.enable = config.powerManagement.enable; + services.dbus.packages = mkIf config.services.printing.enable [ pkgs.system-config-printer ]; hardware.bluetooth.enable = mkDefault true; fonts.fonts = [ pkgs.dejavu_fonts pkgs.cantarell_fonts ]; @@ -160,7 +162,7 @@ in { # Update user dirs as described in http://freedesktop.org/wiki/Software/xdg-user-dirs/ ${pkgs.xdg-user-dirs}/bin/xdg-user-dirs-update - ${gnome3.gnome_session}/bin/gnome-session& + ${gnome3.gnome_session}/bin/gnome-session ${optionalString cfg.debug "--debug"} & waitPID=$! ''; }; diff --git a/nixos/modules/services/x11/desktop-managers/kde5.nix b/nixos/modules/services/x11/desktop-managers/kde5.nix index 2e9183da970a..060dda1a70a8 100644 --- a/nixos/modules/services/x11/desktop-managers/kde5.nix +++ b/nixos/modules/services/x11/desktop-managers/kde5.nix @@ -117,6 +117,9 @@ in # Install activity manager if available ++ lib.optional (lib.hasAttr "kactivitymanagerd" kde5) kde5.kactivitymanagerd + # frameworkintegration was split with plasma-integration in Plasma 5.6 + ++ lib.optional (lib.hasAttr "plasma-integration" kde5) kde5.plasma-integration + # Optional hardware support features ++ lib.optional config.hardware.bluetooth.enable kde5.bluedevil ++ lib.optional config.networking.networkmanager.enable kde5.plasma-nm @@ -167,7 +170,9 @@ in services.xserver.displayManager.sddm = { theme = "breeze"; themes = [ + kde5.extra-cmake-modules # for the setup-hook kde5.plasma-workspace + kde5.breeze-icons (kde5.oxygen-icons or kde5.oxygen-icons5) ]; }; diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix index 4c4e3d967988..634d2a39576a 100644 --- a/nixos/modules/services/x11/desktop-managers/xfce.nix +++ b/nixos/modules/services/x11/desktop-managers/xfce.nix @@ -33,6 +33,14 @@ in default = false; description = "Don't install XFCE desktop components (xfdesktop, panel and notification daemon)."; }; + + extraSessionCommands = mkOption { + default = ""; + type = types.lines; + description = '' + Shell commands executed just before XFCE is started. + ''; + }; }; }; @@ -45,6 +53,8 @@ in bgSupport = true; start = '' + ${cfg.extraSessionCommands} + # Set GTK_PATH so that GTK+ can find the theme engines. export GTK_PATH="${config.system.path}/lib/gtk-2.0:${config.system.path}/lib/gtk-3.0" diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix index 376f9f4b46b5..862ddc1d13f2 100644 --- a/nixos/modules/services/x11/display-managers/default.nix +++ b/nixos/modules/services/x11/display-managers/default.nix @@ -32,6 +32,12 @@ let '' #! ${pkgs.bash}/bin/bash + ${optionalString cfg.displayManager.logToJournal '' + if [ -z "$_DID_SYSTEMD_CAT" ]; then + _DID_SYSTEMD_CAT=1 exec ${config.systemd.package}/bin/systemd-cat -t xsession -- "$0" "$1" + fi + ''} + . /etc/profile cd "$HOME" @@ -39,7 +45,7 @@ let sessionType="$1" if [ "$sessionType" = default ]; then sessionType=""; fi - ${optionalString (!cfg.displayManager.job.logsXsession) '' + ${optionalString (!cfg.displayManager.job.logsXsession && !cfg.displayManager.logToJournal) '' exec > ~/.xsession-errors 2>&1 ''} @@ -83,6 +89,8 @@ let # .local/share doesn't exist yet. mkdir -p $HOME/.local/share + unset _DID_SYSTEMD_CAT + ${cfg.displayManager.sessionCommands} # Allow the user to execute commands at the beginning of the X session. @@ -278,6 +286,16 @@ in }; + logToJournal = mkOption { + type = types.bool; + default = true; + description = '' + By default, the stdout/stderr of sessions is written + to <filename>~/.xsession-errors</filename>. When this option + is enabled, it will instead be written to the journal. + ''; + }; + }; }; diff --git a/nixos/modules/services/x11/display-managers/kdm.nix b/nixos/modules/services/x11/display-managers/kdm.nix index 9b937ff7ee18..d9f7f8f0dfc4 100644 --- a/nixos/modules/services/x11/display-managers/kdm.nix +++ b/nixos/modules/services/x11/display-managers/kdm.nix @@ -139,7 +139,7 @@ in mkdir -m 0755 -p /var/lib/kdm chown kdm /var/lib/kdm ${(optionalString (config.system.boot.loader.id == "grub" && config.system.build.grub != null) "PATH=${config.system.build.grub}/sbin:$PATH ") + - "KDEDIRS=/run/current-system/sw exec ${kdebase_workspace}/bin/kdm -config ${kdmrc} -nodaemon"} + "KDEDIRS=/run/current-system/sw exec ${kdebase_workspace}/bin/kdm -config ${kdmrc} -nodaemon -logfile /dev/stderr"} ''; logsXsession = true; }; diff --git a/nixos/modules/services/x11/hardware/synaptics.nix b/nixos/modules/services/x11/hardware/synaptics.nix index 2981e7545e81..e74b19c8e710 100644 --- a/nixos/modules/services/x11/hardware/synaptics.nix +++ b/nixos/modules/services/x11/hardware/synaptics.nix @@ -169,10 +169,10 @@ in { config = mkIf cfg.enable { - services.xserver.modules = [ pkg ]; + services.xserver.modules = [ pkg.out ]; environment.etc."${etcFile}".source = - "${pkg}/share/X11/xorg.conf.d/50-synaptics.conf"; + "${pkg.out}/share/X11/xorg.conf.d/50-synaptics.conf"; environment.systemPackages = [ pkg ]; diff --git a/nixos/modules/services/x11/window-managers/i3.nix b/nixos/modules/services/x11/window-managers/i3.nix index 2e2e10cc33b0..cfe9439b688c 100644 --- a/nixos/modules/services/x11/window-managers/i3.nix +++ b/nixos/modules/services/x11/window-managers/i3.nix @@ -3,37 +3,52 @@ with lib; let - cfg = config.services.xserver.windowManager.i3; -in + wmCfg = config.services.xserver.windowManager; -{ - options = { - services.xserver.windowManager.i3 = { - enable = mkEnableOption "i3"; - - configFile = mkOption { - default = null; - type = types.nullOr types.path; - description = '' - Path to the i3 configuration file. - If left at the default value, $HOME/.i3/config will be used. - ''; - }; + i3option = name: { + enable = mkEnableOption name; + configFile = mkOption { + default = null; + type = types.nullOr types.path; + description = '' + Path to the i3 configuration file. + If left at the default value, $HOME/.i3/config will be used. + ''; + }; + extraSessionCommands = mkOption { + default = ""; + type = types.lines; + description = '' + Shell commands executed just before i3 is started. + ''; }; }; - config = mkIf cfg.enable { - services.xserver.windowManager = { - session = [{ - name = "i3"; - start = '' - ${pkgs.i3}/bin/i3 ${optionalString (cfg.configFile != null) - "-c \"${cfg.configFile}\"" - } & - waitPID=$! - ''; - }]; - }; - environment.systemPackages = with pkgs; [ i3 ]; + i3config = name: pkg: cfg: { + services.xserver.windowManager.session = [{ + inherit name; + start = '' + ${cfg.extraSessionCommands} + + ${pkg}/bin/i3 ${optionalString (cfg.configFile != null) + "-c \"${cfg.configFile}\"" + } & + waitPID=$! + ''; + }]; + environment.systemPackages = [ pkg ]; }; + +in + +{ + options.services.xserver.windowManager = { + i3 = i3option "i3"; + i3-gaps = i3option "i3-gaps"; + }; + + config = mkMerge [ + (mkIf wmCfg.i3.enable (i3config "i3" pkgs.i3 wmCfg.i3)) + (mkIf wmCfg.i3-gaps.enable (i3config "i3-gaps" pkgs.i3-gaps wmCfg.i3-gaps)) + ]; } diff --git a/nixos/modules/services/x11/xbanish.nix b/nixos/modules/services/x11/xbanish.nix new file mode 100644 index 000000000000..e1e3cbc8e441 --- /dev/null +++ b/nixos/modules/services/x11/xbanish.nix @@ -0,0 +1,30 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let cfg = config.services.xbanish; + +in { + options.services.xbanish = { + + enable = mkEnableOption "xbanish"; + + arguments = mkOption { + description = "Arguments to pass to xbanish command"; + default = ""; + example = "-d -i shift"; + type = types.str; + }; + }; + + config = mkIf cfg.enable { + systemd.user.services.xbanish = { + description = "xbanish hides the mouse pointer"; + wantedBy = [ "default.target" ]; + serviceConfig.ExecStart = '' + ${pkgs.xbanish}/bin/xbanish ${cfg.arguments} + ''; + serviceConfig.Restart = "always"; + }; + }; +} diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix index 9cb9c8de31d7..35816c3a16dd 100644 --- a/nixos/modules/services/x11/xserver.nix +++ b/nixos/modules/services/x11/xserver.nix @@ -16,6 +16,7 @@ let virtualbox = { modules = [ kernelPackages.virtualboxGuestAdditions ]; driverName = "vboxvideo"; }; ati = { modules = with pkgs.xorg; [ xf86videoati glamoregl ]; }; intel = { modules = with pkgs.xorg; [ xf86videointel glamoregl ]; }; + modesetting = { modules = []; }; }; fontsForXServer = @@ -462,7 +463,14 @@ in { source = "${cfg.xkbDir}"; target = "X11/xkb"; } - ]); + ]) + # Needed since 1.18; see https://bugs.freedesktop.org/show_bug.cgi?id=89023#c5 + ++ (let cfgPath = "/X11/xorg.conf.d/10-evdev.conf"; in + [{ + source = xorg.xf86inputevdev.out + "/share" + cfgPath; + target = cfgPath; + }] + ); environment.systemPackages = [ xorg.xorgserver.out @@ -478,6 +486,7 @@ in xorg.xauth pkgs.xterm pkgs.xdg_utils + xorg.xf86inputevdev.out # get evdev.4 man page ] ++ optional (elem "virtualbox" cfg.videoDrivers) xorg.xrefresh; @@ -519,6 +528,7 @@ in serviceConfig = { Restart = "always"; RestartSec = "200ms"; + SyslogIdentifier = "display-manager"; }; }; @@ -526,16 +536,17 @@ in [ "-terminate" "-config ${configFile}" "-xkbdir" "${cfg.xkbDir}" + # Log at the default verbosity level to stderr rather than /var/log/X.*.log. + "-verbose" "3" "-logfile" "/dev/null" ] ++ optional (cfg.display != null) ":${toString cfg.display}" ++ optional (cfg.tty != null) "vt${toString cfg.tty}" ++ optional (cfg.dpi != null) "-dpi ${toString cfg.dpi}" - ++ optionals (cfg.display != null) [ "-logfile" "/var/log/X.${toString cfg.display}.log" ] ++ optional (!cfg.enableTCP) "-nolisten tcp"; services.xserver.modules = concatLists (catAttrs "modules" cfg.drivers) ++ [ xorg.xorgserver.out - xorg.xf86inputevdev + xorg.xf86inputevdev.out ]; services.xserver.xkbDir = mkDefault "${pkgs.xkeyboard_config}/etc/X11/xkb"; diff --git a/nixos/modules/system/boot/initrd-ssh.nix b/nixos/modules/system/boot/initrd-ssh.nix index a881459bed18..3e2805a8c341 100644 --- a/nixos/modules/system/boot/initrd-ssh.nix +++ b/nixos/modules/system/boot/initrd-ssh.nix @@ -85,6 +85,10 @@ 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"; + } ]; boot.initrd.extraUtilsCommands = '' copy_bin_and_libs ${pkgs.dropbear}/bin/dropbear diff --git a/nixos/modules/system/boot/loader/efi.nix b/nixos/modules/system/boot/loader/efi.nix index 726634e664d7..6043c904c450 100644 --- a/nixos/modules/system/boot/loader/efi.nix +++ b/nixos/modules/system/boot/loader/efi.nix @@ -4,19 +4,16 @@ with lib; { options.boot.loader.efi = { + canTouchEfiVariables = mkOption { default = false; - type = types.bool; - - description = "Whether or not the installation process should modify efi boot variables."; + description = "Whether the installation process is allowed to modify EFI boot variables."; }; efiSysMountPoint = mkOption { default = "/boot"; - type = types.str; - description = "Where the EFI System Partition is mounted."; }; }; diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix index 7fc467b60f7b..0640ec306e18 100644 --- a/nixos/modules/system/boot/loader/grub/grub.nix +++ b/nixos/modules/system/boot/loader/grub/grub.nix @@ -48,12 +48,13 @@ let bootPath = args.path; storePath = config.boot.loader.grub.storePath; bootloaderId = if args.efiBootloaderId == null then "NixOS${efiSysMountPoint'}" else args.efiBootloaderId; + timeout = if config.boot.loader.timeout == null then -1 else config.boot.loader.timeout; inherit efiSysMountPoint; inherit (args) devices; inherit (efi) canTouchEfiVariables; inherit (cfg) version extraConfig extraPerEntryConfig extraEntries - extraEntriesBeforeNixOS extraPrepareConfig configurationLimit copyKernels timeout + extraEntriesBeforeNixOS extraPrepareConfig configurationLimit copyKernels default fsIdentifier efiSupport gfxmodeEfi gfxmodeBios; path = (makeBinPath ([ pkgs.coreutils pkgs.gnused pkgs.gnugrep pkgs.findutils pkgs.diffutils pkgs.btrfs-progs @@ -313,14 +314,6 @@ in ''; }; - timeout = mkOption { - default = if (config.boot.loader.timeout != null) then config.boot.loader.timeout else -1; - type = types.int; - description = '' - Timeout (in seconds) until GRUB boots the default menu item. - ''; - }; - default = mkOption { default = 0; type = types.int; @@ -495,7 +488,7 @@ in } { assertion = if args.efiSysMountPoint == null then true else hasPrefix "/" args.efiSysMountPoint; - message = "Efi paths must be absolute, not ${args.efiSysMountPoint}"; + message = "EFI paths must be absolute, not ${args.efiSysMountPoint}"; } ] ++ flip map args.devices (device: { assertion = device == "nodev" || hasPrefix "/" device; diff --git a/nixos/modules/system/boot/loader/gummiboot/gummiboot-builder.py b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py index ef431a7732e1..c38af1b67f17 100644 --- a/nixos/modules/system/boot/loader/gummiboot/gummiboot-builder.py +++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py @@ -88,16 +88,16 @@ def remove_old_entries(gens): if not path in known_paths: os.unlink(path) -parser = argparse.ArgumentParser(description='Update NixOS-related gummiboot files') +parser = argparse.ArgumentParser(description='Update NixOS-related systemd-boot files') parser.add_argument('default_config', metavar='DEFAULT-CONFIG', help='The default NixOS config to boot') args = parser.parse_args() # We deserve our own env var! if os.getenv("NIXOS_INSTALL_GRUB") == "1": if "@canTouchEfiVariables@" == "1": - subprocess.check_call(["@gummiboot@/bin/gummiboot", "--path=@efiSysMountPoint@", "install"]) + subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "install"]) else: - subprocess.check_call(["@gummiboot@/bin/gummiboot", "--path=@efiSysMountPoint@", "--no-variables", "install"]) + subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "--no-variables", "install"]) mkdir_p("@efiSysMountPoint@/efi/nixos") mkdir_p("@efiSysMountPoint@/loader/entries") diff --git a/nixos/modules/system/boot/loader/gummiboot/gummiboot.nix b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix index 69ad2c6d44f4..a778a4f539c9 100644 --- a/nixos/modules/system/boot/loader/gummiboot/gummiboot.nix +++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix @@ -3,45 +3,38 @@ with lib; let - cfg = config.boot.loader.gummiboot; + cfg = config.boot.loader.systemd-boot; efi = config.boot.loader.efi; gummibootBuilder = pkgs.substituteAll { - src = ./gummiboot-builder.py; + src = ./systemd-boot-builder.py; isExecutable = true; - inherit (pkgs) python gummiboot; + inherit (pkgs) python; + + systemd = config.systemd.package; nix = config.nix.package.out; - timeout = if cfg.timeout != null then cfg.timeout else ""; + timeout = if config.boot.loader.timeout != null then config.boot.loader.timeout else ""; inherit (efi) efiSysMountPoint canTouchEfiVariables; }; in { - options.boot.loader.gummiboot = { + + imports = + [ (mkRenamedOptionModule [ "boot" "loader" "gummiboot" "enable" ] [ "boot" "loader" "systemd-boot" "enable" ]) + ]; + + options.boot.loader.systemd-boot = { enable = mkOption { default = false; type = types.bool; - description = "Whether to enable the gummiboot UEFI boot manager"; - }; - - timeout = mkOption { - default = if config.boot.loader.timeout == null then 10000 else config.boot.loader.timeout; - - example = 4; - - type = types.nullOr types.int; - - description = '' - Timeout (in seconds) for how long to show the menu (null if none). - Note that even with no timeout the menu can be forced if the space - key is pressed during bootup - ''; + description = "Whether to enable the systemd-boot (formerly gummiboot) EFI boot manager"; }; }; @@ -59,7 +52,7 @@ in { system = { build.installBootLoader = gummibootBuilder; - boot.loader.id = "gummiboot"; + boot.loader.id = "systemd-boot"; requiredKernelConfig = with config.lib.kernelConfig; [ (isYes "EFI_STUB") diff --git a/nixos/modules/system/boot/luksroot.nix b/nixos/modules/system/boot/luksroot.nix index 77a82547031a..8dad09c89207 100644 --- a/nixos/modules/system/boot/luksroot.nix +++ b/nixos/modules/system/boot/luksroot.nix @@ -5,7 +5,7 @@ with lib; let luks = config.boot.initrd.luks; - openCommand = { name, device, header, keyFile, keyFileSize, allowDiscards, yubikey, ... }: '' + openCommand = name': { name, device, header, keyFile, keyFileSize, allowDiscards, yubikey, ... }: assert name' == name; '' # Wait for luksRoot to appear, e.g. if on a usb drive. # XXX: copied and adapted from stage-1-init.sh - should be # available as a function. @@ -192,9 +192,8 @@ let ''} ''; - isPreLVM = f: f.preLVM; - preLVM = filter isPreLVM luks.devices; - postLVM = filter (f: !(isPreLVM f)) luks.devices; + preLVM = filterAttrs (n: v: v.preLVM) luks.devices; + postLVM = filterAttrs (n: v: !v.preLVM) luks.devices; in { @@ -228,31 +227,31 @@ in }; boot.initrd.luks.devices = mkOption { - default = [ ]; - example = literalExample ''[ { name = "luksroot"; device = "/dev/sda3"; preLVM = true; } ]''; + default = { }; + example = { "luksroot".device = "/dev/disk/by-uuid/430e9eff-d852-4f68-aa3b-2fa3599ebe08"; }; description = '' - The list of devices that should be decrypted using LUKS before trying to mount the - root partition. This works for both LVM-over-LUKS and LUKS-over-LVM setups. - - The devices are decrypted to the device mapper names defined. - - Make sure that initrd has the crypto modules needed for decryption. + The encrypted disk that should be opened before the root + filesystem is mounted. Both LVM-over-LUKS and LUKS-over-LVM + setups are sypported. The unencrypted devices can be accessed as + <filename>/dev/mapper/<replaceable>name</replaceable></filename>. ''; - type = types.listOf types.optionSet; + type = types.loaOf types.optionSet; - options = { + options = { name, ... }: { options = { name = mkOption { + visible = false; + default = name; example = "luksroot"; type = types.str; - description = "Named to be used for the generated device in /dev/mapper."; + description = "Name of the unencrypted device in <filename>/dev/mapper</filename>."; }; device = mkOption { - example = "/dev/sda2"; + example = "/dev/disk/by-uuid/430e9eff-d852-4f68-aa3b-2fa3599ebe08"; type = types.str; - description = "Path of the underlying block device."; + description = "Path of the underlying encrypted block device."; }; header = mkOption { @@ -289,6 +288,7 @@ in ''; }; + # FIXME: get rid of this option. preLVM = mkOption { default = true; type = types.bool; @@ -394,7 +394,7 @@ in }; }; - }; + }; }; }; boot.initrd.luks.yubikeySupport = mkOption { @@ -408,7 +408,7 @@ in }; }; - config = mkIf (luks.devices != []) { + config = mkIf (luks.devices != {}) { # actually, sbp2 driver is the one enabling the DMA attack, but this needs to be tested boot.blacklistedKernelModules = optionals luks.mitigateDMAAttacks @@ -438,7 +438,7 @@ in copy_bin_and_libs ${pkgs.ykpers}/bin/ykinfo copy_bin_and_libs ${pkgs.openssl.bin}/bin/openssl - cc -O3 -I${pkgs.openssl}/include -L${pkgs.openssl.out}/lib ${./pbkdf2-sha512.c} -o pbkdf2-sha512 -lcrypto + cc -O3 -I${pkgs.openssl.dev}/include -L${pkgs.openssl.out}/lib ${./pbkdf2-sha512.c} -o pbkdf2-sha512 -lcrypto strip -s pbkdf2-sha512 copy_bin_and_libs pbkdf2-sha512 @@ -463,8 +463,8 @@ in ''} ''; - boot.initrd.preLVMCommands = concatMapStrings openCommand preLVM; - boot.initrd.postDeviceCommands = concatMapStrings openCommand postLVM; + boot.initrd.preLVMCommands = concatStrings (mapAttrsToList openCommand preLVM); + boot.initrd.postDeviceCommands = concatStrings (mapAttrsToList openCommand postLVM); environment.systemPackages = [ pkgs.cryptsetup ]; }; diff --git a/nixos/modules/system/boot/stage-2-init.sh b/nixos/modules/system/boot/stage-2-init.sh index 1b5b22c2005a..4a7f073ea8ad 100644 --- a/nixos/modules/system/boot/stage-2-init.sh +++ b/nixos/modules/system/boot/stage-2-init.sh @@ -41,6 +41,8 @@ if [ ! -e /proc/1 ]; then mount -n -t proc proc /proc mkdir -m 0755 -p /dev mount -t devtmpfs devtmpfs /dev + mkdir -m 0755 -p /sys + mount -t sysfs sysfs /sys fi diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index e7f892945315..3d8f29c80f95 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -669,6 +669,7 @@ in "systemd/logind.conf".text = '' [Login] + KillUserProcesses=no ${config.services.logind.extraConfig} ''; @@ -753,13 +754,6 @@ in "TMPFS_XATTR" "SECCOMP" ]; - environment.shellAliases = - { start = "systemctl start"; - stop = "systemctl stop"; - restart = "systemctl restart"; - status = "systemctl status"; - }; - users.extraGroups.systemd-journal.gid = config.ids.gids.systemd-journal; users.extraUsers.systemd-journal-gateway.uid = config.ids.uids.systemd-journal-gateway; users.extraGroups.systemd-journal-gateway.gid = config.ids.gids.systemd-journal-gateway; diff --git a/nixos/modules/tasks/cpu-freq.nix b/nixos/modules/tasks/cpu-freq.nix index 70bbee8474eb..1f4d1db33cef 100644 --- a/nixos/modules/tasks/cpu-freq.nix +++ b/nixos/modules/tasks/cpu-freq.nix @@ -38,7 +38,7 @@ in description = "CPU Frequency Governor Setup"; after = [ "systemd-modules-load.service" ]; wantedBy = [ "multi-user.target" ]; - path = [ cpupower ]; + path = [ cpupower config.system.sbin.modprobe ]; unitConfig.ConditionVirtualization = false; serviceConfig = { Type = "oneshot"; diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix index dd351306cb63..cf8232c36154 100644 --- a/nixos/modules/tasks/filesystems.nix +++ b/nixos/modules/tasks/filesystems.nix @@ -111,15 +111,17 @@ in fileSystems = mkOption { default = {}; - example = { - "/".device = "/dev/hda1"; - "/data" = { - device = "/dev/hda2"; - fsType = "ext3"; - options = [ "data=journal" ]; - }; - "/bigdisk".label = "bigdisk"; - }; + example = literalExample '' + { + "/".device = "/dev/hda1"; + "/data" = { + device = "/dev/hda2"; + fsType = "ext3"; + options = [ "data=journal" ]; + }; + "/bigdisk".label = "bigdisk"; + } + ''; type = types.loaOf types.optionSet; options = [ fileSystemOpts ]; description = '' diff --git a/nixos/modules/testing/test-instrumentation.nix b/nixos/modules/testing/test-instrumentation.nix index f0f56b17f20f..e216351b4347 100644 --- a/nixos/modules/testing/test-instrumentation.nix +++ b/nixos/modules/testing/test-instrumentation.nix @@ -113,6 +113,16 @@ let kernel = config.boot.kernelPackages.kernel; 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; + + # Bump kdm's X server start timeout to account for heavily loaded + # VM host systems. + services.xserver.displayManager.kdm.extraConfig = + '' + [X-:*-Core] + ServerTimeout=240 + ''; + }; } diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix index 5d99bccb0e93..9e8417cde1df 100644 --- a/nixos/modules/virtualisation/amazon-image.nix +++ b/nixos/modules/virtualisation/amazon-image.nix @@ -32,8 +32,8 @@ let cfg = config.ec2; in # Generate a GRUB menu. Amazon's pv-grub uses this to boot our kernel/initrd. boot.loader.grub.version = if cfg.hvm then 2 else 1; boot.loader.grub.device = if cfg.hvm then "/dev/xvda" else "nodev"; - boot.loader.grub.timeout = 0; boot.loader.grub.extraPerEntryConfig = mkIf (!cfg.hvm) "root (hd0)"; + boot.loader.timeout = 0; boot.initrd.postDeviceCommands = '' diff --git a/nixos/modules/virtualisation/azure-common.nix b/nixos/modules/virtualisation/azure-common.nix index eedf115ee150..70a3d752f6d1 100644 --- a/nixos/modules/virtualisation/azure-common.nix +++ b/nixos/modules/virtualisation/azure-common.nix @@ -10,10 +10,10 @@ with lib; boot.kernelParams = [ "console=ttyS0" "earlyprintk=ttyS0" "rootdelay=300" "panic=1" "boot.panic_on_fail" ]; boot.initrd.kernelModules = [ "hv_vmbus" "hv_netvsc" "hv_utils" "hv_storvsc" ]; - # Generate a GRUB menu. + # Generate a GRUB menu. boot.loader.grub.device = "/dev/sda"; boot.loader.grub.version = 2; - boot.loader.grub.timeout = 0; + boot.loader.timeout = 0; # Don't put old configurations in the GRUB menu. The user has no # way to select them anyway. diff --git a/nixos/modules/virtualisation/brightbox-image.nix b/nixos/modules/virtualisation/brightbox-image.nix index bcafc06e47c0..456a19fc2512 100644 --- a/nixos/modules/virtualisation/brightbox-image.nix +++ b/nixos/modules/virtualisation/brightbox-image.nix @@ -94,7 +94,7 @@ in # Generate a GRUB menu. Amazon's pv-grub uses this to boot our kernel/initrd. boot.loader.grub.device = "/dev/vda"; - boot.loader.grub.timeout = 0; + boot.loader.timeout = 0; # Don't put old configurations in the GRUB menu. The user has no # way to select them anyway. diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix index fca21a8610be..13ecb8e25ed5 100644 --- a/nixos/modules/virtualisation/containers.nix +++ b/nixos/modules/virtualisation/containers.nix @@ -309,6 +309,10 @@ in touch "$root/etc/os-release" fi + if ! [ -e "$root/etc/machine-id" ]; then + touch "$root/etc/machine-id" + fi + mkdir -p -m 0755 \ "/nix/var/nix/profiles/per-container/$INSTANCE" \ "/nix/var/nix/gcroots/per-container/$INSTANCE" @@ -338,7 +342,7 @@ in fi ''} - + rm -f $root/var/lib/private/host-notify # Run systemd-nspawn without startup notification (we'll # wait for the container systemd to signal readiness). diff --git a/nixos/modules/virtualisation/docker.nix b/nixos/modules/virtualisation/docker.nix index 97b2927cf1bd..c99fc78d49e7 100644 --- a/nixos/modules/virtualisation/docker.nix +++ b/nixos/modules/virtualisation/docker.nix @@ -95,7 +95,7 @@ in LimitNPROC = 1048576; } // proxy_env; - path = [ pkgs.kmod ] ++ (optional (cfg.storageDriver == "zfs") pkgs.zfs); + path = [ config.system.sbin.modprobe ] ++ (optional (cfg.storageDriver == "zfs") pkgs.zfs); environment.MODULE_DIR = "/run/current-system/kernel-modules/lib/modules"; postStart = if cfg.socketActivation then "" else cfg.postStart; diff --git a/nixos/modules/virtualisation/google-compute-image.nix b/nixos/modules/virtualisation/google-compute-image.nix index 38417315df5b..2b522dbe2660 100644 --- a/nixos/modules/virtualisation/google-compute-image.nix +++ b/nixos/modules/virtualisation/google-compute-image.nix @@ -102,7 +102,7 @@ in # Generate a GRUB menu. Amazon's pv-grub uses this to boot our kernel/initrd. boot.loader.grub.device = "/dev/sda"; - boot.loader.grub.timeout = 0; + boot.loader.timeout = 0; # Don't put old configurations in the GRUB menu. The user has no # way to select them anyway. diff --git a/nixos/modules/virtualisation/lxd.nix b/nixos/modules/virtualisation/lxd.nix index 845f14352f3d..9d76b890872a 100644 --- a/nixos/modules/virtualisation/lxd.nix +++ b/nixos/modules/virtualisation/lxd.nix @@ -47,7 +47,7 @@ in # TODO(wkennington): Add lvm2 and thin-provisioning-tools path = with pkgs; [ acl rsync gnutar xz btrfs-progs ]; - serviceConfig.ExecStart = "@${pkgs.lxd}/bin/lxd lxd --syslog --group lxd"; + serviceConfig.ExecStart = "@${pkgs.lxd.bin}/bin/lxd lxd --syslog --group lxd"; serviceConfig.Type = "simple"; serviceConfig.KillMode = "process"; # when stopping, leave the containers alone }; diff --git a/nixos/modules/virtualisation/nova-image.nix b/nixos/modules/virtualisation/nova-image.nix index 13e36e7888b5..7971212b47c5 100644 --- a/nixos/modules/virtualisation/nova-image.nix +++ b/nixos/modules/virtualisation/nova-image.nix @@ -27,7 +27,7 @@ with lib; boot.kernelParams = [ "console=ttyS0" ]; boot.loader.grub.device = "/dev/vda"; - boot.loader.grub.timeout = 0; + boot.loader.timeout = 0; # Allow root logins services.openssh.enable = true; diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix index 8aa643687557..9d9b725a805d 100644 --- a/nixos/modules/virtualisation/qemu-vm.nix +++ b/nixos/modules/virtualisation/qemu-vm.nix @@ -465,7 +465,7 @@ in }); swapDevices = mkVMOverride [ ]; - boot.initrd.luks.devices = mkVMOverride []; + boot.initrd.luks.devices = mkVMOverride {}; # Don't run ntpd in the guest. It should get the correct time from KVM. services.ntp.enable = false; diff --git a/nixos/modules/virtualisation/virtualbox-guest.nix b/nixos/modules/virtualisation/virtualbox-guest.nix index 3a10871ce840..59bac24a7537 100644 --- a/nixos/modules/virtualisation/virtualbox-guest.nix +++ b/nixos/modules/virtualisation/virtualbox-guest.nix @@ -77,7 +77,7 @@ in KERNEL=="vboxuser", OWNER="root", GROUP="root", MODE="0666" # Allow systemd dependencies on vboxguest. - KERNEL=="vboxguest", TAG+="systemd" + SUBSYSTEM=="misc", KERNEL=="vboxguest", TAG+="systemd" ''; }; diff --git a/nixos/release-combined.nix b/nixos/release-combined.nix index c8c4df5c9138..f275291c716c 100644 --- a/nixos/release-combined.nix +++ b/nixos/release-combined.nix @@ -69,6 +69,7 @@ in rec { (all nixos.tests.boot.uefiUsb) (all nixos.tests.boot-stage1) (all nixos.tests.ipv6) + (all nixos.tests.i3wm) (all nixos.tests.kde4) #(all nixos.tests.lightdm) (all nixos.tests.login) diff --git a/nixos/tests/boot.nix b/nixos/tests/boot.nix index af7db5aa8164..3ea0df65c8b5 100644 --- a/nixos/tests/boot.nix +++ b/nixos/tests/boot.nix @@ -12,7 +12,6 @@ let modules = [ ../modules/installer/cd-dvd/installation-cd-minimal.nix ../modules/testing/test-instrumentation.nix - { key = "serial"; } ]; }).config.system.build.isoImage; @@ -30,20 +29,25 @@ let ''; }; in { + biosCdrom = makeBootTest "bios-cdrom" '' cdrom => glob("${iso}/iso/*.iso") ''; + biosUsb = makeBootTest "bios-usb" '' usb => glob("${iso}/iso/*.iso") ''; + uefiCdrom = makeBootTest "uefi-cdrom" '' cdrom => glob("${iso}/iso/*.iso"), bios => '${pkgs.OVMF}/FV/OVMF.fd' ''; + uefiUsb = makeBootTest "uefi-usb" '' usb => glob("${iso}/iso/*.iso"), bios => '${pkgs.OVMF}/FV/OVMF.fd' ''; + netboot = let config = (import ../lib/eval-config.nix { inherit system; diff --git a/nixos/tests/gnome3_20-gdm.nix b/nixos/tests/gnome3_20-gdm.nix new file mode 100644 index 000000000000..8b1e9afedfb9 --- /dev/null +++ b/nixos/tests/gnome3_20-gdm.nix @@ -0,0 +1,41 @@ +import ./make-test.nix ({ pkgs, ...} : { + name = "gnome3-gdm"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ lethalman ]; + }; + + machine = + { config, pkgs, ... }: + + { imports = [ ./common/user-account.nix ]; + + services.xserver.enable = true; + + services.xserver.displayManager.gdm = { + enable = true; + autoLogin = { + enable = true; + user = "alice"; + }; + }; + services.xserver.desktopManager.gnome3.enable = true; + environment.gnome3.packageSet = pkgs.gnome3_20; + + virtualisation.memorySize = 512; + }; + + testScript = + '' + $machine->waitForX; + $machine->sleep(15); + + # Check that logging in has given the user ownership of devices. + $machine->succeed("getfacl /dev/snd/timer | grep -q alice"); + + $machine->succeed("su - alice -c 'DISPLAY=:0.0 gnome-terminal &'"); + $machine->succeed("xauth merge ~alice/.Xauthority"); + $machine->waitForWindow(qr/Terminal/); + $machine->sleep(20); + $machine->screenshot("screen"); + ''; +}) diff --git a/nixos/tests/gnome3_20.nix b/nixos/tests/gnome3_20.nix new file mode 100644 index 000000000000..51c83a4e3129 --- /dev/null +++ b/nixos/tests/gnome3_20.nix @@ -0,0 +1,38 @@ +import ./make-test.nix ({ pkgs, ...} : { + name = "gnome3"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ domenkozar eelco chaoflow lethalman ]; + }; + + machine = + { config, pkgs, ... }: + + { imports = [ ./common/user-account.nix ]; + + services.xserver.enable = true; + + services.xserver.displayManager.auto.enable = true; + services.xserver.displayManager.auto.user = "alice"; + services.xserver.desktopManager.gnome3.enable = true; + + environment.gnome3.packageSet = pkgs.gnome3_20; + + virtualisation.memorySize = 512; + }; + + testScript = + '' + $machine->waitForX; + $machine->sleep(15); + + # Check that logging in has given the user ownership of devices. + $machine->succeed("getfacl /dev/snd/timer | grep -q alice"); + + $machine->succeed("su - alice -c 'DISPLAY=:0.0 gnome-terminal &'"); + $machine->succeed("xauth merge ~alice/.Xauthority"); + $machine->waitForWindow(qr/Terminal/); + $machine->mustSucceed("timeout 900 bash -c 'journalctl -f|grep -m 1 \"GNOME Shell started\"'"); + $machine->sleep(10); + $machine->screenshot("screen"); + ''; +}) diff --git a/nixos/tests/grsecurity.nix b/nixos/tests/grsecurity.nix index 14f1aa9ff885..aadbfd8371ff 100644 --- a/nixos/tests/grsecurity.nix +++ b/nixos/tests/grsecurity.nix @@ -3,17 +3,39 @@ import ./make-test.nix ({ pkgs, ...} : { name = "grsecurity"; meta = with pkgs.stdenv.lib.maintainers; { - maintainers = [ copumpkin ]; + maintainers = [ copumpkin joachifm ]; }; machine = { config, pkgs, ... }: - { boot.kernelPackages = pkgs.linuxPackages_grsec_testing_server; }; + { security.grsecurity.enable = true; + boot.kernel.sysctl."kernel.grsecurity.deter_bruteforce" = 0; + security.apparmor.enable = true; + }; - testScript = - '' - $machine->succeed("uname -a") =~ /grsec/; - # FIXME: this seems to hang the whole test. Unclear why, but let's fix it - # $machine->succeed("${pkgs.paxtest}/bin/paxtest blackhat"); - ''; -}) + testScript = '' + subtest "grsec-lock", sub { + $machine->succeed("systemctl is-active grsec-lock"); + $machine->succeed("grep -Fq 1 /proc/sys/kernel/grsecurity/grsec_lock"); + $machine->fail("echo -n 0 >/proc/sys/kernel/grsecurity/grsec_lock"); + }; + + subtest "paxtest", sub { + # TODO: running paxtest blackhat hangs the vm + $machine->succeed("${pkgs.paxtest}/lib/paxtest/anonmap") =~ /Killed/ or die; + $machine->succeed("${pkgs.paxtest}/lib/paxtest/execbss") =~ /Killed/ or die; + $machine->succeed("${pkgs.paxtest}/lib/paxtest/execdata") =~ /Killed/ or die; + $machine->succeed("${pkgs.paxtest}/lib/paxtest/execheap") =~ /Killed/ or die; + $machine->succeed("${pkgs.paxtest}/lib/paxtest/execstack") =~ /Killed/ or die; + $machine->succeed("${pkgs.paxtest}/lib/paxtest/mprotanon") =~ /Killed/ or die; + $machine->succeed("${pkgs.paxtest}/lib/paxtest/mprotbss") =~ /Killed/ or die; + $machine->succeed("${pkgs.paxtest}/lib/paxtest/mprotdata") =~ /Killed/ or die; + $machine->succeed("${pkgs.paxtest}/lib/paxtest/mprotheap") =~ /Killed/ or die; + $machine->succeed("${pkgs.paxtest}/lib/paxtest/mprotstack") =~ /Killed/ or die; + }; + subtest "tcc", sub { + $machine->execute("echo -e '#include <stdio.h>\nint main(void) { puts(\"hello\"); return 0; }' >main.c"); + $machine->succeed("${pkgs.tinycc.bin}/bin/tcc -run main.c"); + }; + ''; +}) diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix index 0b0e53ee7324..4a30cc18b021 100644 --- a/nixos/tests/installer.nix +++ b/nixos/tests/installer.nix @@ -30,8 +30,8 @@ let boot.loader.grub.configurationLimit = 100 + ${toString forceGrubReinstallCount}; ''} - ${optionalString (bootLoader == "gummiboot") '' - boot.loader.gummiboot.enable = true; + ${optionalString (bootLoader == "systemd-boot") '' + boot.loader.systemd-boot.enable = true; ''} hardware.enableAllFirmware = lib.mkForce false; @@ -57,7 +57,7 @@ let (if system == "x86_64-linux" then "-m 768 " else "-m 512 ") + (optionalString (system == "x86_64-linux") "-cpu kvm64 "); hdFlags = ''hda => "vm-state-machine/machine.qcow2", hdaInterface => "${iface}", '' - + optionalString (bootLoader == "gummiboot") ''bios => "${pkgs.OVMF}/FV/OVMF.fd", ''; + + optionalString (bootLoader == "systemd-boot") ''bios => "${pkgs.OVMF}/FV/OVMF.fd", ''; in '' $machine->start; @@ -159,7 +159,7 @@ let makeInstallerTest = name: { createPartitions, preBootCommands ? "", extraConfig ? "" - , bootLoader ? "grub" # either "grub" or "gummiboot" + , bootLoader ? "grub" # either "grub" or "systemd-boot" , grubVersion ? 2, grubDevice ? "/dev/vda", grubIdentifier ? "uuid" , enableOCR ? false, meta ? {} }: @@ -195,7 +195,7 @@ let virtualisation.qemu.diskInterface = if grubVersion == 1 then "scsi" else "virtio"; - boot.loader.gummiboot.enable = mkIf (bootLoader == "gummiboot") true; + boot.loader.systemd-boot.enable = mkIf (bootLoader == "systemd-boot") true; hardware.enableAllFirmware = mkForce false; @@ -208,7 +208,6 @@ let pkgs.unionfs-fuse pkgs.ntp pkgs.nixos-artwork - pkgs.gummiboot pkgs.perlPackages.XMLLibXML pkgs.perlPackages.ListCompare ] @@ -250,7 +249,7 @@ in { ''; }; - # Simple GPT/UEFI configuration using Gummiboot with 3 partitions: ESP, swap & root filesystem + # Simple GPT/UEFI configuration using systemd-boot with 3 partitions: ESP, swap & root filesystem simpleUefiGummiboot = makeInstallerTest "simpleUefiGummiboot" { createPartitions = '' @@ -270,7 +269,7 @@ in { "mount LABEL=BOOT /mnt/boot", ); ''; - bootLoader = "gummiboot"; + bootLoader = "systemd-boot"; }; # Same as the previous, but now with a separate /boot partition. @@ -360,14 +359,8 @@ in { "mount LABEL=boot /mnt/boot", ); ''; - # XXX: Currently, generate-config doesn't detect LUKS yet. extraConfig = '' boot.kernelParams = lib.mkAfter [ "console=tty0" ]; - boot.initrd.luks.devices = lib.singleton { - name = "cryptroot"; - device = "/dev/vda3"; - preLVM = true; - }; ''; enableOCR = true; preBootCommands = '' @@ -403,8 +396,6 @@ in { "mkdir /mnt/boot", "mount LABEL=boot /mnt/boot", "udevadm settle", - "mdadm --verbose -W /dev/md0", # wait for sync to finish; booting off an unsynced device tends to fail - "mdadm --verbose -W /dev/md1", ); ''; preBootCommands = '' diff --git a/nixos/tests/sddm-kde5.nix b/nixos/tests/sddm-kde5.nix index f97a6d12b63c..0247d267aaa4 100644 --- a/nixos/tests/sddm-kde5.nix +++ b/nixos/tests/sddm-kde5.nix @@ -1,4 +1,6 @@ -import ./make-test.nix ({ pkgs, ...} : { +import ./make-test.nix ({ pkgs, ...} : + +{ name = "sddm"; meta = with pkgs.stdenv.lib.maintainers; { maintainers = [ ttuegel ]; @@ -6,6 +8,7 @@ import ./make-test.nix ({ pkgs, ...} : { machine = { lib, ... }: { imports = [ ./common/user-account.nix ]; + virtualisation.memorySize = 1024; services.xserver.enable = true; services.xserver.displayManager.sddm = { enable = true; @@ -14,18 +17,38 @@ import ./make-test.nix ({ pkgs, ...} : { user = "alice"; }; }; - services.xserver.windowManager.default = "icewm"; - services.xserver.windowManager.icewm.enable = true; - services.xserver.desktopManager.default = "none"; services.xserver.desktopManager.kde5.enable = true; }; enableOCR = true; - testScript = { nodes, ... }: '' - startAll; - $machine->waitForFile("/home/alice/.Xauthority"); - $machine->succeed("xauth merge ~alice/.Xauthority"); - $machine->waitForWindow("^IceWM "); + testScript = { nodes, ... }: + let xdo = "${pkgs.xdotool}/bin/xdotool"; in + '' + sub krunner { + my ($win,) = @_; + $machine->execute("${xdo} key Alt+F2 sleep 1 type $win"); + $machine->execute("${xdo} search --sync --onlyvisible --class krunner sleep 5 key Return"); + } + + $machine->waitUntilSucceeds("pgrep plasmashell"); + $machine->succeed("xauth merge ~alice/.Xauthority"); + $machine->waitForWindow(qr/Desktop.*/); + + # Check that logging in has given the user ownership of devices. + $machine->succeed("getfacl /dev/snd/timer | grep -q alice"); + + krunner("dolphin"); + $machine->waitForWindow(qr/.*Dolphin/); + + krunner("konsole"); + $machine->waitForWindow(qr/.*Konsole/); + + krunner("systemsettings5"); + $machine->waitForWindow(qr/.*Settings/); + $machine->sleep(20); + + $machine->execute("${xdo} key Alt+F1 sleep 10"); + $machine->screenshot("screen"); ''; }) diff --git a/nixos/tests/virtualbox.nix b/nixos/tests/virtualbox.nix index da4c0bddc348..e9bc14a6cdb4 100644 --- a/nixos/tests/virtualbox.nix +++ b/nixos/tests/virtualbox.nix @@ -11,7 +11,7 @@ let #!${pkgs.stdenv.shell} -xe export PATH="${pkgs.coreutils}/bin:${pkgs.utillinux}/bin" - mkdir -p /etc/dbus-1 /var/run/dbus + mkdir -p /var/run/dbus cat > /etc/passwd <<EOF root:x:0:0::/root:/bin/false messagebus:x:1:1::/var/run/dbus:/bin/false @@ -20,9 +20,9 @@ let root:x:0: messagebus:x:1: EOF - cp -v "${pkgs.dbus.daemon}/etc/dbus-1/system.conf" \ - /etc/dbus-1/system.conf - "${pkgs.dbus.daemon}/bin/dbus-daemon" --fork --system + + "${pkgs.dbus.daemon}/bin/dbus-daemon" --fork \ + --config-file="${pkgs.dbus.daemon}/share/dbus-1/system.conf" ${guestAdditions}/bin/VBoxService ${(attrs.vmScript or (const "")) pkgs} @@ -326,6 +326,7 @@ let in [ ./common/user-account.nix ./common/x11.nix ] ++ vmConfigs; virtualisation.memorySize = 2048; virtualisation.virtualbox.host.enable = true; + services.xserver.displayManager.auto.user = "alice"; users.extraUsers.alice.extraGroups = let inherit (config.virtualisation.virtualbox.host) enableHardening; in lib.mkIf enableHardening (lib.singleton "vboxusers"); @@ -363,7 +364,9 @@ in mapAttrs mkVBoxTest { simple-gui = '' createVM_simple; $machine->succeed(ru "VirtualBox &"); - $machine->waitForWindow(qr/Oracle VM VirtualBox Manager/); + $machine->waitUntilSucceeds( + ru "xprop -name 'Oracle VM VirtualBox Manager'" + ); $machine->sleep(5); $machine->screenshot("gui_manager_started"); $machine->sendKeys("ret"); |