diff options
Diffstat (limited to 'nixos')
53 files changed, 1396 insertions, 779 deletions
diff --git a/nixos/doc/manual/configuration/config-syntax.chapter.md b/nixos/doc/manual/configuration/config-syntax.chapter.md index 56d093c0f6e84..9f8d45d588997 100644 --- a/nixos/doc/manual/configuration/config-syntax.chapter.md +++ b/nixos/doc/manual/configuration/config-syntax.chapter.md @@ -15,5 +15,4 @@ NixOS configuration files. <xi:include href="config-file.section.xml" /> <xi:include href="abstractions.section.xml" /> <xi:include href="modularity.section.xml" /> -<xi:include href="summary.section.xml" /> ``` diff --git a/nixos/doc/manual/configuration/summary.section.md b/nixos/doc/manual/configuration/summary.section.md deleted file mode 100644 index 8abbbe257fd90..0000000000000 --- a/nixos/doc/manual/configuration/summary.section.md +++ /dev/null @@ -1,46 +0,0 @@ -# Syntax Summary {#sec-nix-syntax-summary} - -Below is a summary of the most important syntactic constructs in the Nix -expression language. It's not complete. In particular, there are many -other built-in functions. See the [Nix -manual](https://nixos.org/nix/manual/#chap-writing-nix-expressions) for -the rest. - -| Example | Description | -|-----------------------------------------------|--------------------------------------------------------------------------------------------------------------------| -| *Basic values* | | -| `"Hello world"` | A string | -| `"${pkgs.bash}/bin/sh"` | A string containing an expression (expands to `"/nix/store/hash-bash-version/bin/sh"`) | -| `true`, `false` | Booleans | -| `123` | An integer | -| `./foo.png` | A path (relative to the containing Nix expression) | -| *Compound values* | | -| `{ x = 1; y = 2; }` | A set with attributes named `x` and `y` | -| `{ foo.bar = 1; }` | A nested set, equivalent to `{ foo = { bar = 1; }; }` | -| `rec { x = "foo"; y = x + "bar"; }` | A recursive set, equivalent to `{ x = "foo"; y = "foobar"; }` | -| `[ "foo" "bar" ]` | A list with two elements | -| *Operators* | | -| `"foo" + "bar"` | String concatenation | -| `1 + 2` | Integer addition | -| `"foo" == "f" + "oo"` | Equality test (evaluates to `true`) | -| `"foo" != "bar"` | Inequality test (evaluates to `true`) | -| `!true` | Boolean negation | -| `{ x = 1; y = 2; }.x` | Attribute selection (evaluates to `1`) | -| `{ x = 1; y = 2; }.z or 3` | Attribute selection with default (evaluates to `3`) | -| `{ x = 1; y = 2; } // { z = 3; }` | Merge two sets (attributes in the right-hand set taking precedence) | -| *Control structures* | | -| `if 1 + 1 == 2 then "yes!" else "no!"` | Conditional expression | -| `assert 1 + 1 == 2; "yes!"` | Assertion check (evaluates to `"yes!"`). See [](#sec-assertions) for using assertions in modules | -| `let x = "foo"; y = "bar"; in x + y` | Variable definition | -| `with pkgs.lib; head [ 1 2 3 ]` | Add all attributes from the given set to the scope (evaluates to `1`) | -| *Functions (lambdas)* | | -| `x: x + 1` | A function that expects an integer and returns it increased by 1 | -| `(x: x + 1) 100` | A function call (evaluates to 101) | -| `let inc = x: x + 1; in inc (inc (inc 100))` | A function bound to a variable and subsequently called by name (evaluates to 103) | -| `{ x, y }: x + y` | A function that expects a set with required attributes `x` and `y` and concatenates them | -| `{ x, y ? "bar" }: x + y` | A function that expects a set with required attribute `x` and optional `y`, using `"bar"` as default value for `y` | -| `{ x, y, ... }: x + y` | A function that expects a set with required attributes `x` and `y` and ignores any other attributes | -| `{ x, y } @ args: x + y` | A function that expects a set with required attributes `x` and `y`, and binds the whole set to `args` | -| *Built-in functions* | | -| `import ./foo.nix` | Load and return Nix expression in given file | -| `map (x: x + x) [ 1 2 3 ]` | Apply a function to every element of a list (evaluates to `[ 2 4 6 ]`) | diff --git a/nixos/doc/manual/configuration/user-mgmt.chapter.md b/nixos/doc/manual/configuration/user-mgmt.chapter.md index 37990664a8f1b..5c3aca3ef9e95 100644 --- a/nixos/doc/manual/configuration/user-mgmt.chapter.md +++ b/nixos/doc/manual/configuration/user-mgmt.chapter.md @@ -32,8 +32,7 @@ account will cease to exist. Also, imperative commands for managing users and groups, such as useradd, are no longer available. Passwords may still be assigned by setting the user\'s [hashedPassword](#opt-users.users._name_.hashedPassword) option. A -hashed password can be generated using `mkpasswd -m - sha-512`. +hashed password can be generated using `mkpasswd`. A user ID (uid) is assigned automatically. You can also specify a uid manually by adding diff --git a/nixos/doc/manual/from_md/configuration/config-syntax.chapter.xml b/nixos/doc/manual/from_md/configuration/config-syntax.chapter.xml index 01446e53e38ff..baf9639554cc2 100644 --- a/nixos/doc/manual/from_md/configuration/config-syntax.chapter.xml +++ b/nixos/doc/manual/from_md/configuration/config-syntax.chapter.xml @@ -17,5 +17,4 @@ <xi:include href="config-file.section.xml" /> <xi:include href="abstractions.section.xml" /> <xi:include href="modularity.section.xml" /> - <xi:include href="summary.section.xml" /> </chapter> diff --git a/nixos/doc/manual/from_md/configuration/summary.section.xml b/nixos/doc/manual/from_md/configuration/summary.section.xml deleted file mode 100644 index 96a178c4930ed..0000000000000 --- a/nixos/doc/manual/from_md/configuration/summary.section.xml +++ /dev/null @@ -1,332 +0,0 @@ -<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-nix-syntax-summary"> - <title>Syntax Summary</title> - <para> - Below is a summary of the most important syntactic constructs in the - Nix expression language. It’s not complete. In particular, there are - many other built-in functions. See the - <link xlink:href="https://nixos.org/nix/manual/#chap-writing-nix-expressions">Nix - manual</link> for the rest. - </para> - <informaltable> - <tgroup cols="2"> - <colspec align="left" /> - <colspec align="left" /> - <thead> - <row> - <entry> - Example - </entry> - <entry> - Description - </entry> - </row> - </thead> - <tbody> - <row> - <entry> - <emphasis>Basic values</emphasis> - </entry> - <entry> - </entry> - </row> - <row> - <entry> - <literal>"Hello world"</literal> - </entry> - <entry> - A string - </entry> - </row> - <row> - <entry> - <literal>"${pkgs.bash}/bin/sh"</literal> - </entry> - <entry> - A string containing an expression (expands to - <literal>"/nix/store/hash-bash-version/bin/sh"</literal>) - </entry> - </row> - <row> - <entry> - <literal>true</literal>, <literal>false</literal> - </entry> - <entry> - Booleans - </entry> - </row> - <row> - <entry> - <literal>123</literal> - </entry> - <entry> - An integer - </entry> - </row> - <row> - <entry> - <literal>./foo.png</literal> - </entry> - <entry> - A path (relative to the containing Nix expression) - </entry> - </row> - <row> - <entry> - <emphasis>Compound values</emphasis> - </entry> - <entry> - </entry> - </row> - <row> - <entry> - <literal>{ x = 1; y = 2; }</literal> - </entry> - <entry> - A set with attributes named <literal>x</literal> and - <literal>y</literal> - </entry> - </row> - <row> - <entry> - <literal>{ foo.bar = 1; }</literal> - </entry> - <entry> - A nested set, equivalent to - <literal>{ foo = { bar = 1; }; }</literal> - </entry> - </row> - <row> - <entry> - <literal>rec { x = "foo"; y = x + "bar"; }</literal> - </entry> - <entry> - A recursive set, equivalent to - <literal>{ x = "foo"; y = "foobar"; }</literal> - </entry> - </row> - <row> - <entry> - <literal>[ "foo" "bar" ]</literal> - </entry> - <entry> - A list with two elements - </entry> - </row> - <row> - <entry> - <emphasis>Operators</emphasis> - </entry> - <entry> - </entry> - </row> - <row> - <entry> - <literal>"foo" + "bar"</literal> - </entry> - <entry> - String concatenation - </entry> - </row> - <row> - <entry> - <literal>1 + 2</literal> - </entry> - <entry> - Integer addition - </entry> - </row> - <row> - <entry> - <literal>"foo" == "f" + "oo"</literal> - </entry> - <entry> - Equality test (evaluates to <literal>true</literal>) - </entry> - </row> - <row> - <entry> - <literal>"foo" != "bar"</literal> - </entry> - <entry> - Inequality test (evaluates to <literal>true</literal>) - </entry> - </row> - <row> - <entry> - <literal>!true</literal> - </entry> - <entry> - Boolean negation - </entry> - </row> - <row> - <entry> - <literal>{ x = 1; y = 2; }.x</literal> - </entry> - <entry> - Attribute selection (evaluates to <literal>1</literal>) - </entry> - </row> - <row> - <entry> - <literal>{ x = 1; y = 2; }.z or 3</literal> - </entry> - <entry> - Attribute selection with default (evaluates to - <literal>3</literal>) - </entry> - </row> - <row> - <entry> - <literal>{ x = 1; y = 2; } // { z = 3; }</literal> - </entry> - <entry> - Merge two sets (attributes in the right-hand set taking - precedence) - </entry> - </row> - <row> - <entry> - <emphasis>Control structures</emphasis> - </entry> - <entry> - </entry> - </row> - <row> - <entry> - <literal>if 1 + 1 == 2 then "yes!" else "no!"</literal> - </entry> - <entry> - Conditional expression - </entry> - </row> - <row> - <entry> - <literal>assert 1 + 1 == 2; "yes!"</literal> - </entry> - <entry> - Assertion check (evaluates to - <literal>"yes!"</literal>). See - <xref linkend="sec-assertions" /> for using assertions in - modules - </entry> - </row> - <row> - <entry> - <literal>let x = "foo"; y = "bar"; in x + y</literal> - </entry> - <entry> - Variable definition - </entry> - </row> - <row> - <entry> - <literal>with pkgs.lib; head [ 1 2 3 ]</literal> - </entry> - <entry> - Add all attributes from the given set to the scope - (evaluates to <literal>1</literal>) - </entry> - </row> - <row> - <entry> - <emphasis>Functions (lambdas)</emphasis> - </entry> - <entry> - </entry> - </row> - <row> - <entry> - <literal>x: x + 1</literal> - </entry> - <entry> - A function that expects an integer and returns it increased - by 1 - </entry> - </row> - <row> - <entry> - <literal>(x: x + 1) 100</literal> - </entry> - <entry> - A function call (evaluates to 101) - </entry> - </row> - <row> - <entry> - <literal>let inc = x: x + 1; in inc (inc (inc 100))</literal> - </entry> - <entry> - A function bound to a variable and subsequently called by - name (evaluates to 103) - </entry> - </row> - <row> - <entry> - <literal>{ x, y }: x + y</literal> - </entry> - <entry> - A function that expects a set with required attributes - <literal>x</literal> and <literal>y</literal> and - concatenates them - </entry> - </row> - <row> - <entry> - <literal>{ x, y ? "bar" }: x + y</literal> - </entry> - <entry> - A function that expects a set with required attribute - <literal>x</literal> and optional <literal>y</literal>, - using <literal>"bar"</literal> as default value - for <literal>y</literal> - </entry> - </row> - <row> - <entry> - <literal>{ x, y, ... }: x + y</literal> - </entry> - <entry> - A function that expects a set with required attributes - <literal>x</literal> and <literal>y</literal> and ignores - any other attributes - </entry> - </row> - <row> - <entry> - <literal>{ x, y } @ args: x + y</literal> - </entry> - <entry> - A function that expects a set with required attributes - <literal>x</literal> and <literal>y</literal>, and binds the - whole set to <literal>args</literal> - </entry> - </row> - <row> - <entry> - <emphasis>Built-in functions</emphasis> - </entry> - <entry> - </entry> - </row> - <row> - <entry> - <literal>import ./foo.nix</literal> - </entry> - <entry> - Load and return Nix expression in given file - </entry> - </row> - <row> - <entry> - <literal>map (x: x + x) [ 1 2 3 ]</literal> - </entry> - <entry> - Apply a function to every element of a list (evaluates to - <literal>[ 2 4 6 ]</literal>) - </entry> - </row> - </tbody> - </tgroup> - </informaltable> -</section> diff --git a/nixos/doc/manual/from_md/configuration/user-mgmt.chapter.xml b/nixos/doc/manual/from_md/configuration/user-mgmt.chapter.xml index 06492d5c25126..a2d7d2a9f1154 100644 --- a/nixos/doc/manual/from_md/configuration/user-mgmt.chapter.xml +++ b/nixos/doc/manual/from_md/configuration/user-mgmt.chapter.xml @@ -39,7 +39,7 @@ users.users.alice = { Passwords may still be assigned by setting the user's <link linkend="opt-users.users._name_.hashedPassword">hashedPassword</link> option. A hashed password can be generated using - <literal>mkpasswd -m sha-512</literal>. + <literal>mkpasswd</literal>. </para> <para> A user ID (uid) is assigned automatically. You can also specify a diff --git a/nixos/doc/manual/from_md/installation/installing.chapter.xml b/nixos/doc/manual/from_md/installation/installing.chapter.xml index 02a0f14b984ac..f2ed58c0c1fe5 100644 --- a/nixos/doc/manual/from_md/installation/installing.chapter.xml +++ b/nixos/doc/manual/from_md/installation/installing.chapter.xml @@ -455,8 +455,8 @@ OK <listitem> <para> Finally, add a <emphasis>swap</emphasis> partition. The - size required will vary according to needs, here a 8GiB - one is created. + size required will vary according to needs, here a 8GB one + is created. </para> <programlisting> # parted /dev/sda -- mkpart primary linux-swap -8GB 100% @@ -814,8 +814,8 @@ $ passwd eelco </para> <programlisting> # parted /dev/sda -- mklabel msdos -# parted /dev/sda -- mkpart primary 1MiB -8GiB -# parted /dev/sda -- mkpart primary linux-swap -8GiB 100% +# parted /dev/sda -- mkpart primary 1MB -8GB +# parted /dev/sda -- mkpart primary linux-swap -8GB 100% </programlisting> <anchor xml:id="ex-partition-scheme-UEFI" /> <para> @@ -824,9 +824,9 @@ $ passwd eelco </para> <programlisting> # parted /dev/sda -- mklabel gpt -# parted /dev/sda -- mkpart primary 512MiB -8GiB -# parted /dev/sda -- mkpart primary linux-swap -8GiB 100% -# parted /dev/sda -- mkpart ESP fat32 1MiB 512MiB +# parted /dev/sda -- mkpart primary 512MB -8GB +# parted /dev/sda -- mkpart primary linux-swap -8GB 100% +# parted /dev/sda -- mkpart ESP fat32 1MB 512MB # parted /dev/sda -- set 3 esp on </programlisting> <anchor xml:id="ex-install-sequence" /> diff --git a/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml index 20f8933da38f3..8e97e58f81a61 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2211.section.xml @@ -141,6 +141,11 @@ </listitem> <listitem> <para> + PHP 8.2.0 RC 6 is available. + </para> + </listitem> + <listitem> + <para> <literal>protonup</literal> has been aliased to and replaced by <literal>protonup-ng</literal> due to upstream not maintaining it. @@ -626,6 +631,23 @@ </listitem> <listitem> <para> + The <literal>openssl</literal>-extension for the PHP + interpreter used by Nextcloud is built against OpenSSL 1.1 if + <xref linkend="opt-system.stateVersion" /> is below + <literal>22.11</literal>. This is to make sure that people + using + <link xlink:href="https://docs.nextcloud.com/server/latest/admin_manual/configuration_files/encryption_configuration.html">server-side + encryption</link> don’t loose access to their files. + </para> + <para> + In any other case it’s safe to use OpenSSL 3 for PHP’s openssl + extension. This can be done by setting + <xref linkend="opt-services.nextcloud.enableBrokenCiphersForSSE" /> + to <literal>false</literal>. + </para> + </listitem> + <listitem> + <para> The <literal>coq</literal> package and versioned variants starting at <literal>coq_8_14</literal> no longer include CoqIDE, which is now available through @@ -1051,6 +1073,17 @@ services.github-runner.serviceOverrides.SupplementaryGroups = [ <itemizedlist> <listitem> <para> + <literal>firefox</literal>, <literal>thunderbird</literal> and + <literal>librewolf</literal> come with enabled Wayland support + by default. The <literal>firefox-wayland</literal>, + <literal>firefox-esr-wayland</literal>, + <literal>thunderbird-wayland</literal> and + <literal>librewolf-wayland</literal> attributes are obsolete + and have been aliased to their generic attribute. + </para> + </listitem> + <listitem> + <para> The <literal>xplr</literal> package has been updated from 0.18.0 to 0.19.0, which brings some breaking changes. See the <link xlink:href="https://github.com/sayanarijit/xplr/releases/tag/v0.19.0">upstream @@ -1173,22 +1206,146 @@ services.github-runner.serviceOverrides.SupplementaryGroups = [ </listitem> <listitem> <para> - The <literal>services.grafana</literal> options were converted - to a + The module <literal>services.grafana</literal> was refactored + to be compliant with <link xlink:href="https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md">RFC - 0042</link> configuration. - </para> - </listitem> - <listitem> - <para> - The <literal>services.grafana.provision.datasources</literal> - and <literal>services.grafana.provision.dashboards</literal> - options were converted to a - <link xlink:href="https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md">RFC - 0042</link> configuration. They also now support specifying - the provisioning YAML file with <literal>path</literal> - option. + 0042</link>. To be precise, this means that the following + things have changed: </para> + <itemizedlist> + <listitem> + <para> + The newly introduced option + <xref linkend="opt-services.grafana.settings" /> is an + attribute-set that will be converted into Grafana’s INI + format. This means that the configuration from + <link xlink:href="https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/">Grafana’s + configuration reference</link> can be directly written as + attribute-set in Nix within this option. + </para> + </listitem> + <listitem> + <para> + The option + <literal>services.grafana.extraOptions</literal> has been + removed. This option was an association of environment + variables for Grafana. If you had an expression like + </para> + <programlisting language="bash"> +{ + services.grafana.extraOptions.SECURITY_ADMIN_USER = "foobar"; +} +</programlisting> + <para> + your Grafana instance was running with + <literal>GF_SECURITY_ADMIN_USER=foobar</literal> in its + environment. + </para> + <para> + For the migration, it is recommended to turn it into the + INI format, i.e. to declare + </para> + <programlisting language="bash"> +{ + services.grafana.settings.security.admin_user = "foobar"; +} +</programlisting> + <para> + instead. + </para> + <para> + The keys in + <literal>services.grafana.extraOptions</literal> have the + format + <literal><INI section name>_<Key Name></literal>. + Further details are outlined in the + <link xlink:href="https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#override-configuration-with-environment-variables">configuration + reference</link>. + </para> + <para> + Alternatively you can also set all your values from + <literal>extraOptions</literal> to + <literal>systemd.services.grafana.environment</literal>, + make sure you don’t forget to add the + <literal>GF_</literal> prefix though! + </para> + </listitem> + <listitem> + <para> + Previously, the options + <xref linkend="opt-services.grafana.provision.datasources" /> + and + <xref linkend="opt-services.grafana.provision.dashboards" /> + expected lists of datasources or dashboards for the + <link xlink:href="https://grafana.com/docs/grafana/latest/administration/provisioning/">declarative + provisioning</link>. + </para> + <para> + To declare lists of + </para> + <itemizedlist spacing="compact"> + <listitem> + <para> + <emphasis role="strong">datasources</emphasis>, please + rename your declarations to + <xref linkend="opt-services.grafana.provision.datasources.settings.datasources" />. + </para> + </listitem> + <listitem> + <para> + <emphasis role="strong">dashboards</emphasis>, please + rename your declarations to + <xref linkend="opt-services.grafana.provision.dashboards.settings.providers" />. + </para> + </listitem> + </itemizedlist> + <para> + This change was made to support more features for that: + </para> + <itemizedlist> + <listitem> + <para> + It’s possible to declare the + <literal>apiVersion</literal> of your dashboards and + datasources by + <xref linkend="opt-services.grafana.provision.datasources.settings.apiVersion" /> + (or + <xref linkend="opt-services.grafana.provision.dashboards.settings.apiVersion" />). + </para> + </listitem> + <listitem> + <para> + Instead of declaring datasources and dashboards in + pure Nix, it’s also possible to specify configuration + files (or directories) with YAML instead using + <xref linkend="opt-services.grafana.provision.datasources.path" /> + (or + <xref linkend="opt-services.grafana.provision.dashboards.path" />. + This is useful when having provisioning files from + non-NixOS Grafana instances that you also want to + deploy to NixOS. + </para> + <para> + <emphasis role="strong">Note:</emphasis> secrets from + these files will be leaked into the store unless you + use a + <link xlink:href="https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#file-provider"><emphasis role="strong">file</emphasis>-provider + or env-var</link> for secrets! + </para> + </listitem> + <listitem> + <para> + <xref linkend="opt-services.grafana.provision.notifiers" /> + is not affected by this change because this feature is + deprecated by Grafana and will probably removed in + Grafana 10. It’s recommended to use + <literal>services.grafana.provision.alerting.contactPoints</literal> + instead. + </para> + </listitem> + </itemizedlist> + </listitem> + </itemizedlist> </listitem> <listitem> <para> @@ -1428,6 +1585,16 @@ services.github-runner.serviceOverrides.SupplementaryGroups = [ </listitem> <listitem> <para> + The Mastodon package got upgraded from the major version 3 to + 4. See the + <link xlink:href="https://github.com/mastodon/mastodon/releases/tag/v4.0.0">v4.0.0 + release notes</link> for a list of changes. On standard + setups, no manual migration steps are required. Nevertheless, + a database backup is recommended. + </para> + </listitem> + <listitem> + <para> The <literal>nomad</literal> package now defaults to 1.3, which no longer has a downgrade path to releases 1.2 or older. </para> diff --git a/nixos/doc/manual/installation/installing.chapter.md b/nixos/doc/manual/installation/installing.chapter.md index 44e7e29421d65..2c86cb923a5c1 100644 --- a/nixos/doc/manual/installation/installing.chapter.md +++ b/nixos/doc/manual/installation/installing.chapter.md @@ -307,7 +307,7 @@ update /etc/fstab. ``` 4. Finally, add a *swap* partition. The size required will vary - according to needs, here a 8GiB one is created. + according to needs, here a 8GB one is created. ```ShellSession # parted /dev/sda -- mkpart primary linux-swap -8GB 100% @@ -543,8 +543,8 @@ corresponding configuration Nix expression. ::: ```ShellSession # parted /dev/sda -- mklabel msdos -# parted /dev/sda -- mkpart primary 1MiB -8GiB -# parted /dev/sda -- mkpart primary linux-swap -8GiB 100% +# parted /dev/sda -- mkpart primary 1MB -8GB +# parted /dev/sda -- mkpart primary linux-swap -8GB 100% ``` ::: @@ -554,9 +554,9 @@ corresponding configuration Nix expression. ::: ```ShellSession # parted /dev/sda -- mklabel gpt -# parted /dev/sda -- mkpart primary 512MiB -8GiB -# parted /dev/sda -- mkpart primary linux-swap -8GiB 100% -# parted /dev/sda -- mkpart ESP fat32 1MiB 512MiB +# parted /dev/sda -- mkpart primary 512MB -8GB +# parted /dev/sda -- mkpart primary linux-swap -8GB 100% +# parted /dev/sda -- mkpart ESP fat32 1MB 512MB # parted /dev/sda -- set 3 esp on ``` ::: diff --git a/nixos/doc/manual/release-notes/rl-2211.section.md b/nixos/doc/manual/release-notes/rl-2211.section.md index d21acb57fa1dc..ecfba7215c8b2 100644 --- a/nixos/doc/manual/release-notes/rl-2211.section.md +++ b/nixos/doc/manual/release-notes/rl-2211.section.md @@ -57,6 +57,8 @@ In addition to numerous new and upgraded packages, this release has the followin `mod_php` usage we still enable `ZTS` (Zend Thread Safe). This has been a common practice for a long time in other distributions. +- PHP 8.2.0 RC 6 is available. + - `protonup` has been aliased to and replaced by `protonup-ng` due to upstream not maintaining it. - Perl has been updated to 5.36, and its core module `HTTP::Tiny` was patched to verify SSL/TLS certificates by default. @@ -202,6 +204,13 @@ Available as [services.patroni](options.html#opt-services.patroni.enable). - The `p4` package now only includes the open-source Perforce Helix Core command-line client and APIs. It no longer installs the unfree Helix Core Server binaries `p4d`, `p4broker`, and `p4p`. To install the Helix Core Server binaries, use the `p4d` package instead. +- The `openssl`-extension for the PHP interpreter used by Nextcloud is built against OpenSSL 1.1 if + [](#opt-system.stateVersion) is below `22.11`. This is to make sure that people using [server-side encryption](https://docs.nextcloud.com/server/latest/admin_manual/configuration_files/encryption_configuration.html) + don't loose access to their files. + + In any other case it's safe to use OpenSSL 3 for PHP's openssl extension. This can be done by setting + [](#opt-services.nextcloud.enableBrokenCiphersForSSE) to `false`. + - The `coq` package and versioned variants starting at `coq_8_14` no longer include CoqIDE, which is now available through `coqPackages.coqide`. It is still possible to get CoqIDE as part of @@ -332,6 +341,8 @@ Available as [services.patroni](options.html#opt-services.patroni.enable). ## Other Notable Changes {#sec-release-22.11-notable-changes} +- `firefox`, `thunderbird` and `librewolf` come with enabled Wayland support by default. The `firefox-wayland`, `firefox-esr-wayland`, `thunderbird-wayland` and `librewolf-wayland` attributes are obsolete and have been aliased to their generic attribute. + - The `xplr` package has been updated from 0.18.0 to 0.19.0, which brings some breaking changes. See the [upstream release notes](https://github.com/sayanarijit/xplr/releases/tag/v0.19.0) for more details. - Configuring multiple GitHub runners is now possible through `services.github-runners.<name>`. The option `services.github-runner` remains. @@ -368,9 +379,66 @@ Available as [services.patroni](options.html#opt-services.patroni.enable). - The `services.matrix-synapse` systemd unit has been hardened. -- The `services.grafana` options were converted to a [RFC 0042](https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md) configuration. +- The module `services.grafana` was refactored to be compliant with [RFC 0042](https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md). To be precise, this means that the following things have changed: + - The newly introduced option [](#opt-services.grafana.settings) is an attribute-set that + will be converted into Grafana's INI format. This means that the configuration from + [Grafana's configuration reference](https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/) + can be directly written as attribute-set in Nix within this option. + - The option `services.grafana.extraOptions` has been removed. This option was an association + of environment variables for Grafana. If you had an expression like + + ```nix + { + services.grafana.extraOptions.SECURITY_ADMIN_USER = "foobar"; + } + ``` + + your Grafana instance was running with `GF_SECURITY_ADMIN_USER=foobar` in its environment. + + For the migration, it is recommended to turn it into the INI format, i.e. + to declare + + ```nix + { + services.grafana.settings.security.admin_user = "foobar"; + } + ``` + + instead. -- The `services.grafana.provision.datasources` and `services.grafana.provision.dashboards` options were converted to a [RFC 0042](https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md) configuration. They also now support specifying the provisioning YAML file with `path` option. + The keys in `services.grafana.extraOptions` have the format `<INI section name>_<Key Name>`. + Further details are outlined in the [configuration reference](https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#override-configuration-with-environment-variables). + + Alternatively you can also set all your values from `extraOptions` to + `systemd.services.grafana.environment`, make sure you don't forget to add + the `GF_` prefix though! + - Previously, the options [](#opt-services.grafana.provision.datasources) and + [](#opt-services.grafana.provision.dashboards) expected lists of datasources + or dashboards for the [declarative provisioning](https://grafana.com/docs/grafana/latest/administration/provisioning/). + + To declare lists of + - **datasources**, please rename your declarations to [](#opt-services.grafana.provision.datasources.settings.datasources). + - **dashboards**, please rename your declarations to [](#opt-services.grafana.provision.dashboards.settings.providers). + + This change was made to support more features for that: + + - It's possible to declare the `apiVersion` of your dashboards and datasources + by [](#opt-services.grafana.provision.datasources.settings.apiVersion) (or + [](#opt-services.grafana.provision.dashboards.settings.apiVersion)). + + - Instead of declaring datasources and dashboards in pure Nix, it's also possible + to specify configuration files (or directories) with YAML instead using + [](#opt-services.grafana.provision.datasources.path) (or + [](#opt-services.grafana.provision.dashboards.path). This is useful when having + provisioning files from non-NixOS Grafana instances that you also want to + deploy to NixOS. + + __Note:__ secrets from these files will be leaked into the store unless you use a + [**file**-provider or env-var](https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#file-provider) for secrets! + + - [](#opt-services.grafana.provision.notifiers) is not affected by this change because + this feature is deprecated by Grafana and will probably removed in Grafana 10. + It's recommended to use `services.grafana.provision.alerting.contactPoints` instead. - The `services.grafana.provision.alerting` option was added. It includes suboptions for every alerting-related objects (with the exception of `notifiers`), which means it's now possible to configure modern Grafana alerting declaratively. @@ -439,6 +507,8 @@ Available as [services.patroni](options.html#opt-services.patroni.enable). - There is a new module for the `xfconf` program (the Xfce configuration storage system), which has a dbus service. +- The Mastodon package got upgraded from the major version 3 to 4. See the [v4.0.0 release notes](https://github.com/mastodon/mastodon/releases/tag/v4.0.0) for a list of changes. On standard setups, no manual migration steps are required. Nevertheless, a database backup is recommended. + - The `nomad` package now defaults to 1.3, which no longer has a downgrade path to releases 1.2 or older. - The `nodePackages` package set now defaults to the LTS release in the `nodejs` package again, instead of being pinned to `nodejs-14_x`. Several updates to node2nix have been made for compatibility with newer Node.js and npm versions and a new `postRebuild` hook has been added for packages to perform extra build steps before the npm install step prunes dev dependencies. diff --git a/nixos/lib/test-driver/test_driver/machine.py b/nixos/lib/test-driver/test_driver/machine.py index e45c83086fb52..ffbc7c18e42b6 100644 --- a/nixos/lib/test-driver/test_driver/machine.py +++ b/nixos/lib/test-driver/test_driver/machine.py @@ -684,10 +684,10 @@ class Machine: with self.nested("waiting for {} to appear on tty {}".format(regexp, tty)): retry(tty_matches) - def send_chars(self, chars: str) -> None: + def send_chars(self, chars: str, delay: Optional[float] = 0.01) -> None: with self.nested("sending keys ‘{}‘".format(chars)): for char in chars: - self.send_key(char) + self.send_key(char, delay) def wait_for_file(self, filename: str) -> None: """Waits until the file exists in machine's file system.""" @@ -860,10 +860,11 @@ class Machine: if matches is not None: return - def send_key(self, key: str) -> None: + def send_key(self, key: str, delay: Optional[float] = 0.01) -> None: key = CHAR_TO_KEY.get(key, key) self.send_monitor_command("sendkey {}".format(key)) - time.sleep(0.01) + if delay is not None: + time.sleep(delay) def send_console(self, chars: str) -> None: assert self.process diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix index b538a0119c06d..2660b0e6c9388 100644 --- a/nixos/modules/config/users-groups.nix +++ b/nixos/modules/config/users-groups.nix @@ -35,7 +35,7 @@ let ''; hashedPasswordDescription = '' - To generate a hashed password run `mkpasswd -m sha-512`. + To generate a hashed password run `mkpasswd`. If set to an empty string (`""`), this user will be able to log in without being asked for a password (but not via remote @@ -592,6 +592,26 @@ in { ''; }; + # Warn about user accounts with deprecated password hashing schemes + system.activationScripts.hashes = { + deps = [ "users" ]; + text = '' + users=() + while IFS=: read -r user hash tail; do + if [[ "$hash" = "$"* && ! "$hash" =~ ^\$(y|gy|7|2b|2y|2a|6)\$ ]]; then + users+=("$user") + fi + done </etc/shadow + + if (( "''${#users[@]}" )); then + echo " + WARNING: The following user accounts rely on password hashes that will + be removed in NixOS 23.05. They should be renewed as soon as possible." + printf ' - %s\n' "''${users[@]}" + fi + ''; + }; + # for backwards compatibility system.activationScripts.groups = stringAfter [ "users" ] ""; diff --git a/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares.nix b/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares.nix index 288cbc94a321b..3f3571d253825 100644 --- a/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares.nix +++ b/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares.nix @@ -14,8 +14,6 @@ in calamares-nixos calamares-nixos-autostart calamares-nixos-extensions - # Needed for calamares QML module packagechooserq - libsForQt5.full # Get list of locales glibcLocales ]; diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index a886332e90b70..2a23a32eaba6e 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -382,6 +382,7 @@ ./services/databases/pgmanage.nix ./services/databases/postgresql.nix ./services/databases/redis.nix + ./services/databases/surrealdb.nix ./services/databases/victoriametrics.nix ./services/desktops/accountsservice.nix ./services/desktops/bamf.nix @@ -718,6 +719,7 @@ ./services/monitoring/teamviewer.nix ./services/monitoring/telegraf.nix ./services/monitoring/thanos.nix + ./services/monitoring/tremor-rs.nix ./services/monitoring/tuptime.nix ./services/monitoring/unifi-poller.nix ./services/monitoring/ups.nix diff --git a/nixos/modules/programs/steam.nix b/nixos/modules/programs/steam.nix index adbbf5d9ed4b4..1b69aac98863b 100644 --- a/nixos/modules/programs/steam.nix +++ b/nixos/modules/programs/steam.nix @@ -4,17 +4,31 @@ with lib; let cfg = config.programs.steam; - - steam = pkgs.steam.override { - extraLibraries = pkgs: with config.hardware.opengl; - if pkgs.hostPlatform.is64bit - then [ package ] ++ extraPackages - else [ package32 ] ++ extraPackages32; - }; in { options.programs.steam = { enable = mkEnableOption (lib.mdDoc "steam"); + package = mkOption { + type = types.package; + default = pkgs.steam.override { + extraLibraries = pkgs: with config.hardware.opengl; + if pkgs.hostPlatform.is64bit + then [ package ] ++ extraPackages + else [ package32 ] ++ extraPackages32; + }; + defaultText = literalExpression '' + pkgs.steam.override { + extraLibraries = pkgs: with config.hardware.opengl; + if pkgs.hostPlatform.is64bit + then [ package ] ++ extraPackages + else [ package32 ] ++ extraPackages32; + } + ''; + description = lib.mdDoc '' + steam package to use. + ''; + }; + remotePlay.openFirewall = mkOption { type = types.bool; default = false; @@ -44,7 +58,10 @@ in { hardware.steam-hardware.enable = true; - environment.systemPackages = [ steam steam.run ]; + environment.systemPackages = [ + cfg.package + cfg.package.run + ]; networking.firewall = lib.mkMerge [ (mkIf cfg.remotePlay.openFirewall { diff --git a/nixos/modules/services/databases/surrealdb.nix b/nixos/modules/services/databases/surrealdb.nix new file mode 100644 index 0000000000000..27269eb02f64e --- /dev/null +++ b/nixos/modules/services/databases/surrealdb.nix @@ -0,0 +1,79 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + + cfg = config.services.surrealdb; +in { + + options = { + services.surrealdb = { + enable = mkEnableOption (lib.mdDoc "A scalable, distributed, collaborative, document-graph database, for the realtime web "); + + dbPath = mkOption { + type = types.str; + description = lib.mdDoc '' + The path that surrealdb will write data to. Use null for in-memory. + Can be one of "memory", "file://:path", "tikv://:addr". + ''; + default = "file:///var/lib/surrealdb/"; + example = "memory"; + }; + + host = mkOption { + type = types.str; + description = lib.mdDoc '' + The host that surrealdb will connect to. + ''; + default = "127.0.0.1"; + example = "127.0.0.1"; + }; + + port = mkOption { + type = types.port; + description = lib.mdDoc '' + The port that surrealdb will connect to. + ''; + default = 8000; + example = 8000; + }; + }; + }; + + config = mkIf cfg.enable { + + # Used to connect to the running service + environment.systemPackages = [ pkgs.surrealdb ] ; + + systemd.services.surrealdb = { + description = "A scalable, distributed, collaborative, document-graph database, for the realtime web "; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + serviceConfig = { + ExecStart = "${pkgs.surrealdb}/bin/surreal start --bind ${cfg.host}:${toString cfg.port} ${optionalString (cfg.dbPath != null) "-- ${cfg.dbPath}"}"; + DynamicUser = true; + Restart = "on-failure"; + StateDirectory = "surrealdb"; + CapabilityBoundingSet = ""; + NoNewPrivileges = true; + PrivateTmp = true; + ProtectHome = true; + ProtectClock = true; + ProtectProc = "noaccess"; + ProcSubset = "pid"; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectControlGroups = true; + ProtectHostname = true; + RestrictSUIDSGID = true; + RestrictRealtime = true; + RestrictNamespaces = true; + LockPersonality = true; + RemoveIPC = true; + SystemCallFilter = [ "@system-service" "~@privileged" ]; + }; + }; + }; +} diff --git a/nixos/modules/services/desktops/gnome/at-spi2-core.nix b/nixos/modules/services/desktops/gnome/at-spi2-core.nix index 495ea5af9879d..10a2f1f9eca0d 100644 --- a/nixos/modules/services/desktops/gnome/at-spi2-core.nix +++ b/nixos/modules/services/desktops/gnome/at-spi2-core.nix @@ -51,7 +51,10 @@ with lib; }) (mkIf (!config.services.gnome.at-spi2-core.enable) { - environment.variables.NO_AT_BRIDGE = "1"; + environment.variables = { + NO_AT_BRIDGE = "1"; + GTK_A11Y = "none"; + }; }) ]; } diff --git a/nixos/modules/services/hardware/udev.nix b/nixos/modules/services/hardware/udev.nix index 7a7f8330243a2..d95261332419d 100644 --- a/nixos/modules/services/hardware/udev.nix +++ b/nixos/modules/services/hardware/udev.nix @@ -46,6 +46,11 @@ let SUBSYSTEM=="input", KERNEL=="mice", TAG+="systemd" ''; + nixosInitrdRules = '' + # Mark dm devices as db_persist so that they are kept active after switching root + SUBSYSTEM=="block", KERNEL=="dm-[0-9]*", ACTION=="add|change", OPTIONS+="db_persist" + ''; + # Perform substitutions in all udev rules files. udevRulesFor = { name, udevPackages, udevPath, udev, systemd, binPackages, initrdBin ? null }: pkgs.runCommand name { preferLocalBuild = true; @@ -364,8 +369,10 @@ in EOF ''; + boot.initrd.services.udev.rules = nixosInitrdRules; + boot.initrd.systemd.additionalUpstreamUnits = [ - # TODO: "initrd-udevadm-cleanup-db.service" is commented out because of https://github.com/systemd/systemd/issues/12953 + "initrd-udevadm-cleanup-db.service" "systemd-udevd-control.socket" "systemd-udevd-kernel.socket" "systemd-udevd.service" diff --git a/nixos/modules/services/matrix/mautrix-telegram.nix b/nixos/modules/services/matrix/mautrix-telegram.nix index fc8b95051ddbe..2d9c2dc76c29b 100644 --- a/nixos/modules/services/matrix/mautrix-telegram.nix +++ b/nixos/modules/services/matrix/mautrix-telegram.nix @@ -7,8 +7,8 @@ let registrationFile = "${dataDir}/telegram-registration.yaml"; cfg = config.services.mautrix-telegram; settingsFormat = pkgs.formats.json {}; - settingsFileUnsubstituted = settingsFormat.generate "mautrix-telegram-config-unsubstituted.json" cfg.settings; - settingsFile = "${dataDir}/config.json"; + settingsFile = + settingsFormat.generate "mautrix-telegram-config.json" cfg.settings; in { options = { @@ -97,12 +97,23 @@ in { default = null; description = lib.mdDoc '' File containing environment variables to be passed to the mautrix-telegram service, - in which secret tokens can be specified securely by defining values for + in which secret tokens can be specified securely by defining values for e.g. `MAUTRIX_TELEGRAM_APPSERVICE_AS_TOKEN`, `MAUTRIX_TELEGRAM_APPSERVICE_HS_TOKEN`, `MAUTRIX_TELEGRAM_TELEGRAM_API_ID`, `MAUTRIX_TELEGRAM_TELEGRAM_API_HASH` and optionally `MAUTRIX_TELEGRAM_TELEGRAM_BOT_TOKEN`. + + These environment variables can also be used to set other options by + replacing hierachy levels by `.`, converting the name to uppercase + and prepending `MAUTRIX_TELEGRAM_`. + For example, the first value above maps to + {option}`settings.appservice.as_token`. + + The environment variable values can be prefixed with `json::` to have + them be parsed as JSON. For example, `login_shared_secret_map` can be + set as follows: + `MAUTRIX_TELEGRAM_BRIDGE_LOGIN_SHARED_SECRET_MAP=json::{"example.com":"secret"}`. ''; }; @@ -141,16 +152,6 @@ in { environment.HOME = dataDir; preStart = '' - # Not all secrets can be passed as environment variable (yet) - # https://github.com/tulir/mautrix-telegram/issues/584 - [ -f ${settingsFile} ] && rm -f ${settingsFile} - old_umask=$(umask) - umask 0177 - ${pkgs.envsubst}/bin/envsubst \ - -o ${settingsFile} \ - -i ${settingsFileUnsubstituted} - umask $old_umask - # generate the appservice's registration file if absent if [ ! -f '${registrationFile}' ]; then ${pkgs.mautrix-telegram}/bin/mautrix-telegram \ @@ -186,8 +187,6 @@ in { --config='${settingsFile}' ''; }; - - restartTriggers = [ settingsFileUnsubstituted ]; }; }; diff --git a/nixos/modules/services/monitoring/grafana.nix b/nixos/modules/services/monitoring/grafana.nix index 52d5cab9f5159..9b3068796d8e3 100644 --- a/nixos/modules/services/monitoring/grafana.nix +++ b/nixos/modules/services/monitoring/grafana.nix @@ -13,57 +13,96 @@ let settingsFormatIni = pkgs.formats.ini {}; configFile = settingsFormatIni.generate "config.ini" cfg.settings; - datasourceConfiguration = { - apiVersion = 1; - datasources = cfg.provision.datasources; - }; - - datasourceFileNew = if (cfg.provision.datasources.path == null) then provisioningSettingsFormat.generate "datasource.yaml" cfg.provision.datasources.settings else cfg.provision.datasources.path; - datasourceFile = if (builtins.isList cfg.provision.datasources) then provisioningSettingsFormat.generate "datasource.yaml" datasourceConfiguration else datasourceFileNew; - - dashboardConfiguration = { - apiVersion = 1; - providers = cfg.provision.dashboards; - }; - - dashboardFileNew = if (cfg.provision.dashboards.path == null) then provisioningSettingsFormat.generate "dashboard.yaml" cfg.provision.dashboards.settings else cfg.provision.dashboards.path; - dashboardFile = if (builtins.isList cfg.provision.dashboards) then provisioningSettingsFormat.generate "dashboard.yaml" dashboardConfiguration else dashboardFileNew; + mkProvisionCfg = name: attr: provisionCfg: + if provisionCfg.path != null + then provisionCfg.path + else + provisioningSettingsFormat.generate "${name}.yaml" + (if provisionCfg.settings != null + then provisionCfg.settings + else { + apiVersion = 1; + ${attr} = []; + }); + + datasourceFileOrDir = mkProvisionCfg "datasource" "datasources" cfg.provision.datasources; + dashboardFileOrDir = mkProvisionCfg "dashboard" "providers" cfg.provision.dashboards; notifierConfiguration = { apiVersion = 1; notifiers = cfg.provision.notifiers; }; - notifierFile = pkgs.writeText "notifier.yaml" (builtins.toJSON notifierConfiguration); + notifierFileOrDir = pkgs.writeText "notifier.yaml" (builtins.toJSON notifierConfiguration); generateAlertingProvisioningYaml = x: if (cfg.provision.alerting."${x}".path == null) then provisioningSettingsFormat.generate "${x}.yaml" cfg.provision.alerting."${x}".settings else cfg.provision.alerting."${x}".path; - rulesFile = generateAlertingProvisioningYaml "rules"; - contactPointsFile = generateAlertingProvisioningYaml "contactPoints"; - policiesFile = generateAlertingProvisioningYaml "policies"; - templatesFile = generateAlertingProvisioningYaml "templates"; - muteTimingsFile = generateAlertingProvisioningYaml "muteTimings"; - - provisionConfDir = pkgs.runCommand "grafana-provisioning" { } '' + rulesFileOrDir = generateAlertingProvisioningYaml "rules"; + contactPointsFileOrDir = generateAlertingProvisioningYaml "contactPoints"; + policiesFileOrDir = generateAlertingProvisioningYaml "policies"; + templatesFileOrDir = generateAlertingProvisioningYaml "templates"; + muteTimingsFileOrDir = generateAlertingProvisioningYaml "muteTimings"; + + ln = { src, dir, filename }: '' + if [[ -d "${src}" ]]; then + pushd $out/${dir} &>/dev/null + lndir "${src}" + popd &>/dev/null + else + ln -sf ${src} $out/${dir}/${filename}.yaml + fi + ''; + provisionConfDir = pkgs.runCommand "grafana-provisioning" { nativeBuildInputs = [ pkgs.xorg.lndir ]; } '' mkdir -p $out/{datasources,dashboards,notifiers,alerting} - ln -sf ${datasourceFile} $out/datasources/datasource.yaml - ln -sf ${dashboardFile} $out/dashboards/dashboard.yaml - ln -sf ${notifierFile} $out/notifiers/notifier.yaml - ln -sf ${rulesFile} $out/alerting/rules.yaml - ln -sf ${contactPointsFile} $out/alerting/contactPoints.yaml - ln -sf ${policiesFile} $out/alerting/policies.yaml - ln -sf ${templatesFile} $out/alerting/templates.yaml - ln -sf ${muteTimingsFile} $out/alerting/muteTimings.yaml + ${ln { src = datasourceFileOrDir; dir = "datasources"; filename = "datasource"; }} + ${ln { src = dashboardFileOrDir; dir = "dashboards"; filename = "dashbaord"; }} + ${ln { src = notifierFileOrDir; dir = "notifiers"; filename = "notifier"; }} + ${ln { src = rulesFileOrDir; dir = "alerting"; filename = "rules"; }} + ${ln { src = contactPointsFileOrDir; dir = "alerting"; filename = "contactPoints"; }} + ${ln { src = policiesFileOrDir; dir = "alerting"; filename = "policies"; }} + ${ln { src = templatesFileOrDir; dir = "alerting"; filename = "templates"; }} + ${ln { src = muteTimingsFileOrDir; dir = "alerting"; filename = "muteTimings"; }} ''; # Get a submodule without any embedded metadata: _filter = x: filterAttrs (k: v: k != "_module") x; + # FIXME(@Ma27) remove before 23.05. This is just a helper-type + # because `mkRenamedOptionModule` doesn't work if `foo.bar` is renamed + # to `foo.bar.baz`. + submodule' = module: types.coercedTo + (mkOptionType { + name = "grafana-provision-submodule"; + description = "Wrapper-type for backwards compat of Grafana's declarative provisioning"; + check = x: + if builtins.isList x then + throw '' + Provisioning dashboards and datasources declaratively by + setting `dashboards` or `datasources` to a list is not supported + anymore. Use `services.grafana.provision.datasources.settings.datasources` + (or `services.grafana.provision.dashboards.settings.providers`) instead. + '' + else isAttrs x || isFunction x; + }) + id + (types.submodule module); + # http://docs.grafana.org/administration/provisioning/#datasources grafanaTypes.datasourceConfig = types.submodule { freeformType = provisioningSettingsFormat.type; + imports = [ + (mkRemovedOptionModule [ "password" ] '' + `services.grafana.provision.datasources.settings.datasources.<name>.password` has been removed + in Grafana 9. Use `secureJsonData` instead. + '') + (mkRemovedOptionModule [ "basicAuthPassword" ] '' + `services.grafana.provision.datasources.settings.datasources.<name>.basicAuthPassword` has been removed + in Grafana 9. Use `secureJsonData` instead. + '') + ]; + options = { name = mkOption { type = types.str; @@ -93,28 +132,6 @@ let default = false; description = lib.mdDoc "Allow users to edit datasources from the UI."; }; - password = mkOption { - type = types.nullOr types.str; - default = null; - description = lib.mdDoc '' - Database password, if used. Please note that the contents of this option - will end up in a world-readable Nix store. Use the file provider - pointing at a reasonably secured file in the local filesystem - to work around that. Look at the documentation for details: - <https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#file-provider> - ''; - }; - basicAuthPassword = mkOption { - type = types.nullOr types.str; - default = null; - description = lib.mdDoc '' - Basic auth password. Please note that the contents of this option - will end up in a world-readable Nix store. Use the file provider - pointing at a reasonably secured file in the local filesystem - to work around that. Look at the documentation for details: - <https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#file-provider> - ''; - }; secureJsonData = mkOption { type = types.nullOr types.attrs; default = null; @@ -276,6 +293,10 @@ in { (mkRemovedOptionModule [ "services" "grafana" "auth" "google" "clientSecretFile" ] '' This option has been removed. Use 'services.grafana.settings.google.client_secret' with file provider instead. '') + (mkRemovedOptionModule [ "services" "grafana" "extraOptions" ] '' + This option has been removed. Use 'services.grafana.settings' instead. For a detailed migration guide, please + review the release notes of NixOS 22.11. + '') (mkRemovedOptionModule [ "services" "grafana" "auth" "azuread" "tenantId" ] "This option has been deprecated upstream.") ]; @@ -330,19 +351,7 @@ in { Don't change the value of this option if you are planning to use `services.grafana.provision` options. ''; default = provisionConfDir; - defaultText = literalExpression '' - pkgs.runCommand "grafana-provisioning" { } \'\' - mkdir -p $out/{datasources,dashboards,notifiers,alerting} - ln -sf ''${datasourceFile} $out/datasources/datasource.yaml - ln -sf ''${dashboardFile} $out/dashboards/dashboard.yaml - ln -sf ''${notifierFile} $out/notifiers/notifier.yaml - ln -sf ''${rulesFile} $out/alerting/rules.yaml - ln -sf ''${contactPointsFile} $out/alerting/contactPoints.yaml - ln -sf ''${policiesFile} $out/alerting/policies.yaml - ln -sf ''${templatesFile} $out/alerting/templates.yaml - ln -sf ''${muteTimingsFile} $out/alerting/muteTimings.yaml - \'\' - ''; + defaultText = "directory with links to files generated from services.grafana.provision"; type = types.path; }; }; @@ -564,17 +573,14 @@ in { datasources = mkOption { description = lib.mdDoc '' - Deprecated option for Grafana datasource configuration. Use either - `services.grafana.provision.datasources.settings` or - `services.grafana.provision.datasources.path` instead. + Declaratively provision Grafana's datasources. ''; - default = []; - apply = x: if (builtins.isList x) then map _filter x else x; - type = with types; either (listOf grafanaTypes.datasourceConfig) (submodule { + default = {}; + type = submodule' { options.settings = mkOption { description = lib.mdDoc '' Grafana datasource configuration in Nix. Can't be used with - `services.grafana.provision.datasources.path` simultaneously. See + [](#opt-services.grafana.provision.datasources.path) simultaneously. See <https://grafana.com/docs/grafana/latest/administration/provisioning/#data-sources> for supported options. ''; @@ -591,6 +597,7 @@ in { description = lib.mdDoc "List of datasources to insert/update."; default = []; type = types.listOf grafanaTypes.datasourceConfig; + apply = map (flip builtins.removeAttrs [ "password" "basicAuthPassword" ]); }; deleteDatasources = mkOption { @@ -630,28 +637,26 @@ in { options.path = mkOption { description = lib.mdDoc '' Path to YAML datasource configuration. Can't be used with - `services.grafana.provision.datasources.settings` simultaneously. + [](#opt-services.grafana.provision.datasources.settings) simultaneously. + Can be either a directory or a single YAML file. Will end up in the store. ''; default = null; type = types.nullOr types.path; }; - }); + }; }; dashboards = mkOption { description = lib.mdDoc '' - Deprecated option for Grafana dashboard configuration. Use either - `services.grafana.provision.dashboards.settings` or - `services.grafana.provision.dashboards.path` instead. + Declaratively provision Grafana's dashboards. ''; - default = []; - apply = x: if (builtins.isList x) then map _filter x else x; - type = with types; either (listOf grafanaTypes.dashboardConfig) (submodule { + default = {}; + type = submodule' { options.settings = mkOption { description = lib.mdDoc '' Grafana dashboard configuration in Nix. Can't be used with - `services.grafana.provision.dashboards.path` simultaneously. See + [](#opt-services.grafana.provision.dashboards.path) simultaneously. See <https://grafana.com/docs/grafana/latest/administration/provisioning/#dashboards> for supported options. ''; @@ -684,12 +689,13 @@ in { options.path = mkOption { description = lib.mdDoc '' Path to YAML dashboard configuration. Can't be used with - `services.grafana.provision.dashboards.settings` simultaneously. + [](#opt-services.grafana.provision.dashboards.settings) simultaneously. + Can be either a directory or a single YAML file. Will end up in the store. ''; default = null; type = types.nullOr types.path; }; - }); + }; }; @@ -706,7 +712,8 @@ in { path = mkOption { description = lib.mdDoc '' Path to YAML rules configuration. Can't be used with - `services.grafana.provision.alerting.rules.settings` simultaneously. + [](#opt-services.grafana.provision.alerting.rules.settings) simultaneously. + Can be either a directory or a single YAML file. Will end up in the store. ''; default = null; type = types.nullOr types.path; @@ -715,7 +722,7 @@ in { settings = mkOption { description = lib.mdDoc '' Grafana rules configuration in Nix. Can't be used with - `services.grafana.provision.alerting.rules.path` simultaneously. See + [](#opt-services.grafana.provision.alerting.rules.path) simultaneously. See <https://grafana.com/docs/grafana/latest/administration/provisioning/#rules> for supported options. ''; @@ -829,7 +836,8 @@ in { path = mkOption { description = lib.mdDoc '' Path to YAML contact points configuration. Can't be used with - `services.grafana.provision.alerting.contactPoints.settings` simultaneously. + [](#opt-services.grafana.provision.alerting.contactPoints.settings) simultaneously. + Can be either a directory or a single YAML file. Will end up in the store. ''; default = null; type = types.nullOr types.path; @@ -838,7 +846,7 @@ in { settings = mkOption { description = lib.mdDoc '' Grafana contact points configuration in Nix. Can't be used with - `services.grafana.provision.alerting.contactPoints.path` simultaneously. See + [](#opt-services.grafana.provision.alerting.contactPoints.path) simultaneously. See <https://grafana.com/docs/grafana/latest/administration/provisioning/#contact-points> for supported options. ''; @@ -852,7 +860,7 @@ in { }; contactPoints = mkOption { - description = lib.mdDoc "List of contact points to import or update. Please note that sensitive data will end up in world-readable Nix store."; + description = lib.mdDoc "List of contact points to import or update."; default = []; type = types.listOf (types.submodule { freeformType = provisioningSettingsFormat.type; @@ -909,7 +917,8 @@ in { path = mkOption { description = lib.mdDoc '' Path to YAML notification policies configuration. Can't be used with - `services.grafana.provision.alerting.policies.settings` simultaneously. + [](#opt-services.grafana.provision.alerting.policies.settings) simultaneously. + Can be either a directory or a single YAML file. Will end up in the store. ''; default = null; type = types.nullOr types.path; @@ -918,7 +927,7 @@ in { settings = mkOption { description = lib.mdDoc '' Grafana notification policies configuration in Nix. Can't be used with - `services.grafana.provision.alerting.policies.path` simultaneously. See + [](#opt-services.grafana.provision.alerting.policies.path) simultaneously. See <https://grafana.com/docs/grafana/latest/administration/provisioning/#notification-policies> for supported options. ''; @@ -978,7 +987,8 @@ in { path = mkOption { description = lib.mdDoc '' Path to YAML templates configuration. Can't be used with - `services.grafana.provision.alerting.templates.settings` simultaneously. + [](#opt-services.grafana.provision.alerting.templates.settings) simultaneously. + Can be either a directory or a single YAML file. Will end up in the store. ''; default = null; type = types.nullOr types.path; @@ -987,7 +997,7 @@ in { settings = mkOption { description = lib.mdDoc '' Grafana templates configuration in Nix. Can't be used with - `services.grafana.provision.alerting.templates.path` simultaneously. See + [](#opt-services.grafana.provision.alerting.templates.path) simultaneously. See <https://grafana.com/docs/grafana/latest/administration/provisioning/#templates> for supported options. ''; @@ -1059,7 +1069,8 @@ in { path = mkOption { description = lib.mdDoc '' Path to YAML mute timings configuration. Can't be used with - `services.grafana.provision.alerting.muteTimings.settings` simultaneously. + [](#opt-services.grafana.provision.alerting.muteTimings.settings) simultaneously. + Can be either a directory or a single YAML file. Will end up in the store. ''; default = null; type = types.nullOr types.path; @@ -1068,7 +1079,7 @@ in { settings = mkOption { description = lib.mdDoc '' Grafana mute timings configuration in Nix. Can't be used with - `services.grafana.provision.alerting.muteTimings.path` simultaneously. See + [](#opt-services.grafana.provision.alerting.muteTimings.path) simultaneously. See <https://grafana.com/docs/grafana/latest/administration/provisioning/#mute-timings> for supported options. ''; @@ -1159,52 +1170,50 @@ in { config = mkIf cfg.enable { warnings = let - usesFileProvider = opt: defaultValue: builtins.match "^${defaultValue}$|^\\$__file\\{.*}$" opt != null; - in flatten [ - (optional ( - ! usesFileProvider cfg.settings.database.password "" || - ! usesFileProvider cfg.settings.security.admin_password "admin" - ) "Grafana passwords will be stored as plaintext in the Nix store! Use file provider instead.") - (optional ( + doesntUseFileProvider = opt: defaultValue: let - checkOpts = opt: any (x: x.password != null || x.basicAuthPassword != null || x.secureJsonData != null) opt; - datasourcesUsed = if (cfg.provision.datasources.settings == null) then [] else cfg.provision.datasources.settings.datasources; - in if (builtins.isList cfg.provision.datasources) then checkOpts cfg.provision.datasources else checkOpts datasourcesUsed - ) '' - Datasource passwords will be stored as plaintext in the Nix store! - It is not possible to use file provider in provisioning; please provision - datasources via `services.grafana.provision.datasources.path` instead. - '') - (optional ( - any (x: x.secure_settings != null) cfg.provision.notifiers - ) "Notifier secure settings will be stored as plaintext in the Nix store! Use file provider instead.") + regex = "${optionalString (defaultValue != null) "^${defaultValue}$|"}^\\$__(file|env)\\{.*}$|^\\$[^_\\$][^ ]+$"; + in builtins.match regex opt == null; + in + # Ensure that no custom credentials are leaked into the Nix store. Unless the default value + # is specified, this can be achieved by using the file/env provider: + # https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#variable-expansion (optional ( - builtins.isList cfg.provision.datasources && cfg.provision.datasources != [] + doesntUseFileProvider cfg.settings.database.password "" || + doesntUseFileProvider cfg.settings.security.admin_password "admin" ) '' - Provisioning Grafana datasources with options has been deprecated. - Use `services.grafana.provision.datasources.settings` or - `services.grafana.provision.datasources.path` instead. - '') - (optional ( - builtins.isList cfg.provision.datasources && cfg.provision.dashboards != [] + Grafana passwords will be stored as plaintext in the Nix store! + Use file provider or an env-var instead. + '') + # Warn about deprecated notifiers. + ++ (optional (cfg.provision.notifiers != []) '' + Notifiers are deprecated upstream and will be removed in Grafana 10. + Use `services.grafana.provision.alerting.contactPoints` instead. + '') + # Ensure that `secureJsonData` of datasources provisioned via `datasources.settings` + # only uses file/env providers. + ++ (optional ( + let + datasourcesToCheck = optionals + (cfg.provision.datasources.settings != null) + cfg.provision.datasources.settings.datasources; + declarationUnsafe = { secureJsonData, ... }: + secureJsonData != null + && any (flip doesntUseFileProvider null) (attrValues secureJsonData); + in any declarationUnsafe datasourcesToCheck ) '' - Provisioning Grafana dashboards with options has been deprecated. - Use `services.grafana.provision.dashboards.settings` or - `services.grafana.provision.dashboards.path` instead. - '') - (optional ( - cfg.provision.notifiers != [] - ) '' - Notifiers are deprecated upstream and will be removed in Grafana 10. - Use `services.grafana.provision.alerting.contactPoints` instead. - '') - ]; + Declarations in the `secureJsonData`-block of a datasource will be leaked to the + Nix store unless a file-provider or an env-var is used! + '') + ++ (optional ( + any (x: x.secure_settings != null) cfg.provision.notifiers + ) "Notifier secure settings will be stored as plaintext in the Nix store! Use file provider instead."); environment.systemPackages = [ cfg.package ]; assertions = [ { - assertion = if (builtins.isList cfg.provision.datasources) then true else cfg.provision.datasources.settings == null || cfg.provision.datasources.path == null; + assertion = cfg.provision.datasources.settings == null || cfg.provision.datasources.path == null; message = "Cannot set both datasources settings and datasources path"; } { @@ -1213,12 +1222,11 @@ in { ({ type, access, ... }: type == "prometheus" -> access != "direct") opt; in - if (builtins.isList cfg.provision.datasources) then prometheusIsNotDirect cfg.provision.datasources - else cfg.provision.datasources.settings == null || prometheusIsNotDirect cfg.provision.datasources.settings.datasources; + cfg.provision.datasources.settings == null || prometheusIsNotDirect cfg.provision.datasources.settings.datasources; message = "For datasources of type `prometheus`, the `direct` access mode is not supported anymore (since Grafana 9.2.0)"; } { - assertion = if (builtins.isList cfg.provision.dashboards) then true else cfg.provision.dashboards.settings == null || cfg.provision.dashboards.path == null; + assertion = cfg.provision.dashboards.settings == null || cfg.provision.dashboards.path == null; message = "Cannot set both dashboards settings and dashboards path"; } { diff --git a/nixos/modules/services/monitoring/tremor-rs.nix b/nixos/modules/services/monitoring/tremor-rs.nix new file mode 100644 index 0000000000000..213e8a474868c --- /dev/null +++ b/nixos/modules/services/monitoring/tremor-rs.nix @@ -0,0 +1,129 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + + cfg = config.services.tremor-rs; + + loggerSettingsFormat = pkgs.formats.yaml { }; + loggerConfigFile = loggerSettingsFormat.generate "logger.yaml" cfg.loggerSettings; +in { + + options = { + services.tremor-rs = { + enable = lib.mkEnableOption (lib.mdDoc "Tremor event- or stream-processing system"); + + troyFileList = mkOption { + type = types.listOf types.path; + default = []; + description = lib.mdDoc "List of troy files to load."; + }; + + tremorLibDir = mkOption { + type = types.path; + default = ""; + description = lib.mdDoc "Directory where to find /lib containing tremor script files"; + }; + + host = mkOption { + type = types.str; + default = "127.0.0.1"; + description = lib.mdDoc "The host tremor should be listening on"; + }; + + port = mkOption { + type = types.port; + default = 9898; + description = lib.mdDoc "the port tremor should be listening on"; + }; + + loggerSettings = mkOption { + description = lib.mdDoc "Tremor logger configuration"; + default = {}; + type = loggerSettingsFormat.type; + + example = { + refresh_rate = "30 seconds"; + appenders.stdout.kind = "console"; + root = { + level = "warn"; + appenders = [ "stdout" ]; + }; + loggers = { + tremor_runtime = { + level = "debug"; + appenders = [ "stdout" ]; + additive = false; + }; + tremor = { + level = "debug"; + appenders = [ "stdout" ]; + additive = false; + }; + }; + }; + + defaultText = literalExpression '' + { + refresh_rate = "30 seconds"; + appenders.stdout.kind = "console"; + root = { + level = "warn"; + appenders = [ "stdout" ]; + }; + loggers = { + tremor_runtime = { + level = "debug"; + appenders = [ "stdout" ]; + additive = false; + }; + tremor = { + level = "debug"; + appenders = [ "stdout" ]; + additive = false; + }; + }; + } + ''; + + }; + }; + }; + + config = mkIf (cfg.enable) { + + environment.systemPackages = [ pkgs.tremor-rs ] ; + + systemd.services.tremor-rs = { + description = "Tremor event- or stream-processing system"; + wantedBy = [ "multi-user.target" ]; + requires = [ "network-online.target" ]; + after = [ "network-online.target" ]; + + environment.TREMOR_PATH = "${pkgs.tremor-rs}/lib:${cfg.tremorLibDir}"; + + serviceConfig = { + ExecStart = "${pkgs.tremor-rs}/bin/tremor --logger-config ${loggerConfigFile} server run ${concatStringsSep " " cfg.troyFileList} --api-host ${cfg.host}:${toString cfg.port}"; + DynamicUser = true; + Restart = "always"; + NoNewPrivileges = true; + PrivateTmp = true; + ProtectHome = true; + ProtectClock = true; + ProtectProc = "noaccess"; + ProcSubset = "pid"; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectControlGroups = true; + ProtectHostname = true; + RestrictSUIDSGID = true; + RestrictRealtime = true; + RestrictNamespaces = true; + LockPersonality = true; + RemoveIPC = true; + SystemCallFilter = [ "@system-service" "~@privileged" ]; + }; + }; + }; +} diff --git a/nixos/modules/services/networking/firewall.nix b/nixos/modules/services/networking/firewall.nix index 0242a3780ffc5..27119dcc57c55 100644 --- a/nixos/modules/services/networking/firewall.nix +++ b/nixos/modules/services/networking/firewall.nix @@ -325,7 +325,7 @@ in example = literalExpression "pkgs.iptables-legacy"; description = lib.mdDoc '' - The iptables package to use for running the firewall service." + The iptables package to use for running the firewall service. ''; }; diff --git a/nixos/modules/services/networking/mullvad-vpn.nix b/nixos/modules/services/networking/mullvad-vpn.nix index 7eb3761aad37b..82e68bf92af1f 100644 --- a/nixos/modules/services/networking/mullvad-vpn.nix +++ b/nixos/modules/services/networking/mullvad-vpn.nix @@ -14,6 +14,15 @@ with lib; ''; }; + enableExcludeWrapper = mkOption { + type = types.bool; + default = true; + description = lib.mdDoc '' + This option activates the wrapper that allows the use of mullvad-exclude. + Might have minor security impact, so consider disabling if you do not use the feature. + ''; + }; + package = mkOption { type = types.package; default = pkgs.mullvad; @@ -27,12 +36,22 @@ with lib; config = mkIf cfg.enable { boot.kernelModules = [ "tun" ]; + environment.systemPackages = [ cfg.package ]; + # mullvad-daemon writes to /etc/iproute2/rt_tables networking.iproute2.enable = true; # See https://github.com/NixOS/nixpkgs/issues/113589 networking.firewall.checkReversePath = "loose"; + # See https://github.com/NixOS/nixpkgs/issues/176603 + security.wrappers.mullvad-exclude = mkIf cfg.enableExcludeWrapper { + setuid = true; + owner = "root"; + group = "root"; + source = "${cfg.package}/bin/mullvad-exclude"; + }; + systemd.services.mullvad-daemon = { description = "Mullvad VPN daemon"; wantedBy = [ "multi-user.target" ]; diff --git a/nixos/modules/services/networking/tailscale.nix b/nixos/modules/services/networking/tailscale.nix index eb3afe118c644..26997dd96013c 100644 --- a/nixos/modules/services/networking/tailscale.nix +++ b/nixos/modules/services/networking/tailscale.nix @@ -41,7 +41,11 @@ in { }; config = mkIf cfg.enable { - warnings = optional (firewallOn && rpfIsStrict) "Strict reverse path filtering breaks Tailscale exit node use and some subnet routing setups. Consider setting `networking.firewall.checkReversePath` = 'loose'"; + warnings = optional (firewallOn && rpfIsStrict) '' + Strict reverse path filtering breaks Tailscale exit node use and some subnet routing setups. Consider setting: + + networking.firewall.checkReversePath = "loose"; + ''; environment.systemPackages = [ cfg.package ]; # for the CLI systemd.packages = [ cfg.package ]; systemd.services.tailscaled = { diff --git a/nixos/modules/services/system/dbus.nix b/nixos/modules/services/system/dbus.nix index c0de00bb914ca..b87e48f2945d1 100644 --- a/nixos/modules/services/system/dbus.nix +++ b/nixos/modules/services/system/dbus.nix @@ -1,8 +1,6 @@ # D-Bus configuration and system bus daemon. -{ config, lib, options, pkgs, ... }: - -with lib; +{ config, lib, pkgs, ... }: let @@ -16,11 +14,11 @@ let serviceDirectories = cfg.packages; }; + inherit (lib) mkOption types; + in { - ###### interface - options = { services.dbus = { @@ -65,31 +63,13 @@ in ''; default = "disabled"; }; - - socketActivated = mkOption { - type = types.nullOr types.bool; - default = null; - visible = false; - description = lib.mdDoc '' - Removed option, do not use. - ''; - }; }; }; - ###### implementation - - config = mkIf cfg.enable { - warnings = optional (cfg.socketActivated != null) ( - let - files = showFiles options.services.dbus.socketActivated.files; - in - "The option 'services.dbus.socketActivated' in ${files} no longer has" - + " any effect and can be safely removed: the user D-Bus session is" - + " now always socket activated." - ); - - environment.systemPackages = [ pkgs.dbus.daemon pkgs.dbus ]; + config = lib.mkIf cfg.enable { + environment.systemPackages = [ + pkgs.dbus + ]; environment.etc."dbus-1".source = configDir; @@ -102,10 +82,12 @@ in users.groups.messagebus.gid = config.ids.gids.messagebus; - systemd.packages = [ pkgs.dbus.daemon ]; + systemd.packages = [ + pkgs.dbus + ]; security.wrappers.dbus-daemon-launch-helper = { - source = "${pkgs.dbus.daemon}/libexec/dbus-daemon-launch-helper"; + source = "${pkgs.dbus}/libexec/dbus-daemon-launch-helper"; owner = "root"; group = "messagebus"; setuid = true; @@ -114,26 +96,36 @@ in }; services.dbus.packages = [ - pkgs.dbus.out + pkgs.dbus config.system.path ]; systemd.services.dbus = { # Don't restart dbus-daemon. Bad things tend to happen if we do. reloadIfChanged = true; - restartTriggers = [ configDir ]; - environment = { LD_LIBRARY_PATH = config.system.nssModules.path; }; + restartTriggers = [ + configDir + ]; + environment = { + LD_LIBRARY_PATH = config.system.nssModules.path; + }; }; - systemd.user = { - services.dbus = { - # Don't restart dbus-daemon. Bad things tend to happen if we do. - reloadIfChanged = true; - restartTriggers = [ configDir ]; - }; - sockets.dbus.wantedBy = [ "sockets.target" ]; + systemd.user.services.dbus = { + # Don't restart dbus-daemon. Bad things tend to happen if we do. + reloadIfChanged = true; + restartTriggers = [ + configDir + ]; }; - environment.pathsToLink = [ "/etc/dbus-1" "/share/dbus-1" ]; + systemd.user.sockets.dbus.wantedBy = [ + "sockets.target" + ]; + + environment.pathsToLink = [ + "/etc/dbus-1" + "/share/dbus-1" + ]; }; } diff --git a/nixos/modules/services/web-apps/alps.nix b/nixos/modules/services/web-apps/alps.nix index b73cb82925d9b..4681739af4ab0 100644 --- a/nixos/modules/services/web-apps/alps.nix +++ b/nixos/modules/services/web-apps/alps.nix @@ -70,6 +70,23 @@ in { ''; }; }; + + package = mkOption { + internal = true; + type = types.package; + default = pkgs.alps; + }; + + args = mkOption { + internal = true; + type = types.listOf types.str; + default = [ + "-addr" "${cfg.bindIP}:${toString cfg.port}" + "-theme" "${cfg.theme}" + "imaps://${cfg.imaps.host}:${toString cfg.imaps.port}" + "smpts://${cfg.smtps.host}:${toString cfg.smtps.port}" + ]; + }; }; config = mkIf cfg.enable { @@ -80,16 +97,33 @@ in { after = [ "network.target" "network-online.target" ]; serviceConfig = { - ExecStart = '' - ${pkgs.alps}/bin/alps \ - -addr ${cfg.bindIP}:${toString cfg.port} \ - -theme ${cfg.theme} \ - imaps://${cfg.imaps.host}:${toString cfg.imaps.port} \ - smpts://${cfg.smtps.host}:${toString cfg.smtps.port} - ''; - StateDirectory = "alps"; - WorkingDirectory = "/var/lib/alps"; + ExecStart = "${cfg.package}/bin/alps ${escapeShellArgs cfg.args}"; DynamicUser = true; + ## This is desirable but would restrict bindIP to 127.0.0.1 + #IPAddressAllow = "localhost"; + #IPAddressDeny = "any"; + LockPersonality = true; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateIPC = true; + PrivateTmp = true; + PrivateUsers = true; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + ProtectSystem = "strict"; + RemoveIPC = true; + RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ]; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + SystemCallFilter = [ "@system-service @resources" "~@privileged @obsolete" ]; }; }; }; diff --git a/nixos/modules/services/web-apps/keycloak.nix b/nixos/modules/services/web-apps/keycloak.nix index 521cf778a36bf..d52190a28648e 100644 --- a/nixos/modules/services/web-apps/keycloak.nix +++ b/nixos/modules/services/web-apps/keycloak.nix @@ -482,6 +482,10 @@ in assertion = (cfg.database.useSSL && cfg.database.type == "postgresql") -> (cfg.database.caCert != null); message = "A CA certificate must be specified (in 'services.keycloak.database.caCert') when PostgreSQL is used with SSL"; } + { + assertion = createLocalPostgreSQL -> config.services.postgresql.settings.standard_conforming_strings or true; + message = "Setting up a local PostgreSQL db for Keycloak requires `standard_conforming_strings` turned on to work reliably"; + } ]; environment.systemPackages = [ keycloakBuild ]; @@ -544,7 +548,13 @@ in create_role="$(mktemp)" trap 'rm -f "$create_role"' EXIT + # Read the password from the credentials directory and + # escape any single quotes by adding additional single + # quotes after them, following the rules laid out here: + # https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-CONSTANTS db_password="$(<"$CREDENTIALS_DIRECTORY/db_password")" + db_password="''${db_password//\'/\'\'}" + echo "CREATE ROLE keycloak WITH LOGIN PASSWORD '$db_password' CREATEDB" > "$create_role" psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='keycloak'" | grep -q 1 || psql -tA --file="$create_role" psql -tAc "SELECT 1 FROM pg_database WHERE datname = 'keycloak'" | grep -q 1 || psql -tAc 'CREATE DATABASE "keycloak" OWNER "keycloak"' @@ -566,8 +576,16 @@ in script = '' set -o errexit -o pipefail -o nounset -o errtrace shopt -s inherit_errexit + + # Read the password from the credentials directory and + # escape any single quotes by adding additional single + # quotes after them, following the rules laid out here: + # https://dev.mysql.com/doc/refman/8.0/en/string-literals.html db_password="$(<"$CREDENTIALS_DIRECTORY/db_password")" - ( echo "CREATE USER IF NOT EXISTS 'keycloak'@'localhost' IDENTIFIED BY '$db_password';" + db_password="''${db_password//\'/\'\'}" + + ( echo "SET sql_mode = 'NO_BACKSLASH_ESCAPES';" + echo "CREATE USER IF NOT EXISTS 'keycloak'@'localhost' IDENTIFIED BY '$db_password';" echo "CREATE DATABASE IF NOT EXISTS keycloak CHARACTER SET utf8 COLLATE utf8_unicode_ci;" echo "GRANT ALL PRIVILEGES ON keycloak.* TO 'keycloak'@'localhost';" ) | mysql -N @@ -632,12 +650,17 @@ in ${secretReplacements} + # Escape any backslashes in the db parameters, since + # they're otherwise unexpectedly read as escape + # sequences. + sed -i '/db-/ s|\\|\\\\|g' /run/keycloak/conf/keycloak.conf + '' + optionalString (cfg.sslCertificate != null && cfg.sslCertificateKey != null) '' mkdir -p /run/keycloak/ssl cp $CREDENTIALS_DIRECTORY/ssl_{cert,key} /run/keycloak/ssl/ '' + '' export KEYCLOAK_ADMIN=admin - export KEYCLOAK_ADMIN_PASSWORD=${cfg.initialAdminPassword} + export KEYCLOAK_ADMIN_PASSWORD=${escapeShellArg cfg.initialAdminPassword} kc.sh start --optimized ''; }; diff --git a/nixos/modules/services/web-apps/mastodon.nix b/nixos/modules/services/web-apps/mastodon.nix index d159d2ade0630..1e9e04dcc0558 100644 --- a/nixos/modules/services/web-apps/mastodon.nix +++ b/nixos/modules/services/web-apps/mastodon.nix @@ -688,7 +688,7 @@ in { inherit (cfg) group; }; }) - (lib.attrsets.setAttrByPath [ cfg.user "packages" ] [ cfg.package mastodonEnv ]) + (lib.attrsets.setAttrByPath [ cfg.user "packages" ] [ cfg.package mastodonEnv pkgs.imagemagick ]) ]; users.groups.${cfg.group}.members = lib.optional cfg.configureNginx config.services.nginx.user; diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix index 04599884f139c..da621573f2a26 100644 --- a/nixos/modules/services/web-apps/nextcloud.nix +++ b/nixos/modules/services/web-apps/nextcloud.nix @@ -13,7 +13,12 @@ let phpPackage = cfg.phpPackage.buildEnv { extensions = { enabled, all }: (with all; - enabled + # disable default openssl extension + (lib.filter (e: e.pname != "php-openssl") enabled) + # use OpenSSL 1.1 for RC4 Nextcloud encryption if user + # has acknowledged the brokeness of the ciphers (RC4). + # TODO: remove when https://github.com/nextcloud/server/issues/32003 is fixed. + ++ (if cfg.enableBrokenCiphersForSSE then [ cfg.phpPackage.extensions.openssl-legacy ] else [ cfg.phpPackage.extensions.openssl ]) ++ optional cfg.enableImagemagick imagick # Optionally enabled depending on caching settings ++ optional cfg.caching.apcu apcu @@ -80,6 +85,40 @@ in { options.services.nextcloud = { enable = mkEnableOption (lib.mdDoc "nextcloud"); + + enableBrokenCiphersForSSE = mkOption { + type = types.bool; + default = versionOlder stateVersion "22.11"; + defaultText = literalExpression "versionOlder system.stateVersion \"22.11\""; + description = lib.mdDoc '' + This option enables using the OpenSSL PHP extension linked against OpenSSL 1.1 + rather than latest OpenSSL (≥ 3), this is not recommended unless you need + it for server-side encryption (SSE). SSE uses the legacy RC4 cipher which is + considered broken for several years now. See also [RFC7465](https://datatracker.ietf.org/doc/html/rfc7465). + + This cipher has been disabled in OpenSSL ≥ 3 and requires + a specific legacy profile to re-enable it. + + If you deploy Nextcloud using OpenSSL ≥ 3 for PHP and have + server-side encryption configured, you will not be able to access + your files anymore. Enabling this option can restore access to your files. + Upon testing we didn't encounter any data corruption when turning + this on and off again, but this cannot be guaranteed for + each Nextcloud installation. + + It is `true` by default for systems with a [](#opt-system.stateVersion) below + `22.11` to make sure that existing installations won't break on update. On newer + NixOS systems you have to explicitly enable it on your own. + + Please note that this only provides additional value when using + external storage such as S3 since it's not an end-to-end encryption. + If this is not the case, + it is advised to [disable server-side encryption](https://docs.nextcloud.com/server/latest/admin_manual/configuration_files/encryption_configuration.html#disabling-encryption) and set this to `false`. + + In the future, Nextcloud may move to AES-256-GCM, by then, + this option will be removed. + ''; + }; hostName = mkOption { type = types.str; description = lib.mdDoc "FQDN for the nextcloud instance."; @@ -649,6 +688,23 @@ in { ++ (optional (versionOlder cfg.package.version "23") (upgradeWarning 22 "22.05")) ++ (optional (versionOlder cfg.package.version "24") (upgradeWarning 23 "22.05")) ++ (optional (versionOlder cfg.package.version "25") (upgradeWarning 24 "22.11")) + ++ (optional cfg.enableBrokenCiphersForSSE '' + You're using PHP's openssl extension built against OpenSSL 1.1 for Nextcloud. + This is only necessary if you're using Nextcloud's server-side encryption. + Please keep in mind that it's using the broken RC4 cipher. + + If you don't use that feature, you can switch to OpenSSL 3 and get + rid of this warning by declaring + + services.nextcloud.enableBrokenCiphersForSSE = false; + + If you need to use server-side encryption you can ignore this waring. + Otherwise you'd have to disable server-side encryption first in order + to be able to safely disable this option and get rid of this warning. + See <https://docs.nextcloud.com/server/latest/admin_manual/configuration_files/encryption_configuration.html#disabling-encryption> on how to achieve this. + + For more context, here is the implementing pull request: https://github.com/NixOS/nixpkgs/pull/198470 + '') ++ (optional isUnsupportedMariadb '' You seem to be using MariaDB at an unsupported version (i.e. at least 10.6)! Please note that this isn't supported officially by Nextcloud. You can either diff --git a/nixos/modules/services/web-apps/nextcloud.xml b/nixos/modules/services/web-apps/nextcloud.xml index a0b69dbd606ce..ca57692fc16a8 100644 --- a/nixos/modules/services/web-apps/nextcloud.xml +++ b/nixos/modules/services/web-apps/nextcloud.xml @@ -170,6 +170,20 @@ </listitem> </itemizedlist> </listitem> + <listitem> + <formalpara> + <title>Server-side encryption</title> + <para> + Nextcloud supports <link xlink:href="https://docs.nextcloud.com/server/latest/admin_manual/configuration_files/encryption_configuration.html">server-side encryption (SSE)</link>. + This is not an end-to-end encryption, but can be used to encrypt files that will be persisted + to external storage such as S3. Please note that this won't work anymore when using OpenSSL 3 + for PHP's openssl extension because this is implemented using the legacy cipher RC4. + If <xref linkend="opt-system.stateVersion" /> is <emphasis>above</emphasis> <literal>22.05</literal>, + this is disabled by default. To turn it on again and for further information please refer to + <xref linkend="opt-services.nextcloud.enableBrokenCiphersForSSE" />. + </para> + </formalpara> + </listitem> </itemizedlist> </section> diff --git a/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixos/modules/services/x11/desktop-managers/plasma5.nix index 44faa19bc22ab..a6ab3053087c1 100644 --- a/nixos/modules/services/x11/desktop-managers/plasma5.nix +++ b/nixos/modules/services/x11/desktop-managers/plasma5.nix @@ -590,9 +590,9 @@ in }; }; kwinrc = { - Windows = { - # Forces windows to be maximized - Placement = lib.mkDefault "Maximizing"; + "Wayland" = { + "InputMethod[$e]" = "/run/current-system/sw/share/applications/com.github.maliit.keyboard.desktop"; + "VirtualKeyboardEnabled" = "true"; }; "org.kde.kdecoration2" = { # No decorations (title bar) diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh index 994aa0e33cbfa..4596c160a9571 100644 --- a/nixos/modules/system/boot/stage-1-init.sh +++ b/nixos/modules/system/boot/stage-1-init.sh @@ -342,6 +342,14 @@ checkFS() { return 0 } +escapeFstab() { + local original="$1" + + # Replace space + local escaped="${original// /\\040}" + # Replace tab + echo "${escaped//$'\t'/\\011}" +} # Function for mounting a file system. mountFS() { @@ -569,7 +577,7 @@ while read -u 3 mountPoint; do continue fi - mountFS "$device" "$mountPoint" "$options" "$fsType" + mountFS "$device" "$(escapeFstab "$mountPoint")" "$(escapeFstab "$options")" "$fsType" done exec 3>&- diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix index 399ea9eabe08d..7ab8f8dc676c7 100644 --- a/nixos/modules/tasks/filesystems.nix +++ b/nixos/modules/tasks/filesystems.nix @@ -167,7 +167,7 @@ let else throw "No device specified for mount point ‘${fs.mountPoint}’.") + " " + escape (rootPrefix + fs.mountPoint) + " " + fs.fsType - + " " + builtins.concatStringsSep "," (fs.options ++ (extraOpts fs)) + + " " + escape (builtins.concatStringsSep "," (fs.options ++ (extraOpts fs))) + " " + (optionalString (!excludeChecks) ("0 " + (if skipCheck fs then "0" else if fs.mountPoint == "/" then "1" else "2"))) + "\n" diff --git a/nixos/modules/tasks/filesystems/ext.nix b/nixos/modules/tasks/filesystems/ext.nix index 9b61f21643aba..edc0efc552136 100644 --- a/nixos/modules/tasks/filesystems/ext.nix +++ b/nixos/modules/tasks/filesystems/ext.nix @@ -3,13 +3,14 @@ let inInitrd = lib.any (fs: fs == "ext2" || fs == "ext3" || fs == "ext4") config.boot.initrd.supportedFilesystems; + inSystem = lib.any (fs: fs == "ext2" || fs == "ext3" || fs == "ext4") config.boot.supportedFilesystems; in { config = { - system.fsPackages = lib.mkIf (config.boot.initrd.systemd.enable -> inInitrd) [ pkgs.e2fsprogs ]; + system.fsPackages = lib.mkIf (config.boot.initrd.systemd.enable -> (inInitrd || inSystem)) [ pkgs.e2fsprogs ]; # As of kernel 4.3, there is no separate ext3 driver (they're also handled by ext4.ko) boot.initrd.availableKernelModules = lib.mkIf (config.boot.initrd.systemd.enable -> inInitrd) [ "ext2" "ext4" ]; diff --git a/nixos/release-combined.nix b/nixos/release-combined.nix index bd7b452735f1c..337b5192776f8 100644 --- a/nixos/release-combined.nix +++ b/nixos/release-combined.nix @@ -77,6 +77,7 @@ in rec { (onFullSupported "nixos.tests.i3wm") (onSystems ["x86_64-linux"] "nixos.tests.installer.btrfsSimple") (onSystems ["x86_64-linux"] "nixos.tests.installer.btrfsSubvolDefault") + (onSystems ["x86_64-linux"] "nixos.tests.installer.btrfsSubvolEscape") (onSystems ["x86_64-linux"] "nixos.tests.installer.btrfsSubvols") (onSystems ["x86_64-linux"] "nixos.tests.installer.luksroot") (onSystems ["x86_64-linux"] "nixos.tests.installer.lvm") diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index bd0fe18c4f8c2..d3dc8b9ca08a4 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -74,6 +74,7 @@ in { agda = handleTest ./agda.nix {}; airsonic = handleTest ./airsonic.nix {}; allTerminfo = handleTest ./all-terminfo.nix {}; + alps = handleTest ./alps.nix {}; amazon-init-shell = handleTest ./amazon-init-shell.nix {}; apfs = handleTest ./apfs.nix {}; apparmor = handleTest ./apparmor.nix {}; @@ -251,8 +252,8 @@ in { haproxy = handleTest ./haproxy.nix {}; hardened = handleTest ./hardened.nix {}; healthchecks = handleTest ./web-apps/healthchecks.nix {}; - hbase1 = handleTest ./hbase.nix { package=pkgs.hbase1; }; hbase2 = handleTest ./hbase.nix { package=pkgs.hbase2; }; + hbase_2_4 = handleTest ./hbase.nix { package=pkgs.hbase_2_4; }; hbase3 = handleTest ./hbase.nix { package=pkgs.hbase3; }; hedgedoc = handleTest ./hedgedoc.nix {}; herbstluftwm = handleTest ./herbstluftwm.nix {}; @@ -490,9 +491,11 @@ in { pgadmin4-standalone = handleTest ./pgadmin4-standalone.nix {}; pgjwt = handleTest ./pgjwt.nix {}; pgmanage = handleTest ./pgmanage.nix {}; + phosh = handleTest ./phosh.nix {}; php = handleTest ./php {}; php80 = handleTest ./php { php = pkgs.php80; }; php81 = handleTest ./php { php = pkgs.php81; }; + php82 = handleTest ./php { php = pkgs.php82; }; phylactery = handleTest ./web-apps/phylactery.nix {}; pict-rs = handleTest ./pict-rs.nix {}; pinnwand = handleTest ./pinnwand.nix {}; diff --git a/nixos/tests/alps.nix b/nixos/tests/alps.nix new file mode 100644 index 0000000000000..8d7814117df1e --- /dev/null +++ b/nixos/tests/alps.nix @@ -0,0 +1,104 @@ +let + certs = import ./common/acme/server/snakeoil-certs.nix; + domain = certs.domain; +in +import ./make-test-python.nix ({ pkgs, ... }: { + name = "alps"; + + nodes = { + server = { + imports = [ ./common/user-account.nix ]; + security.pki.certificateFiles = [ + certs.ca.cert + ]; + networking.extraHosts = '' + 127.0.0.1 ${domain} + ''; + networking.firewall.allowedTCPPorts = [ 25 465 993 ]; + services.postfix = { + enable = true; + enableSubmission = true; + enableSubmissions = true; + tlsTrustedAuthorities = "${certs.ca.cert}"; + sslCert = "${certs.${domain}.cert}"; + sslKey = "${certs.${domain}.key}"; + }; + services.dovecot2 = { + enable = true; + enableImap = true; + sslCACert = "${certs.ca.cert}"; + sslServerCert = "${certs.${domain}.cert}"; + sslServerKey = "${certs.${domain}.key}"; + }; + }; + + client = { nodes, config, ... }: { + security.pki.certificateFiles = [ + certs.ca.cert + ]; + networking.extraHosts = '' + ${nodes.server.config.networking.primaryIPAddress} ${domain} + ''; + services.alps = { + enable = true; + theme = "alps"; + imaps = { + host = domain; + port = 993; + }; + smtps = { + host = domain; + port = 465; + }; + }; + environment.systemPackages = [ + (pkgs.writers.writePython3Bin "test-alps-login" { } '' + from urllib.request import build_opener, HTTPCookieProcessor, Request + from urllib.parse import urlencode, urljoin + from http.cookiejar import CookieJar + + baseurl = "http://localhost:${toString config.services.alps.port}" + username = "alice" + password = "${nodes.server.config.users.users.alice.password}" + cookiejar = CookieJar() + cookieprocessor = HTTPCookieProcessor(cookiejar) + opener = build_opener(cookieprocessor) + + data = urlencode({"username": username, "password": password}).encode() + req = Request(urljoin(baseurl, "login"), data=data, method="POST") + with opener.open(req) as ret: + # Check that the alps_session cookie is set + print(cookiejar) + assert any(cookie.name == "alps_session" for cookie in cookiejar) + + req = Request(baseurl) + with opener.open(req) as ret: + # Check that the alps_session cookie is still there... + print(cookiejar) + assert any(cookie.name == "alps_session" for cookie in cookiejar) + # ...and that we have not been redirected back to the login page + print(ret.url) + assert ret.url == urljoin(baseurl, "mailbox/INBOX") + + req = Request(urljoin(baseurl, "logout")) + with opener.open(req) as ret: + # Check that the alps_session cookie is now gone + print(cookiejar) + assert all(cookie.name != "alps_session" for cookie in cookiejar) + '') + ]; + }; + }; + + testScript = '' + server.start() + server.wait_for_unit("postfix.service") + server.wait_for_unit("dovecot2.service") + server.wait_for_open_port(465) + server.wait_for_open_port(993) + + client.start() + client.wait_for_unit("alps.service") + client.succeed("test-alps-login") + ''; +}) diff --git a/nixos/tests/common/acme/server/acme.test.cert.pem b/nixos/tests/common/acme/server/acme.test.cert.pem index 76b0d916a8175..562e7a329b681 100644 --- a/nixos/tests/common/acme/server/acme.test.cert.pem +++ b/nixos/tests/common/acme/server/acme.test.cert.pem @@ -1,19 +1,19 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- diff --git a/nixos/tests/common/acme/server/acme.test.key.pem b/nixos/tests/common/acme/server/acme.test.key.pem index 741df99a372e3..fd3e9f7dbcf61 100644 --- a/nixos/tests/common/acme/server/acme.test.key.pem +++ b/nixos/tests/common/acme/server/acme.test.key.pem @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- diff --git a/nixos/tests/common/acme/server/ca.cert.pem b/nixos/tests/common/acme/server/ca.cert.pem index 5c33e879b675b..8d52a0a8f462c 100644 --- a/nixos/tests/common/acme/server/ca.cert.pem +++ b/nixos/tests/common/acme/server/ca.cert.pem @@ -1,20 +1,20 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- diff --git a/nixos/tests/common/acme/server/ca.key.pem b/nixos/tests/common/acme/server/ca.key.pem index ed46f5dccf467..cde4e8ac7c758 100644 --- a/nixos/tests/common/acme/server/ca.key.pem +++ b/nixos/tests/common/acme/server/ca.key.pem @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- diff --git a/nixos/tests/deluge.nix b/nixos/tests/deluge.nix index 0cd1d21870adf..e8945fdea003a 100644 --- a/nixos/tests/deluge.nix +++ b/nixos/tests/deluge.nix @@ -54,8 +54,10 @@ import ./make-test-python.nix ({ pkgs, ...} : { declarative.wait_for_unit("deluged") declarative.wait_for_unit("delugeweb") declarative.wait_until_succeeds("curl --fail http://declarative:3142") + + # deluge-console always exits with 1. https://dev.deluge-torrent.org/ticket/3291 declarative.succeed( - "deluge-console 'connect 127.0.0.1:58846 andrew password; help' | grep -q 'rm.*Remove a torrent'" + "(deluge-console 'connect 127.0.0.1:58846 andrew password; help' || true) | grep -q 'rm.*Remove a torrent'" ) ''; }) diff --git a/nixos/tests/grafana/provision/default.nix b/nixos/tests/grafana/provision/default.nix index 7a707ab9fed1f..1eb927632eb7a 100644 --- a/nixos/tests/grafana/provision/default.nix +++ b/nixos/tests/grafana/provision/default.nix @@ -17,7 +17,7 @@ let security = { admin_user = "testadmin"; - admin_password = "snakeoilpwd"; + admin_password = "$__file{${pkgs.writeText "pwd" "snakeoilpwd"}}"; }; }; }; @@ -28,17 +28,24 @@ let }; extraNodeConfs = { - provisionOld = { + provisionLegacyNotifiers = { services.grafana.provision = { - datasources = [{ - name = "Test Datasource"; - type = "testdata"; - access = "proxy"; - uid = "test_datasource"; - }]; - - dashboards = [{ options.path = "/var/lib/grafana/dashboards"; }]; - + datasources.settings = { + apiVersion = 1; + datasources = [{ + name = "Test Datasource"; + type = "testdata"; + access = "proxy"; + uid = "test_datasource"; + }]; + }; + dashboards.settings = { + apiVersion = 1; + providers = [{ + name = "default"; + options.path = "/var/lib/grafana/dashboards"; + }]; + }; notifiers = [{ uid = "test_notifiers"; name = "Test Notifiers"; @@ -50,7 +57,6 @@ let }]; }; }; - provisionNix = { services.grafana.provision = { datasources.settings = { @@ -157,6 +163,22 @@ let }; }; }; + + provisionYamlDirs = let + mkdir = p: pkgs.writeTextDir (baseNameOf p) (builtins.readFile p); + in { + services.grafana.provision = { + datasources.path = mkdir ./datasources.yaml; + dashboards.path = mkdir ./dashboards.yaml; + alerting = { + rules.path = mkdir ./rules.yaml; + contactPoints.path = mkdir ./contact-points.yaml; + policies.path = mkdir ./policies.yaml; + templates.path = mkdir ./templates.yaml; + muteTimings.path = mkdir ./mute-timings.yaml; + }; + }; + }; }; nodes = builtins.mapAttrs (_: val: mkMerge [ val baseGrafanaConf ]) extraNodeConfs; @@ -172,58 +194,58 @@ in { testScript = '' start_all() - nodeOld = ("Nix (old format)", provisionOld) nodeNix = ("Nix (new format)", provisionNix) nodeYaml = ("Nix (YAML)", provisionYaml) + nodeYamlDir = ("Nix (YAML in dirs)", provisionYamlDirs) - for nodeInfo in [nodeOld, nodeNix, nodeYaml]: - with subtest(f"Should start provision node: {nodeInfo[0]}"): - nodeInfo[1].wait_for_unit("grafana.service") - nodeInfo[1].wait_for_open_port(3000) + for description, machine in [nodeNix, nodeYaml, nodeYamlDir]: + with subtest(f"Should start provision node: {description}"): + machine.wait_for_unit("grafana.service") + machine.wait_for_open_port(3000) - with subtest(f"Successful datasource provision with {nodeInfo[0]}"): - nodeInfo[1].succeed( + with subtest(f"Successful datasource provision with {description}"): + machine.succeed( "curl -sSfN -u testadmin:snakeoilpwd http://127.0.0.1:3000/api/datasources/uid/test_datasource | grep Test\ Datasource" ) - with subtest(f"Successful dashboard provision with {nodeInfo[0]}"): - nodeInfo[1].succeed( + with subtest(f"Successful dashboard provision with {description}"): + machine.succeed( "curl -sSfN -u testadmin:snakeoilpwd http://127.0.0.1:3000/api/dashboards/uid/test_dashboard | grep Test\ Dashboard" ) - - - with subtest(f"Successful notifiers provision with {nodeOld[0]}"): - nodeOld[1].succeed( - "curl -sSfN -u testadmin:snakeoilpwd http://127.0.0.1:3000/api/alert-notifications/uid/test_notifiers | grep Test\ Notifiers" - ) - - - - for nodeInfo in [nodeNix, nodeYaml]: - with subtest(f"Successful rule provision with {nodeInfo[0]}"): - nodeInfo[1].succeed( + with subtest(f"Successful rule provision with {description}"): + machine.succeed( "curl -sSfN -u testadmin:snakeoilpwd http://127.0.0.1:3000/api/v1/provisioning/alert-rules/test_rule | grep Test\ Rule" ) - with subtest(f"Successful contact point provision with {nodeInfo[0]}"): - nodeInfo[1].succeed( + with subtest(f"Successful contact point provision with {description}"): + machine.succeed( "curl -sSfN -u testadmin:snakeoilpwd http://127.0.0.1:3000/api/v1/provisioning/contact-points | grep Test\ Contact\ Point" ) - with subtest(f"Successful policy provision with {nodeInfo[0]}"): - nodeInfo[1].succeed( + with subtest(f"Successful policy provision with {description}"): + machine.succeed( "curl -sSfN -u testadmin:snakeoilpwd http://127.0.0.1:3000/api/v1/provisioning/policies | grep Test\ Contact\ Point" ) - with subtest(f"Successful template provision with {nodeInfo[0]}"): - nodeInfo[1].succeed( + with subtest(f"Successful template provision with {description}"): + machine.succeed( "curl -sSfN -u testadmin:snakeoilpwd http://127.0.0.1:3000/api/v1/provisioning/templates | grep Test\ Template" ) - with subtest("Successful mute timings provision with {nodeInfo[0]}"): - nodeInfo[1].succeed( + with subtest("Successful mute timings provision with {description}"): + machine.succeed( "curl -sSfN -u testadmin:snakeoilpwd http://127.0.0.1:3000/api/v1/provisioning/mute-timings | grep Test\ Mute\ Timing" ) + + with subtest("Successful notifiers provision"): + provisionLegacyNotifiers.wait_for_unit("grafana.service") + provisionLegacyNotifiers.wait_for_open_port(3000) + print(provisionLegacyNotifiers.succeed( + "curl -sSfN -u testadmin:snakeoilpwd http://127.0.0.1:3000/api/alert-notifications/uid/test_notifiers" + )) + provisionLegacyNotifiers.succeed( + "curl -sSfN -u testadmin:snakeoilpwd http://127.0.0.1:3000/api/alert-notifications/uid/test_notifiers | grep Test\ Notifiers" + ) ''; }) diff --git a/nixos/tests/hibernate.nix b/nixos/tests/hibernate.nix index 7a4b331169a39..cb75322ca5f92 100644 --- a/nixos/tests/hibernate.nix +++ b/nixos/tests/hibernate.nix @@ -26,8 +26,9 @@ let powerManagement.resumeCommands = "systemctl --no-block restart backdoor.service"; - fileSystems = { - "/".device = "/dev/vda2"; + fileSystems."/" = { + device = "/dev/vda2"; + fsType = "ext3"; }; swapDevices = mkOverride 0 [ { device = "/dev/vda1"; } ]; boot.resumeDevice = mkIf systemdStage1 "/dev/vda1"; diff --git a/nixos/tests/installer-systemd-stage-1.nix b/nixos/tests/installer-systemd-stage-1.nix index d02387ee80e09..03f0ec8d746b8 100644 --- a/nixos/tests/installer-systemd-stage-1.nix +++ b/nixos/tests/installer-systemd-stage-1.nix @@ -8,9 +8,10 @@ # them when fixed. inherit (import ./installer.nix { inherit system config pkgs; systemdStage1 = true; }) # bcache - # btrfsSimple - # btrfsSubvolDefault - # btrfsSubvols + btrfsSimple + btrfsSubvolDefault + btrfsSubvolEscape + btrfsSubvols # encryptedFSWithKeyfile # grub1 # luksroot diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix index d9f64a781c57e..9b3c8a762991b 100644 --- a/nixos/tests/installer.nix +++ b/nixos/tests/installer.nix @@ -911,4 +911,25 @@ in { ) ''; }; + + # Test to see if we can deal with subvols that need to be escaped in fstab + btrfsSubvolEscape = makeInstallerTest "btrfsSubvolEscape" { + createPartitions = '' + machine.succeed( + "sgdisk -Z /dev/vda", + "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda", + "mkswap /dev/vda2 -L swap", + "swapon -L swap", + "mkfs.btrfs -L root /dev/vda3", + "btrfs device scan", + "mount LABEL=root /mnt", + "btrfs subvol create '/mnt/nixos in space'", + "btrfs subvol create /mnt/boot", + "umount /mnt", + "mount -o 'defaults,subvol=nixos in space' LABEL=root /mnt", + "mkdir /mnt/boot", + "mount -o defaults,subvol=boot LABEL=root /mnt/boot", + ) + ''; + }; } diff --git a/nixos/tests/keycloak.nix b/nixos/tests/keycloak.nix index 6ce136330d438..228e57d1cdd6f 100644 --- a/nixos/tests/keycloak.nix +++ b/nixos/tests/keycloak.nix @@ -5,10 +5,13 @@ let certs = import ./common/acme/server/snakeoil-certs.nix; frontendUrl = "https://${certs.domain}"; - initialAdminPassword = "h4IhoJFnt2iQIR9"; keycloakTest = import ./make-test-python.nix ( { pkgs, databaseType, ... }: + let + initialAdminPassword = "h4Iho\"JFn't2>iQIR9"; + adminPasswordFile = pkgs.writeText "admin-password" "${initialAdminPassword}"; + in { name = "keycloak"; meta = with pkgs.lib.maintainers; { @@ -37,7 +40,7 @@ let type = databaseType; username = "bogus"; name = "also bogus"; - passwordFile = "${pkgs.writeText "dbPassword" "wzf6vOCbPp6cqTH"}"; + passwordFile = "${pkgs.writeText "dbPassword" ''wzf6\"vO"Cb\nP>p#6;c&o?eu=q'THE'''H''''E''}"; }; plugins = with config.services.keycloak.package.plugins; [ keycloak-discord @@ -111,7 +114,7 @@ let keycloak.succeed(""" curl -sSf -d 'client_id=admin-cli' \ -d 'username=admin' \ - -d 'password=${initialAdminPassword}' \ + -d "password=$(<${adminPasswordFile})" \ -d 'grant_type=password' \ '${frontendUrl}/realms/master/protocol/openid-connect/token' \ | jq -r '"Authorization: bearer " + .access_token' >admin_auth_header @@ -119,10 +122,10 @@ let # Register the metrics SPI keycloak.succeed( - "${pkgs.jre}/bin/keytool -import -alias snakeoil -file ${certs.ca.cert} -storepass aaaaaa -keystore cacert.jks -noprompt", - "KC_OPTS='-Djavax.net.ssl.trustStore=cacert.jks -Djavax.net.ssl.trustStorePassword=aaaaaa' kcadm.sh config credentials --server '${frontendUrl}' --realm master --user admin --password '${initialAdminPassword}'", - "KC_OPTS='-Djavax.net.ssl.trustStore=cacert.jks -Djavax.net.ssl.trustStorePassword=aaaaaa' kcadm.sh update events/config -s 'eventsEnabled=true' -s 'adminEventsEnabled=true' -s 'eventsListeners+=metrics-listener'", - "curl -sSf '${frontendUrl}/realms/master/metrics' | grep '^keycloak_admin_event_UPDATE'" + """${pkgs.jre}/bin/keytool -import -alias snakeoil -file ${certs.ca.cert} -storepass aaaaaa -keystore cacert.jks -noprompt""", + """KC_OPTS='-Djavax.net.ssl.trustStore=cacert.jks -Djavax.net.ssl.trustStorePassword=aaaaaa' kcadm.sh config credentials --server '${frontendUrl}' --realm master --user admin --password "$(<${adminPasswordFile})" """, + """KC_OPTS='-Djavax.net.ssl.trustStore=cacert.jks -Djavax.net.ssl.trustStorePassword=aaaaaa' kcadm.sh update events/config -s 'eventsEnabled=true' -s 'adminEventsEnabled=true' -s 'eventsListeners+=metrics-listener'""", + """curl -sSf '${frontendUrl}/realms/master/metrics' | grep '^keycloak_admin_event_UPDATE'""" ) # Publish the realm, including a test OIDC client and user diff --git a/nixos/tests/nextcloud/basic.nix b/nixos/tests/nextcloud/basic.nix index eb37470a4c7bb..a475049e7b264 100644 --- a/nixos/tests/nextcloud/basic.nix +++ b/nixos/tests/nextcloud/basic.nix @@ -37,6 +37,8 @@ in { "d /var/lib/nextcloud-data 0750 nextcloud nginx - -" ]; + system.stateVersion = "22.11"; # stateVersion >=21.11 to make sure that we use OpenSSL3 + services.nextcloud = { enable = true; datadir = "/var/lib/nextcloud-data"; @@ -99,6 +101,10 @@ in { # This is just to ensure the nextcloud-occ program is working nextcloud.succeed("nextcloud-occ status") nextcloud.succeed("curl -sSf http://nextcloud/login") + # Ensure that no OpenSSL 1.1 is used. + nextcloud.succeed( + "${nodes.nextcloud.services.phpfpm.pools.nextcloud.phpPackage}/bin/php -i | grep 'OpenSSL Library Version' | awk -F'=>' '{ print $2 }' | awk '{ print $2 }' | grep -v 1.1" + ) nextcloud.succeed( "${withRcloneEnv} ${copySharedFile}" ) @@ -108,5 +114,6 @@ in { "${withRcloneEnv} ${diffSharedFile}" ) assert "hi" in client.succeed("cat /mnt/dav/test-shared-file") + nextcloud.succeed("grep -vE '^HBEGIN:oc_encryption_module' /var/lib/nextcloud-data/data/root/files/test-shared-file") ''; })) args diff --git a/nixos/tests/nextcloud/default.nix b/nixos/tests/nextcloud/default.nix index 7dbdff9882387..b8d3ba75b51a9 100644 --- a/nixos/tests/nextcloud/default.nix +++ b/nixos/tests/nextcloud/default.nix @@ -8,6 +8,10 @@ with pkgs.lib; foldl (matrix: ver: matrix // { "basic${toString ver}" = import ./basic.nix { inherit system pkgs; nextcloudVersion = ver; }; + "openssl-sse${toString ver}" = import ./openssl-sse.nix { + inherit system pkgs; + nextcloudVersion = ver; + }; "with-postgresql-and-redis${toString ver}" = import ./with-postgresql-and-redis.nix { inherit system pkgs; nextcloudVersion = ver; diff --git a/nixos/tests/nextcloud/openssl-sse.nix b/nixos/tests/nextcloud/openssl-sse.nix new file mode 100644 index 0000000000000..7595ee2c67e31 --- /dev/null +++ b/nixos/tests/nextcloud/openssl-sse.nix @@ -0,0 +1,105 @@ +args@{ pkgs, nextcloudVersion ? 25, ... }: + +(import ../make-test-python.nix ({ pkgs, ...}: let + adminuser = "root"; + adminpass = "notproduction"; + nextcloudBase = { + networking.firewall.allowedTCPPorts = [ 80 ]; + system.stateVersion = "22.05"; # stateVersions <22.11 use openssl 1.1 by default + services.nextcloud = { + enable = true; + config.adminpassFile = "${pkgs.writeText "adminpass" adminpass}"; + package = pkgs.${"nextcloud" + (toString nextcloudVersion)}; + }; + }; +in { + name = "nextcloud-openssl"; + meta = with pkgs.lib.maintainers; { + maintainers = [ ma27 ]; + }; + nodes.nextcloudwithopenssl1 = { + imports = [ nextcloudBase ]; + services.nextcloud.hostName = "nextcloudwithopenssl1"; + }; + nodes.nextcloudwithopenssl3 = { + imports = [ nextcloudBase ]; + services.nextcloud = { + hostName = "nextcloudwithopenssl3"; + enableBrokenCiphersForSSE = false; + }; + }; + testScript = { nodes, ... }: let + withRcloneEnv = host: pkgs.writeScript "with-rclone-env" '' + #!${pkgs.runtimeShell} + export RCLONE_CONFIG_NEXTCLOUD_TYPE=webdav + export RCLONE_CONFIG_NEXTCLOUD_URL="http://${host}/remote.php/webdav/" + export RCLONE_CONFIG_NEXTCLOUD_VENDOR="nextcloud" + export RCLONE_CONFIG_NEXTCLOUD_USER="${adminuser}" + export RCLONE_CONFIG_NEXTCLOUD_PASS="$(${pkgs.rclone}/bin/rclone obscure ${adminpass})" + "''${@}" + ''; + withRcloneEnv1 = withRcloneEnv "nextcloudwithopenssl1"; + withRcloneEnv3 = withRcloneEnv "nextcloudwithopenssl3"; + copySharedFile1 = pkgs.writeScript "copy-shared-file" '' + #!${pkgs.runtimeShell} + echo 'hi' | ${withRcloneEnv1} ${pkgs.rclone}/bin/rclone rcat nextcloud:test-shared-file + ''; + copySharedFile3 = pkgs.writeScript "copy-shared-file" '' + #!${pkgs.runtimeShell} + echo 'bye' | ${withRcloneEnv3} ${pkgs.rclone}/bin/rclone rcat nextcloud:test-shared-file2 + ''; + openssl1-node = nodes.nextcloudwithopenssl1.config.system.build.toplevel; + openssl3-node = nodes.nextcloudwithopenssl3.config.system.build.toplevel; + in '' + nextcloudwithopenssl1.start() + nextcloudwithopenssl1.wait_for_unit("multi-user.target") + nextcloudwithopenssl1.succeed("nextcloud-occ status") + nextcloudwithopenssl1.succeed("curl -sSf http://nextcloudwithopenssl1/login") + + with subtest("With OpenSSL 1 SSE can be enabled and used"): + nextcloudwithopenssl1.succeed("nextcloud-occ app:enable encryption") + nextcloudwithopenssl1.succeed("nextcloud-occ encryption:enable") + + with subtest("Upload file and ensure it's encrypted"): + nextcloudwithopenssl1.succeed("${copySharedFile1}") + nextcloudwithopenssl1.succeed("grep -E '^HBEGIN:oc_encryption_module' /var/lib/nextcloud/data/root/files/test-shared-file") + nextcloudwithopenssl1.succeed("${withRcloneEnv1} ${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file | grep hi") + + with subtest("Switch to OpenSSL 3"): + nextcloudwithopenssl1.succeed("${openssl3-node}/bin/switch-to-configuration test") + nextcloudwithopenssl1.wait_for_open_port(80) + nextcloudwithopenssl1.succeed("nextcloud-occ status") + + with subtest("Existing encrypted files cannot be read, but new files can be added"): + nextcloudwithopenssl1.fail("${withRcloneEnv3} ${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file >&2") + nextcloudwithopenssl1.succeed("nextcloud-occ encryption:disable") + nextcloudwithopenssl1.succeed("${copySharedFile3}") + nextcloudwithopenssl1.succeed("grep bye /var/lib/nextcloud/data/root/files/test-shared-file2") + nextcloudwithopenssl1.succeed("${withRcloneEnv3} ${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file2 | grep bye") + + with subtest("Switch back to OpenSSL 1.1 and ensure that encrypted files are readable again"): + nextcloudwithopenssl1.succeed("${openssl1-node}/bin/switch-to-configuration test") + nextcloudwithopenssl1.wait_for_open_port(80) + nextcloudwithopenssl1.succeed("nextcloud-occ status") + nextcloudwithopenssl1.succeed("nextcloud-occ encryption:enable") + nextcloudwithopenssl1.succeed("${withRcloneEnv1} ${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file2 | grep bye") + nextcloudwithopenssl1.succeed("${withRcloneEnv1} ${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file | grep hi") + nextcloudwithopenssl1.succeed("grep -E '^HBEGIN:oc_encryption_module' /var/lib/nextcloud/data/root/files/test-shared-file") + nextcloudwithopenssl1.succeed("grep bye /var/lib/nextcloud/data/root/files/test-shared-file2") + + with subtest("Ensure that everything can be decrypted"): + nextcloudwithopenssl1.succeed("echo y | nextcloud-occ encryption:decrypt-all >&2") + nextcloudwithopenssl1.succeed("${withRcloneEnv1} ${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file2 | grep bye") + nextcloudwithopenssl1.succeed("${withRcloneEnv1} ${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file | grep hi") + nextcloudwithopenssl1.succeed("grep -vE '^HBEGIN:oc_encryption_module' /var/lib/nextcloud/data/root/files/test-shared-file") + + with subtest("Switch to OpenSSL 3 ensure that all files are usable now"): + nextcloudwithopenssl1.succeed("${openssl3-node}/bin/switch-to-configuration test") + nextcloudwithopenssl1.wait_for_open_port(80) + nextcloudwithopenssl1.succeed("nextcloud-occ status") + nextcloudwithopenssl1.succeed("${withRcloneEnv3} ${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file2 | grep bye") + nextcloudwithopenssl1.succeed("${withRcloneEnv3} ${pkgs.rclone}/bin/rclone cat nextcloud:test-shared-file | grep hi") + + nextcloudwithopenssl1.shutdown() + ''; +})) args diff --git a/nixos/tests/phosh.nix b/nixos/tests/phosh.nix new file mode 100644 index 0000000000000..6c6357f580968 --- /dev/null +++ b/nixos/tests/phosh.nix @@ -0,0 +1,65 @@ +import ./make-test-python.nix ({ pkgs, ...}: let + pin = "1234"; +in { + name = "phosh"; + meta = with pkgs.lib.maintainers; { + maintainers = [ zhaofengli ]; + }; + + nodes = { + phone = { config, pkgs, ... }: { + users.users.nixos = { + isNormalUser = true; + password = pin; + }; + + services.xserver.desktopManager.phosh = { + enable = true; + user = "nixos"; + group = "users"; + + phocConfig = { + outputs.Virtual-1 = { + scale = 2; + }; + }; + }; + + systemd.services.phosh = { + environment = { + # Accelerated graphics fail on phoc 0.20 (wlroots 0.15) + "WLR_RENDERER" = "pixman"; + }; + }; + + virtualisation.resolution = { x = 720; y = 1440; }; + virtualisation.qemu.options = [ "-vga none -device virtio-gpu-pci,xres=720,yres=1440" ]; + }; + }; + + enableOCR = true; + + testScript = '' + import time + + start_all() + phone.wait_for_unit("phosh.service") + + with subtest("Check that we can see the lock screen info page"): + # Saturday, January 1 + phone.succeed("timedatectl set-time '2022-01-01 07:00'") + + phone.wait_for_text("Saturday") + phone.screenshot("01lockinfo") + + with subtest("Check that we can unlock the screen"): + phone.send_chars("${pin}", delay=0.2) + time.sleep(1) + phone.screenshot("02unlock") + + phone.send_chars("\n") + + phone.wait_for_text("All Apps") + phone.screenshot("03launcher") + ''; +}) diff --git a/nixos/tests/systemd-initrd-luks-password.nix b/nixos/tests/systemd-initrd-luks-password.nix index e8e651f7b35f8..55d0b4324b400 100644 --- a/nixos/tests/systemd-initrd-luks-password.nix +++ b/nixos/tests/systemd-initrd-luks-password.nix @@ -23,6 +23,8 @@ import ./make-test-python.nix ({ lib, pkgs, ... }: { cryptroot2.device = "/dev/vdd"; }; virtualisation.bootDevice = "/dev/mapper/cryptroot"; + # test mounting device unlocked in initrd after switching root + virtualisation.fileSystems."/cryptroot2".device = "/dev/mapper/cryptroot2"; }; }; @@ -31,6 +33,8 @@ import ./make-test-python.nix ({ lib, pkgs, ... }: { machine.wait_for_unit("multi-user.target") machine.succeed("echo -n supersecret | cryptsetup luksFormat -q --iter-time=1 /dev/vdc -") machine.succeed("echo -n supersecret | cryptsetup luksFormat -q --iter-time=1 /dev/vdd -") + machine.succeed("echo -n supersecret | cryptsetup luksOpen -q /dev/vdd cryptroot2") + machine.succeed("mkfs.ext4 /dev/mapper/cryptroot2") # Boot from the encrypted disk machine.succeed("bootctl set-default nixos-generation-1-specialisation-boot-luks.conf") @@ -44,5 +48,6 @@ import ./make-test-python.nix ({ lib, pkgs, ... }: { machine.wait_for_unit("multi-user.target") assert "/dev/mapper/cryptroot on / type ext4" in machine.succeed("mount") + assert "/dev/mapper/cryptroot2 on /cryptroot2 type ext4" in machine.succeed("mount") ''; }) diff --git a/nixos/tests/web-apps/mastodon.nix b/nixos/tests/web-apps/mastodon.nix index 05cc727476d67..bc1122e7268f9 100644 --- a/nixos/tests/web-apps/mastodon.nix +++ b/nixos/tests/web-apps/mastodon.nix @@ -16,7 +16,7 @@ let in { name = "mastodon"; - meta.maintainers = with pkgs.lib.maintainers; [ erictapen izorkin ]; + meta.maintainers = with pkgs.lib.maintainers; [ erictapen izorkin turion ]; nodes = { ca = { pkgs, ... }: { @@ -56,6 +56,9 @@ in }; server = { pkgs, ... }: { + + virtualisation.memorySize = 2048; + networking = { interfaces.eth1 = { ipv4.addresses = [ |