Project import generated by Copybara.

GitOrigin-RevId: 5aba0fe9766a7201a336249fd6cb76e0d7ba2faf
This commit is contained in:
Default email 2020-09-24 23:45:31 -05:00
parent ae0eda1ba8
commit 58f8944c92
3325 changed files with 104557 additions and 56443 deletions

View file

@ -57,10 +57,13 @@ indent_size = unset
[deps.nix] [deps.nix]
insert_final_newline = unset insert_final_newline = unset
[eggs.nix]
trim_trailing_whitespace = unset
[gemset.nix] [gemset.nix]
insert_final_newline = unset insert_final_newline = unset
[node-packages.nix] [node-{composition,packages}.nix]
insert_final_newline = unset insert_final_newline = unset
[nixos/modules/services/networking/ircd-hybrid/*.{conf,in}] [nixos/modules/services/networking/ircd-hybrid/*.{conf,in}]
@ -102,5 +105,15 @@ insert_final_newline = unset
indent_size = unset indent_size = unset
trim_trailing_whitespace = unset trim_trailing_whitespace = unset
[pkgs/tools/misc/timidity/timidity.cfg]
trim_trailing_whitespace = unset
[pkgs/tools/security/enpass/data.json]
insert_final_newline = unset
trim_trailing_whitespace = unset
[pkgs/top-level/emscripten-packages.nix]
trim_trailing_whitespace = unset
[pkgs/top-level/perl-packages.nix] [pkgs/top-level/perl-packages.nix]
indent_size = unset indent_size = unset

View file

@ -83,9 +83,9 @@
/pkgs/development/haskell-modules/hoogle.nix @cdepillabout /pkgs/development/haskell-modules/hoogle.nix @cdepillabout
# Perl # Perl
/pkgs/development/interpreters/perl @volth /pkgs/development/interpreters/perl @volth @stigtsp
/pkgs/top-level/perl-packages.nix @volth /pkgs/top-level/perl-packages.nix @volth @stigtsp
/pkgs/development/perl-modules @volth /pkgs/development/perl-modules @volth @stigtsp
# R # R
/pkgs/applications/science/math/R @peti /pkgs/applications/science/math/R @peti
@ -195,10 +195,11 @@
/pkgs/top-level/php-packages.nix @NixOS/php /pkgs/top-level/php-packages.nix @NixOS/php
# Podman, CRI-O modules and related # Podman, CRI-O modules and related
/nixos/modules/virtualisation/containers.nix @NixOS/podman /nixos/modules/virtualisation/containers.nix @NixOS/podman @zowoq
/nixos/modules/virtualisation/cri-o.nix @NixOS/podman /nixos/modules/virtualisation/cri-o.nix @NixOS/podman @zowoq
/nixos/modules/virtualisation/podman.nix @NixOS/podman /nixos/modules/virtualisation/podman.nix @NixOS/podman @zowoq
/nixos/tests/podman.nix @NixOS/podman /nixos/tests/cri-o.nix @NixOS/podman @zowoq
/nixos/tests/podman.nix @NixOS/podman @zowoq
# Blockchains # Blockchains
/pkgs/applications/blockchains @mmahut /pkgs/applications/blockchains @mmahut

View file

@ -55,7 +55,7 @@ Follow these steps to backport a change into a release branch in compliance with
1. Take note of the commits in which the change was introduced into `master` branch. 1. Take note of the commits in which the change was introduced into `master` branch.
2. Check out the target _release branch_, e.g. `release-20.03`. Do not use a _channel branch_ like `nixos-20.03` or `nixpkgs-20.03`. 2. Check out the target _release branch_, e.g. `release-20.03`. Do not use a _channel branch_ like `nixos-20.03` or `nixpkgs-20.03`.
3. Create a branch for your change, e.g. `git checkout -b backport`. 3. Create a branch for your change, e.g. `git checkout -b backport`.
4. When the reason to backport is not obvious from the original commit message, use `git cherry-pick -xe <original commit>` and add a reason. Otherwise use `git cherry-pick -x <original commit>`. That's fine for minor version updates that only include security and bug fixes, commits that fixes an otherwise broken package or similar. 4. When the reason to backport is not obvious from the original commit message, use `git cherry-pick -xe <original commit>` and add a reason. Otherwise use `git cherry-pick -x <original commit>`. That's fine for minor version updates that only include security and bug fixes, commits that fixes an otherwise broken package or similar. Please also ensure the commits exists on the master branch; in the case of squashed or rebased merges, the commit hash will change and the new commits can be found in the merge message at the bottom of the master pull request.
5. Push to GitHub and open a backport pull request. Make sure to select the release branch (e.g. `release-20.03`) as the target branch of the pull request, and link to the pull request in which the original change was comitted to `master`. The pull request title should be the commit title with the release version as prefix, e.g. `[20.03]`. 5. Push to GitHub and open a backport pull request. Make sure to select the release branch (e.g. `release-20.03`) as the target branch of the pull request, and link to the pull request in which the original change was comitted to `master`. The pull request title should be the commit title with the release version as prefix, e.g. `[20.03]`.
## Reviewing contributions ## Reviewing contributions

View file

@ -0,0 +1,27 @@
name: "Checking EditorConfig"
on:
pull_request:
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: technote-space/get-diff-action@v3.1.0
- name: Fetch editorconfig-checker
if: env.GIT_DIFF
env:
ECC_VERSION: "2.1.0"
ECC_URL: "https://github.com/editorconfig-checker/editorconfig-checker/releases/download"
run: |
curl -sSf -O -L -C - "$ECC_URL/$ECC_VERSION/ec-linux-amd64.tar.gz" && \
tar xzf ec-linux-amd64.tar.gz && \
mv ./bin/ec-linux-amd64 ./bin/editorconfig-checker
- name: Checking EditorConfig
if: env.GIT_DIFF
run: |
./bin/editorconfig-checker -disable-indentation \
${{ env.GIT_DIFF }}

View file

@ -0,0 +1,21 @@
name: "clear pending status"
on:
check_suite:
types: [ completed ]
jobs:
action:
runs-on: ubuntu-latest
steps:
- name: clear pending status
if: github.repository_owner == 'NixOS' && github.event.check_suite.app.name == 'OfBorg'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
curl \
-X POST \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token $GITHUB_TOKEN" \
-d '{"state": "success", "target_url": " ", "description": " ", "context": "Wait for ofborg"}' \
"https://api.github.com/repos/NixOS/nixpkgs/statuses/${{ github.event.check_suite.head_sha }}"

View file

@ -0,0 +1,20 @@
name: "set pending status"
on:
pull_request_target:
jobs:
action:
runs-on: ubuntu-latest
steps:
- name: set pending status
if: github.repository_owner == 'NixOS'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
curl \
-X POST \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token $GITHUB_TOKEN" \
-d '{"state": "failure", "target_url": " ", "description": "This failed status will be cleared when ofborg finishes eval.", "context": "Wait for ofborg"}' \
"https://api.github.com/repos/NixOS/nixpkgs/statuses/${{ github.event.pull_request.head.sha }}"

View file

@ -1 +1 @@
20.09 21.03

View file

@ -132,11 +132,11 @@ buildImage {
<para> <para>
By default <function>buildImage</function> will use a static date of one second past the UNIX Epoch. This allows <function>buildImage</function> to produce binary reproducible images. When listing images with <command>docker images</command>, the newly created images will be listed like this: By default <function>buildImage</function> will use a static date of one second past the UNIX Epoch. This allows <function>buildImage</function> to produce binary reproducible images. When listing images with <command>docker images</command>, the newly created images will be listed like this:
</para> </para>
<screen><![CDATA[ <screen>
$ docker images <prompt>$ </prompt>docker images
REPOSITORY TAG IMAGE ID CREATED SIZE REPOSITORY TAG IMAGE ID CREATED SIZE
hello latest 08c791c7846e 48 years ago 25.2MB hello latest 08c791c7846e 48 years ago 25.2MB
]]></screen> </screen>
<para> <para>
You can break binary reproducibility but have a sorted, meaningful <literal>CREATED</literal> column by setting <literal>created</literal> to <literal>now</literal>. You can break binary reproducibility but have a sorted, meaningful <literal>CREATED</literal> column by setting <literal>created</literal> to <literal>now</literal>.
</para> </para>
@ -152,11 +152,11 @@ pkgs.dockerTools.buildImage {
]]></programlisting> ]]></programlisting>
<para> <para>
and now the Docker CLI will display a reasonable date and sort the images as expected: and now the Docker CLI will display a reasonable date and sort the images as expected:
<screen><![CDATA[ <screen>
$ docker images <prompt>$ </prompt>docker images
REPOSITORY TAG IMAGE ID CREATED SIZE REPOSITORY TAG IMAGE ID CREATED SIZE
hello latest de2bf4786de6 About a minute ago 25.2MB hello latest de2bf4786de6 About a minute ago 25.2MB
]]></screen> </screen>
however, the produced images will not be binary reproducible. however, the produced images will not be binary reproducible.
</para> </para>
</example> </example>

View file

@ -38,8 +38,7 @@ buildContainer {
readonly = false; <co xml:id='ex-ociTools-buildContainer-3' /> readonly = false; <co xml:id='ex-ociTools-buildContainer-3' />
} }
</programlisting>
</programlisting>
<calloutlist> <calloutlist>
<callout arearefs='ex-ociTools-buildContainer-1'> <callout arearefs='ex-ociTools-buildContainer-1'>
<para> <para>

View file

@ -22,10 +22,10 @@
</para> </para>
<para> <para>
In order to set this up, you first have to <link xlink:href="https://its.uiowa.edu/support/article/102186">download the <literal>.cr</literal> file from the Netscaler Gateway</link>. After that you can configure the <command>selfservice</command> like this: In order to set this up, you first have to <link xlink:href="https://its.uiowa.edu/support/article/102186">download the <literal>.cr</literal> file from the Netscaler Gateway</link>. After that you can configure the <command>selfservice</command> like this:
<screen> <screen>
<prompt>$ </prompt>storebrowse -C ~/Downloads/receiverconfig.cr <prompt>$ </prompt>storebrowse -C ~/Downloads/receiverconfig.cr
<prompt>$ </prompt>selfservice <prompt>$ </prompt>selfservice
</screen> </screen>
</para> </para>
</section> </section>

View file

@ -18,10 +18,13 @@
includes all available plugins. To make use of this functionality, use an includes all available plugins. To make use of this functionality, use an
overlay or directly install an expression that overrides its configuration, overlay or directly install an expression that overrides its configuration,
such as such as
<programlisting>rxvt-unicode.override { configure = { availablePlugins, ... }: { <programlisting>
rxvt-unicode.override {
configure = { availablePlugins, ... }: {
plugins = with availablePlugins; [ perls resize-font vtwheel ]; plugins = with availablePlugins; [ perls resize-font vtwheel ];
} };
}</programlisting> }
</programlisting>
If the <literal>configure</literal> function returns an attrset without the If the <literal>configure</literal> function returns an attrset without the
<literal>plugins</literal> attribute, <literal>availablePlugins</literal> <literal>plugins</literal> attribute, <literal>availablePlugins</literal>
will be used automatically. will be used automatically.
@ -30,18 +33,22 @@
<para> <para>
In order to add plugins but also keep all default plugins installed, it is In order to add plugins but also keep all default plugins installed, it is
possible to use the following method: possible to use the following method:
<programlisting>rxvt-unicode.override { configure = { availablePlugins, ... }: { <programlisting>
plugins = (builtins.attrValues availablePlugins) ++ [ custom-plugin ]; rxvt-unicode.override {
}; configure = { availablePlugins, ... }: {
}</programlisting> plugins = (builtins.attrValues availablePlugins) ++ [ custom-plugin ];
};
}
</programlisting>
</para> </para>
<para> <para>
To get a list of all the plugins available, open the Nix REPL and run To get a list of all the plugins available, open the Nix REPL and run
<programlisting>$ nix repl <screen>
<prompt>$ </prompt>nix repl
:l &lt;nixpkgs&gt; :l &lt;nixpkgs&gt;
map (p: p.name) pkgs.rxvt-unicode.plugins map (p: p.name) pkgs.rxvt-unicode.plugins
</programlisting> </screen>
Alternatively, if your shell is bash or zsh and have completion enabled, Alternatively, if your shell is bash or zsh and have completion enabled,
simply type <literal>nixpkgs.rxvt-unicode.plugins.&lt;tab&gt;</literal>. simply type <literal>nixpkgs.rxvt-unicode.plugins.&lt;tab&gt;</literal>.
</para> </para>
@ -53,18 +60,24 @@ map (p: p.name) pkgs.rxvt-unicode.plugins
<literal>extraDeps</literal> can be used, for example, to provide <literal>extraDeps</literal> can be used, for example, to provide
<literal>xsel</literal> (a clipboard manager) to the clipboard plugin, <literal>xsel</literal> (a clipboard manager) to the clipboard plugin,
without installing it globally: without installing it globally:
<programlisting>rxvt-unicode.override { configure = { availablePlugins, ... }: { <programlisting>
pluginsDeps = [ xsel ]; rxvt-unicode.override {
} configure = { availablePlugins, ... }: {
}</programlisting> pluginsDeps = [ xsel ];
};
}
</programlisting>
<literal>perlDeps</literal> is a handy way to provide Perl packages to <literal>perlDeps</literal> is a handy way to provide Perl packages to
your custom plugins (in <literal>$HOME/.urxvt/ext</literal>). For example, your custom plugins (in <literal>$HOME/.urxvt/ext</literal>). For example,
if you need <literal>AnyEvent</literal> you can do: if you need <literal>AnyEvent</literal> you can do:
<programlisting>rxvt-unicode.override { configure = { availablePlugins, ... }: { <programlisting>
perlDeps = with perlPackages; [ AnyEvent ]; rxvt-unicode.override {
} configure = { availablePlugins, ... }: {
}</programlisting> perlDeps = with perlPackages; [ AnyEvent ];
};
}
</programlisting>
</para> </para>
</section> </section>
@ -90,7 +103,8 @@ map (p: p.name) pkgs.rxvt-unicode.plugins
<para> <para>
If the plugin is itself a perl package that needs to be imported from If the plugin is itself a perl package that needs to be imported from
other plugins or scripts, add the following passthrough: other plugins or scripts, add the following passthrough:
<programlisting>passthru.perlPackages = [ "self" ]; <programlisting>
passthru.perlPackages = [ "self" ];
</programlisting> </programlisting>
This will make the urxvt wrapper pick up the dependency and set up the perl This will make the urxvt wrapper pick up the dependency and set up the perl
path accordingly. path accordingly.

View file

@ -209,12 +209,12 @@ Additional information.
</para> </para>
<programlisting> <programlisting>
(fetchpatch { (fetchpatch {
name = "CVE-2019-11068.patch"; name = "CVE-2019-11068.patch";
url = "https://gitlab.gnome.org/GNOME/libxslt/commit/e03553605b45c88f0b4b2980adfbbb8f6fca2fd6.patch"; url = "https://gitlab.gnome.org/GNOME/libxslt/commit/e03553605b45c88f0b4b2980adfbbb8f6fca2fd6.patch";
sha256 = "0pkpb4837km15zgg6h57bncp66d5lwrlvkr73h0lanywq7zrwhj8"; sha256 = "0pkpb4837km15zgg6h57bncp66d5lwrlvkr73h0lanywq7zrwhj8";
}) })
</programlisting> </programlisting>
<para> <para>
If a security fix applies to both master and a stable release then, similar to regular changes, they are preferably delivered via master first and cherry-picked to the release branch. If a security fix applies to both master and a stable release then, similar to regular changes, they are preferably delivered via master first and cherry-picked to the release branch.

View file

@ -72,9 +72,9 @@
To install any of those builders into your profile, refer to them by their attribute path <literal>beamPackages.rebar3</literal>: To install any of those builders into your profile, refer to them by their attribute path <literal>beamPackages.rebar3</literal>:
</para> </para>
<screen> <screen>
<prompt>$ </prompt>nix-env -f &quot;&lt;nixpkgs&gt;&quot; -iA beamPackages.rebar3 <prompt>$ </prompt>nix-env -f &quot;&lt;nixpkgs&gt;&quot; -iA beamPackages.rebar3
</screen> </screen>
</section> </section>
<section xml:id="packaging-beam-applications"> <section xml:id="packaging-beam-applications">

View file

@ -38,11 +38,7 @@ pet = buildGoModule rec {
vendorSha256 = "1879j77k96684wi554rkjxydrj8g3hpp0kvxz03sd8dmwr3lh83j"; <co xml:id='ex-buildGoModule-1' /> vendorSha256 = "1879j77k96684wi554rkjxydrj8g3hpp0kvxz03sd8dmwr3lh83j"; <co xml:id='ex-buildGoModule-1' />
subPackages = [ "." ]; <co xml:id='ex-buildGoModule-2' /> runVend = true; <co xml:id='ex-buildGoModule-2' />
deleteVendor = true; <co xml:id='ex-buildGoModule-3' />
runVend = true; <co xml:id='ex-buildGoModule-4' />
meta = with lib; { meta = with lib; {
description = "Simple command-line snippet manager, written in Go"; description = "Simple command-line snippet manager, written in Go";
@ -64,16 +60,6 @@ pet = buildGoModule rec {
</para> </para>
</callout> </callout>
<callout arearefs='ex-buildGoModule-2'> <callout arearefs='ex-buildGoModule-2'>
<para>
<varname>subPackages</varname> limits the builder from building child packages that have not been listed. If <varname>subPackages</varname> is not specified, all child packages will be built.
</para>
</callout>
<callout arearefs='ex-buildGoModule-3'>
<para>
<varname>deleteVendor</varname> removes the pre-existing vendor directory and fetches the dependencies. This should only be used if the dependencies included in the vendor folder are broken or incomplete.
</para>
</callout>
<callout arearefs='ex-buildGoModule-4'>
<para> <para>
<varname>runVend</varname> runs the vend command to generate the vendor directory. This is useful if your code depends on c code and go mod tidy does not include the needed sources to build. <varname>runVend</varname> runs the vend command to generate the vendor directory. This is useful if your code depends on c code and go mod tidy does not include the needed sources to build.
</para> </para>
@ -82,12 +68,7 @@ pet = buildGoModule rec {
</para> </para>
<para> <para>
<varname>vendorSha256</varname> can also take <varname>null</varname> as an input. <varname>vendorSha256</varname> can also take <varname>null</varname> as an input. When `null` is used as a value, rather than fetching the dependencies and vendoring them, we use the vendoring included within the source repo. If you'd like to not have to update this field on dependency changes, run `go mod vendor` in your source repo and set 'vendorSha256 = null;'
When `null` is used as a value, rather than fetching the dependencies
and vendoring them, we use the vendoring included within the source repo.
If you'd like to not have to update this field on dependency changes,
run `go mod vendor` in your source repo and set 'vendorSha256 = null;'
</para> </para>
</section> </section>
@ -106,7 +87,6 @@ deis = buildGoPackage rec {
version = "1.13.0"; version = "1.13.0";
goPackagePath = "github.com/deis/deis"; <co xml:id='ex-buildGoPackage-1' /> goPackagePath = "github.com/deis/deis"; <co xml:id='ex-buildGoPackage-1' />
subPackages = [ "client" ]; <co xml:id='ex-buildGoPackage-2' />
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "deis"; owner = "deis";
@ -115,9 +95,7 @@ deis = buildGoPackage rec {
sha256 = "1qv9lxqx7m18029lj8cw3k7jngvxs4iciwrypdy0gd2nnghc68sw"; sha256 = "1qv9lxqx7m18029lj8cw3k7jngvxs4iciwrypdy0gd2nnghc68sw";
}; };
goDeps = ./deps.nix; <co xml:id='ex-buildGoPackage-3' /> goDeps = ./deps.nix; <co xml:id='ex-buildGoPackage-2' />
buildFlags = [ "--tags" "release" ]; <co xml:id='ex-buildGoPackage-4' />
} }
</programlisting> </programlisting>
</example> </example>
@ -131,23 +109,10 @@ deis = buildGoPackage rec {
</para> </para>
</callout> </callout>
<callout arearefs='ex-buildGoPackage-2'> <callout arearefs='ex-buildGoPackage-2'>
<para>
<varname>subPackages</varname> limits the builder from building child packages that have not been listed. If <varname>subPackages</varname> is not specified, all child packages will be built.
</para>
<para>
In this example only <literal>github.com/deis/deis/client</literal> will be built.
</para>
</callout>
<callout arearefs='ex-buildGoPackage-3'>
<para> <para>
<varname>goDeps</varname> is where the Go dependencies of a Go program are listed as a list of package source identified by Go import path. It could be imported as a separate <varname>deps.nix</varname> file for readability. The dependency data structure is described below. <varname>goDeps</varname> is where the Go dependencies of a Go program are listed as a list of package source identified by Go import path. It could be imported as a separate <varname>deps.nix</varname> file for readability. The dependency data structure is described below.
</para> </para>
</callout> </callout>
<callout arearefs='ex-buildGoPackage-4'>
<para>
<varname>buildFlags</varname> is a list of flags passed to the go build command.
</para>
</callout>
</calloutlist> </calloutlist>
</para> </para>
@ -214,4 +179,70 @@ done
</screen> </screen>
</para> </para>
</section> </section>
<section xml:id="ssec-go-common-attributes">
<title>Attributes used by the builders</title>
<para>
Both <link xlink:href="#ssec-go-modules"><varname>buildGoModule</varname></link> and <link xlink:href="#ssec-go-modules"><varname>buildGoPackage</varname></link> can be tweaked to behave slightly differently, if the following attributes are used:
</para>
<variablelist>
<varlistentry xml:id="var-go-buildFlagsArray">
<term>
<varname>buildFlagsArray</varname> and <varname>buildFlags</varname>
</term>
<listitem>
<para>
These attributes set build flags supported by <varname>go build</varname>. We recommend using <varname>buildFlagsArray</varname>. The most common use case of these attributes is to make the resulting executable aware of its own version. For example:
</para>
<example xml:id='ex-goBuildFlags-nospaces'>
<title>buildFlagsArray</title>
<programlisting>
buildFlagsArray = [
"-ldflags=-X main.Version=${version} -X main.Commit=${version}" <co xml:id='ex-goBuildFlags-1' />
];
</programlisting>
</example>
<calloutlist>
<callout arearefs='ex-goBuildFlags-1'>
<para>
Note: single quotes are not needed.
</para>
</callout>
</calloutlist>
<example xml:id='ex-goBuildFlags-noarray'>
<title>buildFlagsArray</title>
<programlisting>
buildFlagsArray = ''
-ldflags=
-X main.Version=${version}
-X main.Commit=${version}
'';
</programlisting>
</example>
</listitem>
</varlistentry>
<varlistentry xml:id="var-go-deleteVendor">
<term>
<varname>deleteVendor</varname>
</term>
<listitem>
<para>
Removes the pre-existing vendor directory. This should only be used if the dependencies included in the vendor folder are broken or incomplete.
</para>
</listitem>
</varlistentry>
<varlistentry xml:id="var-go-subPackages">
<term>
<varname>subPackages</varname>
</term>
<listitem>
<para>
Limits the builder from building child packages that have not been listed. If <varname>subPackages</varname> is not specified, all child packages will be built.
</para>
</listitem>
</varlistentry>
</variablelist>
</section>
</section> </section>

View file

@ -25,12 +25,13 @@ build system it uses. Here are some examples:
After you have identified the correct system, you need to override your package After you have identified the correct system, you need to override your package
expression while adding in build system as a build input. For example, `dat` expression while adding in build system as a build input. For example, `dat`
requires `node-gyp-build`, so we override its expression in `default.nix`: requires `node-gyp-build`, so [we override](https://github.com/NixOS/nixpkgs/blob/32f5e5da4a1b3f0595527f5195ac3a91451e9b56/pkgs/development/node-packages/default.nix#L37-L40) its expression in [`default.nix`](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/node-packages/default.nix):
```nix ```nix
dat = nodePackages.dat.override (oldAttrs: { dat = super.dat.override {
buildInputs = oldAttrs.buildInputs ++ [ nodePackages.node-gyp-build ]; buildInputs = [ self.node-gyp-build pkgs.libtool pkgs.autoconf pkgs.automake ];
}); meta.broken = since "12";
};
``` ```
To add a package from NPM to nixpkgs: To add a package from NPM to nixpkgs:

View file

@ -8,28 +8,28 @@
<para> <para>
When executing a Perl script, it is possible you get an error such as <literal>./myscript.pl: bad interpreter: /usr/bin/perl: no such file or directory</literal>. This happens when the script expects Perl to be installed at <filename>/usr/bin/perl</filename>, which is not the case when using Perl from nixpkgs. You can fix the script by changing the first line to: When executing a Perl script, it is possible you get an error such as <literal>./myscript.pl: bad interpreter: /usr/bin/perl: no such file or directory</literal>. This happens when the script expects Perl to be installed at <filename>/usr/bin/perl</filename>, which is not the case when using Perl from nixpkgs. You can fix the script by changing the first line to:
<programlisting> <programlisting>
#!/usr/bin/env perl #!/usr/bin/env perl
</programlisting> </programlisting>
to take the Perl installation from the <literal>PATH</literal> environment variable, or invoke Perl directly with: to take the Perl installation from the <literal>PATH</literal> environment variable, or invoke Perl directly with:
<screen> <screen>
<prompt>$ </prompt>perl ./myscript.pl <prompt>$ </prompt>perl ./myscript.pl
</screen> </screen>
</para> </para>
<para> <para>
When the script is using a Perl library that is not installed globally, you might get an error such as <literal>Can't locate DB_File.pm in @INC (you may need to install the DB_File module)</literal>. In that case, you can use <command>nix-shell</command> to start an ad-hoc shell with that library installed, for instance: When the script is using a Perl library that is not installed globally, you might get an error such as <literal>Can't locate DB_File.pm in @INC (you may need to install the DB_File module)</literal>. In that case, you can use <command>nix-shell</command> to start an ad-hoc shell with that library installed, for instance:
<screen> <screen>
<prompt>$ </prompt>nix-shell -p perl perlPackages.DBFile --run ./myscript.pl <prompt>$ </prompt>nix-shell -p perl perlPackages.DBFile --run ./myscript.pl
</screen> </screen>
</para> </para>
<para> <para>
If you are always using the script in places where <command>nix-shell</command> is available, you can embed the <command>nix-shell</command> invocation in the shebang like this: If you are always using the script in places where <command>nix-shell</command> is available, you can embed the <command>nix-shell</command> invocation in the shebang like this:
<programlisting> <programlisting>
#!/usr/bin/env nix-shell #!/usr/bin/env nix-shell
#! nix-shell -i perl -p perl perlPackages.DBFile #! nix-shell -i perl -p perl perlPackages.DBFile
</programlisting> </programlisting>
</para> </para>
</section> </section>
@ -44,30 +44,30 @@
<para> <para>
Perl packages from CPAN are defined in <link Perl packages from CPAN are defined in <link
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/perl-packages.nix"><filename>pkgs/top-level/perl-packages.nix</filename></link>, rather than <filename>pkgs/all-packages.nix</filename>. Most Perl packages are so straight-forward to build that they are defined here directly, rather than having a separate function for each package called from <filename>perl-packages.nix</filename>. However, more complicated packages should be put in a separate file, typically in <filename>pkgs/development/perl-modules</filename>. Here is an example of the former: xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/perl-packages.nix"><filename>pkgs/top-level/perl-packages.nix</filename></link>, rather than <filename>pkgs/all-packages.nix</filename>. Most Perl packages are so straight-forward to build that they are defined here directly, rather than having a separate function for each package called from <filename>perl-packages.nix</filename>. However, more complicated packages should be put in a separate file, typically in <filename>pkgs/development/perl-modules</filename>. Here is an example of the former:
<programlisting> <programlisting>
ClassC3 = buildPerlPackage rec { ClassC3 = buildPerlPackage rec {
name = "Class-C3-0.21"; name = "Class-C3-0.21";
src = fetchurl { src = fetchurl {
url = "mirror://cpan/authors/id/F/FL/FLORA/${name}.tar.gz"; url = "mirror://cpan/authors/id/F/FL/FLORA/${name}.tar.gz";
sha256 = "1bl8z095y4js66pwxnm7s853pi9czala4sqc743fdlnk27kq94gz"; sha256 = "1bl8z095y4js66pwxnm7s853pi9czala4sqc743fdlnk27kq94gz";
}; };
}; };
</programlisting> </programlisting>
Note the use of <literal>mirror://cpan/</literal>, and the <literal>${name}</literal> in the URL definition to ensure that the name attribute is consistent with the source that were actually downloading. Perl packages are made available in <filename>all-packages.nix</filename> through the variable <varname>perlPackages</varname>. For instance, if you have a package that needs <varname>ClassC3</varname>, you would typically write Note the use of <literal>mirror://cpan/</literal>, and the <literal>${name}</literal> in the URL definition to ensure that the name attribute is consistent with the source that were actually downloading. Perl packages are made available in <filename>all-packages.nix</filename> through the variable <varname>perlPackages</varname>. For instance, if you have a package that needs <varname>ClassC3</varname>, you would typically write
<programlisting> <programlisting>
foo = import ../path/to/foo.nix { foo = import ../path/to/foo.nix {
inherit stdenv fetchurl ...; inherit stdenv fetchurl ...;
inherit (perlPackages) ClassC3; inherit (perlPackages) ClassC3;
}; };
</programlisting> </programlisting>
in <filename>all-packages.nix</filename>. You can test building a Perl package as follows: in <filename>all-packages.nix</filename>. You can test building a Perl package as follows:
<screen> <screen>
<prompt>$ </prompt>nix-build -A perlPackages.ClassC3 <prompt>$ </prompt>nix-build -A perlPackages.ClassC3
</screen> </screen>
<varname>buildPerlPackage</varname> adds <literal>perl-</literal> to the start of the name attribute, so the package above is actually called <literal>perl-Class-C3-0.21</literal>. So to install it, you can say: <varname>buildPerlPackage</varname> adds <literal>perl-</literal> to the start of the name attribute, so the package above is actually called <literal>perl-Class-C3-0.21</literal>. So to install it, you can say:
<screen> <screen>
<prompt>$ </prompt>nix-env -i perl-Class-C3 <prompt>$ </prompt>nix-env -i perl-Class-C3
</screen> </screen>
(Of course you can also install using the attribute name: <literal>nix-env -i -A perlPackages.ClassC3</literal>.) (Of course you can also install using the attribute name: <literal>nix-env -i -A perlPackages.ClassC3</literal>.)
</para> </para>
@ -94,61 +94,61 @@
<para> <para>
<varname>buildPerlPackage</varname> is built on top of <varname>stdenv</varname>, so everything can be customised in the usual way. For instance, the <literal>BerkeleyDB</literal> module has a <varname>preConfigure</varname> hook to generate a configuration file used by <filename>Makefile.PL</filename>: <varname>buildPerlPackage</varname> is built on top of <varname>stdenv</varname>, so everything can be customised in the usual way. For instance, the <literal>BerkeleyDB</literal> module has a <varname>preConfigure</varname> hook to generate a configuration file used by <filename>Makefile.PL</filename>:
<programlisting> <programlisting>
{ buildPerlPackage, fetchurl, db }: { buildPerlPackage, fetchurl, db }:
buildPerlPackage rec { buildPerlPackage rec {
name = "BerkeleyDB-0.36"; name = "BerkeleyDB-0.36";
src = fetchurl { src = fetchurl {
url = "mirror://cpan/authors/id/P/PM/PMQS/${name}.tar.gz"; url = "mirror://cpan/authors/id/P/PM/PMQS/${name}.tar.gz";
sha256 = "07xf50riarb60l1h6m2dqmql8q5dij619712fsgw7ach04d8g3z1"; sha256 = "07xf50riarb60l1h6m2dqmql8q5dij619712fsgw7ach04d8g3z1";
}; };
preConfigure = '' preConfigure = ''
echo "LIB = ${db.out}/lib" > config.in echo "LIB = ${db.out}/lib" > config.in
echo "INCLUDE = ${db.dev}/include" >> config.in echo "INCLUDE = ${db.dev}/include" >> config.in
''; '';
} }
</programlisting> </programlisting>
</para> </para>
<para> <para>
Dependencies on other Perl packages can be specified in the <varname>buildInputs</varname> and <varname>propagatedBuildInputs</varname> attributes. If something is exclusively a build-time dependency, use <varname>buildInputs</varname>; if its (also) a runtime dependency, use <varname>propagatedBuildInputs</varname>. For instance, this builds a Perl module that has runtime dependencies on a bunch of other modules: Dependencies on other Perl packages can be specified in the <varname>buildInputs</varname> and <varname>propagatedBuildInputs</varname> attributes. If something is exclusively a build-time dependency, use <varname>buildInputs</varname>; if its (also) a runtime dependency, use <varname>propagatedBuildInputs</varname>. For instance, this builds a Perl module that has runtime dependencies on a bunch of other modules:
<programlisting> <programlisting>
ClassC3Componentised = buildPerlPackage rec { ClassC3Componentised = buildPerlPackage rec {
name = "Class-C3-Componentised-1.0004"; name = "Class-C3-Componentised-1.0004";
src = fetchurl { src = fetchurl {
url = "mirror://cpan/authors/id/A/AS/ASH/${name}.tar.gz"; url = "mirror://cpan/authors/id/A/AS/ASH/${name}.tar.gz";
sha256 = "0xql73jkcdbq4q9m0b0rnca6nrlvf5hyzy8is0crdk65bynvs8q1"; sha256 = "0xql73jkcdbq4q9m0b0rnca6nrlvf5hyzy8is0crdk65bynvs8q1";
}; };
propagatedBuildInputs = [ propagatedBuildInputs = [
ClassC3 ClassInspector TestException MROCompat ClassC3 ClassInspector TestException MROCompat
]; ];
}; };
</programlisting> </programlisting>
</para> </para>
<para> <para>
On Darwin, if a script has too many <literal>-I<replaceable>dir</replaceable></literal> flags in its first line (its “shebang line”), it will not run. This can be worked around by calling the <literal>shortenPerlShebang</literal> function from the <literal>postInstall</literal> phase: On Darwin, if a script has too many <literal>-I<replaceable>dir</replaceable></literal> flags in its first line (its “shebang line”), it will not run. This can be worked around by calling the <literal>shortenPerlShebang</literal> function from the <literal>postInstall</literal> phase:
<programlisting> <programlisting>
{ stdenv, buildPerlPackage, fetchurl, shortenPerlShebang }: { stdenv, buildPerlPackage, fetchurl, shortenPerlShebang }:
ImageExifTool = buildPerlPackage { ImageExifTool = buildPerlPackage {
pname = "Image-ExifTool"; pname = "Image-ExifTool";
version = "11.50"; version = "11.50";
src = fetchurl { src = fetchurl {
url = "https://www.sno.phy.queensu.ca/~phil/exiftool/Image-ExifTool-11.50.tar.gz"; url = "https://www.sno.phy.queensu.ca/~phil/exiftool/Image-ExifTool-11.50.tar.gz";
sha256 = "0d8v48y94z8maxkmw1rv7v9m0jg2dc8xbp581njb6yhr7abwqdv3"; sha256 = "0d8v48y94z8maxkmw1rv7v9m0jg2dc8xbp581njb6yhr7abwqdv3";
}; };
buildInputs = stdenv.lib.optional stdenv.isDarwin shortenPerlShebang; buildInputs = stdenv.lib.optional stdenv.isDarwin shortenPerlShebang;
postInstall = stdenv.lib.optional stdenv.isDarwin '' postInstall = stdenv.lib.optional stdenv.isDarwin ''
shortenPerlShebang $out/bin/exiftool shortenPerlShebang $out/bin/exiftool
''; '';
}; };
</programlisting> </programlisting>
This will remove the <literal>-I</literal> flags from the shebang line, rewrite them in the <literal>use lib</literal> form, and put them on the next line instead. This function can be given any number of Perl scripts as arguments; it will modify them in-place. This will remove the <literal>-I</literal> flags from the shebang line, rewrite them in the <literal>use lib</literal> form, and put them on the next line instead. This function can be given any number of Perl scripts as arguments; it will modify them in-place.
</para> </para>
@ -159,27 +159,27 @@
Nix expressions for Perl packages can be generated (almost) automatically from CPAN. This is done by the program <command>nix-generate-from-cpan</command>, which can be installed as follows: Nix expressions for Perl packages can be generated (almost) automatically from CPAN. This is done by the program <command>nix-generate-from-cpan</command>, which can be installed as follows:
</para> </para>
<screen> <screen>
<prompt>$ </prompt>nix-env -i nix-generate-from-cpan <prompt>$ </prompt>nix-env -i nix-generate-from-cpan
</screen> </screen>
<para> <para>
This program takes a Perl module name, looks it up on CPAN, fetches and unpacks the corresponding package, and prints a Nix expression on standard output. For example: This program takes a Perl module name, looks it up on CPAN, fetches and unpacks the corresponding package, and prints a Nix expression on standard output. For example:
<screen> <screen>
<prompt>$ </prompt>nix-generate-from-cpan XML::Simple <prompt>$ </prompt>nix-generate-from-cpan XML::Simple
XMLSimple = buildPerlPackage rec { XMLSimple = buildPerlPackage rec {
name = "XML-Simple-2.22"; name = "XML-Simple-2.22";
src = fetchurl { src = fetchurl {
url = "mirror://cpan/authors/id/G/GR/GRANTM/${name}.tar.gz"; url = "mirror://cpan/authors/id/G/GR/GRANTM/${name}.tar.gz";
sha256 = "b9450ef22ea9644ae5d6ada086dc4300fa105be050a2030ebd4efd28c198eb49"; sha256 = "b9450ef22ea9644ae5d6ada086dc4300fa105be050a2030ebd4efd28c198eb49";
}; };
propagatedBuildInputs = [ XMLNamespaceSupport XMLSAX XMLSAXExpat ]; propagatedBuildInputs = [ XMLNamespaceSupport XMLSAX XMLSAXExpat ];
meta = { meta = {
description = "An API for simple XML files"; description = "An API for simple XML files";
license = with stdenv.lib.licenses; [ artistic1 gpl1Plus ]; license = with stdenv.lib.licenses; [ artistic1 gpl1Plus ];
}; };
}; };
</screen> </screen>
The output can be pasted into <filename>pkgs/top-level/perl-packages.nix</filename> or wherever else you need it. The output can be pasted into <filename>pkgs/top-level/perl-packages.nix</filename> or wherever else you need it.
</para> </para>
</section> </section>

View file

@ -567,7 +567,7 @@ test run would be:
checkPhase = "pytest"; checkPhase = "pytest";
``` ```
However, many repositories' test suites do not translate well to nix's build However, many repositories' test suites do not translate well to nix's build
sandbox, and will generally need many tests to be disabled. sandbox, and will generally need many tests to be disabled.
To filter tests using pytest, one can do the following: To filter tests using pytest, one can do the following:

View file

@ -18,7 +18,7 @@ mkDerivation { <co xml:id='qt-default-nix-co-2' />
buildInputs = [ qtbase ]; <co xml:id='qt-default-nix-co-3' /> buildInputs = [ qtbase ]; <co xml:id='qt-default-nix-co-3' />
} }
</programlisting> </programlisting>
</example> </example>
<calloutlist> <calloutlist>

View file

@ -12,14 +12,14 @@
</para> </para>
<screen> <screen>
<![CDATA[$ cd pkgs/servers/monitoring <prompt>$ </prompt>cd pkgs/servers/monitoring
$ mkdir sensu <prompt>$ </prompt>mkdir sensu
$ cd sensu <prompt>$ </prompt>cd sensu
$ cat > Gemfile <prompt>$ </prompt>cat > Gemfile
source 'https://rubygems.org' source 'https://rubygems.org'
gem 'sensu' gem 'sensu'
$ $(nix-build '<nixpkgs>' -A bundix --no-out-link)/bin/bundix --magic <prompt>$ </prompt>$(nix-build '&lt;nixpkgs>' -A bundix --no-out-link)/bin/bundix --magic
$ cat > default.nix <prompt>$ </prompt>cat > default.nix
{ lib, bundlerEnv, ruby }: { lib, bundlerEnv, ruby }:
bundlerEnv rec { bundlerEnv rec {
@ -37,7 +37,7 @@ bundlerEnv rec {
maintainers = with maintainers; [ theuni ]; maintainers = with maintainers; [ theuni ];
platforms = platforms.unix; platforms = platforms.unix;
}; };
}]]> }
</screen> </screen>
<para> <para>
@ -49,17 +49,16 @@ bundlerEnv rec {
</para> </para>
<screen> <screen>
<![CDATA[$ cd pkgs/servers/monitoring/sensu <prompt>$ </prompt>cd pkgs/servers/monitoring/sensu
$ nix-shell -p bundler --run 'bundle lock --update' <prompt>$ </prompt>nix-shell -p bundler --run 'bundle lock --update'
$ nix-shell -p bundix --run 'bundix' <prompt>$ </prompt>nix-shell -p bundix --run 'bundix'
]]>
</screen> </screen>
<para> <para>
For tools written in Ruby - i.e. where the desire is to install a package and then execute e.g. <command>rake</command> at the command line, there is an alternative builder called <literal>bundlerApp</literal>. Set up the <filename>gemset.nix</filename> the same way, and then, for example: For tools written in Ruby - i.e. where the desire is to install a package and then execute e.g. <command>rake</command> at the command line, there is an alternative builder called <literal>bundlerApp</literal>. Set up the <filename>gemset.nix</filename> the same way, and then, for example:
</para> </para>
<screen> <programlisting>
<![CDATA[{ lib, bundlerApp }: <![CDATA[{ lib, bundlerApp }:
bundlerApp { bundlerApp {
@ -75,7 +74,7 @@ bundlerApp {
platforms = platforms.unix; platforms = platforms.unix;
}; };
}]]> }]]>
</screen> </programlisting>
<para> <para>
The chief advantage of <literal>bundlerApp</literal> over <literal>bundlerEnv</literal> is the executables introduced in the environment are precisely those selected in the <literal>exes</literal> list, as opposed to <literal>bundlerEnv</literal> which adds all the executables made available by gems in the gemset, which can mean e.g. <command>rspec</command> or <command>rake</command> in unpredictable versions available from various packages. The chief advantage of <literal>bundlerApp</literal> over <literal>bundlerEnv</literal> is the executables introduced in the environment are precisely those selected in the <literal>exes</literal> list, as opposed to <literal>bundlerEnv</literal> which adds all the executables made available by gems in the gemset, which can mean e.g. <command>rspec</command> or <command>rake</command> in unpredictable versions available from various packages.

View file

@ -50,7 +50,7 @@ rustPlatform.buildRustPackage rec {
`buildRustPackage` requires a `cargoSha256` attribute which is computed over `buildRustPackage` requires a `cargoSha256` attribute which is computed over
all crate sources of this package. Currently it is obtained by inserting a all crate sources of this package. Currently it is obtained by inserting a
fake checksum into the expression and building the package once. The correct fake checksum into the expression and building the package once. The correct
checksum can be then take from the failed build. checksum can then be taken from the failed build.
Per the instructions in the [Cargo Book](https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html) Per the instructions in the [Cargo Book](https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html)
best practices guide, Rust applications should always commit the `Cargo.lock` best practices guide, Rust applications should always commit the `Cargo.lock`
@ -119,6 +119,18 @@ The above are just guidelines, and exceptions may be granted on a case-by-case b
However, please check if it's possible to disable a problematic subset of the However, please check if it's possible to disable a problematic subset of the
test suite and leave a comment explaining your reasoning. test suite and leave a comment explaining your reasoning.
#### Setting `test-threads`
`buildRustPackage` will use parallel test threads by default,
sometimes it may be necessary to disable this so the tests run consecutively.
```nix
rustPlatform.buildRustPackage {
/* ... */
cargoParallelTestThreads = false;
}
```
### Building a package in `debug` mode ### Building a package in `debug` mode
By default, `buildRustPackage` will use `release` mode for builds. If a package By default, `buildRustPackage` will use `release` mode for builds. If a package

View file

@ -44,11 +44,11 @@ texlive.combine {
<listitem> <listitem>
<para> <para>
You can list packages e.g. by <command>nix repl</command>. You can list packages e.g. by <command>nix repl</command>.
<programlisting><![CDATA[ <programlisting>
$ nix repl <prompt>$ </prompt>nix repl
nix-repl> :l <nixpkgs> <prompt>nix-repl> </prompt>:l &lt;nixpkgs>
nix-repl> texlive.collection-<TAB> <prompt>nix-repl> </prompt>texlive.collection-<keycap function="tab" />
]]></programlisting> </programlisting>
</para> </para>
</listitem> </listitem>
<listitem> <listitem>

View file

@ -263,6 +263,8 @@ Sometimes plugins require an override that must be changed when the plugin is up
To add a new plugin, run `./update.py --add "[owner]/[name]"`. **NOTE**: This script automatically commits to your git repository. Be sure to check out a fresh branch before running. To add a new plugin, run `./update.py --add "[owner]/[name]"`. **NOTE**: This script automatically commits to your git repository. Be sure to check out a fresh branch before running.
Finally, there are some plugins that are also packaged in nodePackages because they have Javascript-related build steps, such as running webpack. Those plugins are not listed in `vim-plugin-names` or managed by `update.py` at all, and are included separately in `overrides.nix`. Currently, all these plugins are related to the `coc.nvim` ecosystem of Language Server Protocol integration with vim/neovim.
## Important repositories ## Important repositories
- [vim-pi](https://bitbucket.org/vimcommunity/vim-pi) is a plugin repository - [vim-pi](https://bitbucket.org/vimcommunity/vim-pi) is a plugin repository

View file

@ -1,7 +1,7 @@
<book xmlns="http://docbook.org/ns/docbook" <book xmlns="http://docbook.org/ns/docbook"
xmlns:xi="http://www.w3.org/2001/XInclude"> xmlns:xi="http://www.w3.org/2001/XInclude">
<info> <info>
<title>Nixpkgs Users and Contributors Guide</title> <title>Nixpkgs Manual</title>
<subtitle>Version <xi:include href=".version" parse="text" /> <subtitle>Version <xi:include href=".version" parse="text" />
</subtitle> </subtitle>
</info> </info>

View file

@ -22,39 +22,69 @@
The reduction effects could be instead achieved by building the parts in completely separate derivations. That would often additionally reduce build-time closures, but it tends to be much harder to write such derivations, as build systems typically assume all parts are being built at once. This compromise approach of single source package producing multiple binary packages is also utilized often by rpm and deb. The reduction effects could be instead achieved by building the parts in completely separate derivations. That would often additionally reduce build-time closures, but it tends to be much harder to write such derivations, as build systems typically assume all parts are being built at once. This compromise approach of single source package producing multiple binary packages is also utilized often by rpm and deb.
</para> </para>
</note> </note>
<para>
A number of attributes can be used to work with a derivation with multiple outputs. The attribute <varname>outputs</varname> is a list of strings, which are the names of the outputs. For each of these names, an identically named attribute is created, corresponding to that output. The attribute <varname>meta.outputsToInstall</varname> is used to determine the default set of outputs to install when using the derivation name unqualified.
</para>
</section> </section>
<section xml:id="sec-multiple-outputs-installing"> <section xml:id="sec-multiple-outputs-installing">
<title>Installing a split package</title> <title>Installing a split package</title>
<para> <para>
When installing a package via <varname>systemPackages</varname> or <command>nix-env</command> you have several options: When installing a package with multiple outputs, the package's <varname>meta.outputsToInstall</varname> attribute determines which outputs are actually installed. <varname>meta.outputsToInstall</varname> is a list whose <link xlink:href="https://github.com/NixOS/nixpkgs/blob/f1680774340d5443a1409c3421ced84ac1163ba9/pkgs/stdenv/generic/make-derivation.nix#L310-L320">default installs binaries and the associated man pages</link>. The following sections describe ways to install different outputs.
</para> </para>
<itemizedlist> <section xml:id="sec-multiple-outputs-installing-nixos">
<listitem> <title>Selecting outputs to install via NixOS</title>
<para>
You can install particular outputs explicitly, as each is available in the Nix language as an attribute of the package. The <varname>outputs</varname> attribute contains a list of output names. <para>
</para> NixOS provides two ways to select the outputs to install for packages listed in <varname>environment.systemPackages</varname>:
</listitem> </para>
<listitem>
<para> <itemizedlist>
You can let it use the default outputs. These are handled by <varname>meta.outputsToInstall</varname> attribute that contains a list of output names. <listitem>
</para>
<para>
TODO: more about tweaking the attribute, etc.
</para>
</listitem>
<listitem>
<para>
NixOS provides configuration option <varname>environment.extraOutputsToInstall</varname> that allows adding extra outputs of <varname>environment.systemPackages</varname> atop the default ones. It's mainly meant for documentation and debug symbols, and it's also modified by specific options.
</para>
<note>
<para> <para>
At this moment there is no similar configurability for packages installed by <command>nix-env</command>. You can still use approach from <xref linkend="sec-modify-via-packageOverrides" /> to override <varname>meta.outputsToInstall</varname> attributes, but that's a rather inconvenient way. The configuration option <varname>environment.extraOutputsToInstall</varname> is appended to each package's <varname>meta.outputsToInstall</varname> attribute to determine the outputs to install. It can for example be used to install <literal>info</literal> documentation or debug symbols for all packages.
</para> </para>
</note> </listitem>
</listitem> <listitem>
</itemizedlist> <para>
The outputs can be listed as packages in <varname>environment.systemPackages</varname>. For example, the <literal>"out"</literal> and <literal>"info"</literal> outputs for the <varname>coreutils</varname> package can be installed by including <varname>coreutils</varname> and <varname>coreutils.info</varname> in <varname>environment.systemPackages</varname>.
</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="sec-multiple-outputs-installing-nix-env">
<title>Selecting outputs to install via <command>nix-env</command></title>
<para>
<command>nix-env</command> lacks an easy way to select the outputs to install. When installing a package, <command>nix-env</command> always installs the outputs listed in <varname>meta.outputsToInstall</varname>, even when the user explicitly selects an output.
</para>
<warning>
<para>
<command>nix-env</command> silenty disregards the outputs selected by the user, and instead installs the outputs from <varname>meta.outputsToInstall</varname>. For example,
</para>
<screen><prompt>$ </prompt>nix-env -iA nixpkgs.coreutils.info</screen>
<para>
installs the <literal>"out"</literal> output (<varname>coreutils.meta.outputsToInstall</varname> is <literal>[ "out" ]</literal>) instead of the requested <literal>"info"</literal>.
</para>
</warning>
<para>
The only recourse to select an output with <command>nix-env</command> is to override the package's <varname>meta.outputsToInstall</varname>, using the functions described in <xref linkend="chap-overrides" />. For example, the following overlay adds the <literal>"info"</literal> output for the <varname>coreutils</varname> package:
</para>
<programlisting>self: super:
{
coreutils = super.coreutils.overrideAttrs (oldAttrs: {
meta = oldAttrs.meta // { outputsToInstall = oldAttrs.meta.outputsToInstall or [ "out" ] ++ [ "info" ]; };
});
}
</programlisting>
</section>
</section> </section>
<section xml:id="sec-multiple-outputs-using-split-packages"> <section xml:id="sec-multiple-outputs-using-split-packages">
<title>Using a split package</title> <title>Using a split package</title>

View file

@ -66,7 +66,7 @@
<listitem> <listitem>
<para> <para>
For allowing the build of a broken package once, you can use an environment variable for a single invocation of the nix tools: For allowing the build of a broken package once, you can use an environment variable for a single invocation of the nix tools:
<programlisting>$ export NIXPKGS_ALLOW_BROKEN=1</programlisting> <screen><prompt>$ </prompt>export NIXPKGS_ALLOW_BROKEN=1</screen>
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
@ -92,7 +92,7 @@
<listitem> <listitem>
<para> <para>
For allowing the build of an unsupported package once, you can use an environment variable for a single invocation of the nix tools: For allowing the build of an unsupported package once, you can use an environment variable for a single invocation of the nix tools:
<programlisting>$ export NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM=1</programlisting> <screen><prompt>$ </prompt>export NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM=1</screen>
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
@ -122,7 +122,7 @@
<listitem> <listitem>
<para> <para>
To temporarily allow all unfree packages, you can use an environment variable for a single invocation of the nix tools: To temporarily allow all unfree packages, you can use an environment variable for a single invocation of the nix tools:
<programlisting>$ export NIXPKGS_ALLOW_UNFREE=1</programlisting> <screen><prompt>$ </prompt>export NIXPKGS_ALLOW_UNFREE=1</screen>
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
@ -187,7 +187,7 @@
<listitem> <listitem>
<para> <para>
To temporarily allow all insecure packages, you can use an environment variable for a single invocation of the nix tools: To temporarily allow all insecure packages, you can use an environment variable for a single invocation of the nix tools:
<programlisting>$ export NIXPKGS_ALLOW_INSECURE=1</programlisting> <screen><prompt>$ </prompt>export NIXPKGS_ALLOW_INSECURE=1</screen>
</para> </para>
</listitem> </listitem>
<listitem> <listitem>

View file

@ -187,14 +187,28 @@ self: super:
<listitem> <listitem>
<para> <para>
<link <link
xlink:href="https://developer.amd.com/amd-aocl/blas-library/">AMD xlink:href="https://github.com/flame/blis">BLIS</link>
BLIS/LIBFLAME</link> (optimized for modern AMD x86_64 CPUs)
</para> </para>
<para> <para>
The AMD BLIS library, with attribute <literal>amd-blis</literal>, BLIS, available through the attribute
provides a BLAS implementation. The complementary AMD LIBFLAME <literal>blis</literal>, is a framework for linear algebra kernels. In
library, with attribute <literal>amd-libflame</literal>, provides addition, it implements the BLAS interface.
a LAPACK implementation. </para>
</listitem>
<listitem>
<para>
<link
xlink:href="https://developer.amd.com/amd-aocl/blas-library/">AMD
BLIS/LIBFLAME</link> (optimized for modern AMD x86_64 CPUs)
</para>
<para>
The AMD fork of the BLIS library, with attribute
<literal>amd-blis</literal>, extends BLIS with optimizations for
modern AMD CPUs. The changes are usually submitted to
the upstream BLIS project after some time. However, AMD BLIS
typically provides some performance improvements on AMD Zen CPUs.
The complementary AMD LIBFLAME library, with attribute
<literal>amd-libflame</literal>, provides a LAPACK implementation.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
@ -226,7 +240,7 @@ self: super:
lapackProvider = self.mkl; lapackProvider = self.mkl;
} }
} }
</programlisting> </programlisting>
<para> <para>
This overlay uses Intels MKL library for both BLAS and LAPACK This overlay uses Intels MKL library for both BLAS and LAPACK
interfaces. Note that the same can be accomplished at runtime interfaces. Note that the same can be accomplished at runtime
@ -234,9 +248,9 @@ self: super:
<literal>libblas.so.3</literal> and <literal>libblas.so.3</literal> and
<literal>liblapack.so.3</literal>. For instance: <literal>liblapack.so.3</literal>. For instance:
</para> </para>
<programlisting> <screen>
$ LD_LIBRARY_PATH=$(nix-build -A mkl)/lib:$LD_LIBRARY_PATH nix-shell -p octave --run octave <prompt>$ </prompt>LD_LIBRARY_PATH=$(nix-build -A mkl)/lib:$LD_LIBRARY_PATH nix-shell -p octave --run octave
</programlisting> </screen>
<para> <para>
Intel MKL requires an <literal>openmp</literal> implementation Intel MKL requires an <literal>openmp</literal> implementation
when running with multiple processors. By default, when running with multiple processors. By default,
@ -274,7 +288,7 @@ assert (!blas.isILP64) &amp;&amp; (!lapack.isILP64);
stdenv.mkDerivation { stdenv.mkDerivation {
... ...
} }
</programlisting> </programlisting>
</section> </section>
</section> </section>
</chapter> </chapter>

View file

@ -5,7 +5,6 @@
outputs = { self }: outputs = { self }:
let let
jobs = import ./pkgs/top-level/release.nix { jobs = import ./pkgs/top-level/release.nix {
nixpkgs = self; nixpkgs = self;
}; };
@ -28,10 +27,31 @@
lib = lib.extend (final: prev: { lib = lib.extend (final: prev: {
nixosSystem = { modules, ... } @ args: nixosSystem = { modules, ... } @ args:
import ./nixos/lib/eval-config.nix (args // { import ./nixos/lib/eval-config.nix (args // {
modules = modules ++ modules =
[ { system.nixos.versionSuffix = let
vmConfig = (import ./nixos/lib/eval-config.nix
(args // {
modules = modules ++ [ ./nixos/modules/virtualisation/qemu-vm.nix ];
})).config;
vmWithBootLoaderConfig = (import ./nixos/lib/eval-config.nix
(args // {
modules = modules ++ [
./nixos/modules/virtualisation/qemu-vm.nix
{ virtualisation.useBootLoader = true; }
];
})).config;
in
modules ++ [
{
system.nixos.versionSuffix =
".${final.substring 0 8 (self.lastModifiedDate or self.lastModified)}.${self.shortRev or "dirty"}"; ".${final.substring 0 8 (self.lastModifiedDate or self.lastModified)}.${self.shortRev or "dirty"}";
system.nixos.revision = final.mkIf (self ? rev) self.rev; system.nixos.revision = final.mkIf (self ? rev) self.rev;
system.build = {
vm = vmConfig.system.build.vm;
vmWithBootLoader = vmWithBootLoaderConfig.system.build.vm;
};
} }
]; ];
}); });

View file

@ -203,40 +203,59 @@ rec {
/* If this option is true, attrsets like { __pretty = fn; val = ; } /* If this option is true, attrsets like { __pretty = fn; val = ; }
will use fn to convert val to a pretty printed representation. will use fn to convert val to a pretty printed representation.
(This means fn is type Val -> String.) */ (This means fn is type Val -> String.) */
allowPrettyValues ? false allowPrettyValues ? false,
}@args: v: with builtins; /* If this option is true, the output is indented with newlines for attribute sets and lists */
multiline ? true
}@args: let
go = indent: v: with builtins;
let isPath = v: typeOf v == "path"; let isPath = v: typeOf v == "path";
introSpace = if multiline then "\n${indent} " else " ";
outroSpace = if multiline then "\n${indent}" else " ";
in if isInt v then toString v in if isInt v then toString v
else if isFloat v then "~${toString v}" else if isFloat v then "~${toString v}"
else if isString v then ''"${libStr.escape [''"''] v}"'' else if isString v then
let
# Separate a string into its lines
newlineSplits = filter (v: ! isList v) (builtins.split "\n" v);
# For a '' string terminated by a \n, which happens when the closing '' is on a new line
multilineResult = "''" + introSpace + concatStringsSep introSpace (lib.init newlineSplits) + outroSpace + "''";
# For a '' string not terminated by a \n, which happens when the closing '' is not on a new line
multilineResult' = "''" + introSpace + concatStringsSep introSpace newlineSplits + "''";
# For single lines, replace all newlines with their escaped representation
singlelineResult = "\"" + libStr.escape [ "\"" ] (concatStringsSep "\\n" newlineSplits) + "\"";
in if multiline && length newlineSplits > 1 then
if lib.last newlineSplits == "" then multilineResult else multilineResult'
else singlelineResult
else if true == v then "true" else if true == v then "true"
else if false == v then "false" else if false == v then "false"
else if null == v then "null" else if null == v then "null"
else if isPath v then toString v else if isPath v then toString v
else if isList v then "[ " else if isList v then
+ libStr.concatMapStringsSep " " (toPretty args) v if v == [] then "[ ]"
+ " ]" else "[" + introSpace
+ libStr.concatMapStringsSep introSpace (go (indent + " ")) v
+ outroSpace + "]"
else if isFunction v then
let fna = lib.functionArgs v;
showFnas = concatStringsSep ", " (libAttr.mapAttrsToList
(name: hasDefVal: if hasDefVal then name + "?" else name)
fna);
in if fna == {} then "<function>"
else "<function, args: {${showFnas}}>"
else if isAttrs v then else if isAttrs v then
# apply pretty values if allowed # apply pretty values if allowed
if attrNames v == [ "__pretty" "val" ] && allowPrettyValues if attrNames v == [ "__pretty" "val" ] && allowPrettyValues
then v.__pretty v.val then v.__pretty v.val
# TODO: there is probably a better representation? else if v == {} then "{ }"
else if v ? type && v.type == "derivation" then else if v ? type && v.type == "derivation" then
"<δ:${v.name}>" "<derivation ${v.drvPath}>"
# "<δ:${concatStringsSep "," (builtins.attrNames v)}>" else "{" + introSpace
else "{ " + libStr.concatStringsSep introSpace (libAttr.mapAttrsToList
+ libStr.concatStringsSep " " (libAttr.mapAttrsToList
(name: value: (name: value:
"${toPretty args name} = ${toPretty args value};") v) "${libStr.escapeNixIdentifier name} = ${go (indent + " ") value};") v)
+ " }" + outroSpace + "}"
else if isFunction v then
let fna = lib.functionArgs v;
showFnas = concatStringsSep "," (libAttr.mapAttrsToList
(name: hasDefVal: if hasDefVal then "(${name})" else name)
fna);
in if fna == {} then "<λ>"
else "<λ:{${showFnas}}>"
else abort "generators.toPretty: should never happen (v = ${v})"; else abort "generators.toPretty: should never happen (v = ${v})";
in go "";
# PLIST handling # PLIST handling
toPlist = {}: v: let toPlist = {}: v: let

View file

@ -436,17 +436,18 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
}; };
# Proprietary binaries; free to redistribute without modification. # Proprietary binaries; free to redistribute without modification.
databricks = {
fullName = "Databricks Proprietary License";
url = "https://pypi.org/project/databricks-connect";
free = false;
};
issl = { issl = {
fullName = "Intel Simplified Software License"; fullName = "Intel Simplified Software License";
url = "https://software.intel.com/en-us/license/intel-simplified-software-license"; url = "https://software.intel.com/en-us/license/intel-simplified-software-license";
free = false; free = false;
}; };
jasper = spdx {
spdxId = "JasPer-2.0";
fullName = "JasPer License";
};
lgpl2Only = spdx { lgpl2Only = spdx {
spdxId = "LGPL-2.0-only"; spdxId = "LGPL-2.0-only";
fullName = "GNU Library General Public License v2 only"; fullName = "GNU Library General Public License v2 only";
@ -643,6 +644,12 @@ lib.mapAttrs (n: v: v // { shortName = n; }) {
url = "https://enterprise.dejacode.com/licenses/public/purdue-bsd"; url = "https://enterprise.dejacode.com/licenses/public/purdue-bsd";
}; };
prosperity30 = {
fullName = "Prosperity-3.0.0";
free = false;
url = "https://prosperitylicense.com/versions/3.0.0.html";
};
qhull = spdx { qhull = spdx {
spdxId = "Qhull"; spdxId = "Qhull";
fullName = "Qhull License"; fullName = "Qhull License";

View file

@ -117,7 +117,7 @@ rec {
if config._module.check && config._module.freeformType == null && merged.unmatchedDefns != [] then if config._module.check && config._module.freeformType == null && merged.unmatchedDefns != [] then
let let
firstDef = head merged.unmatchedDefns; firstDef = head merged.unmatchedDefns;
baseMsg = "The option `${showOption (prefix ++ firstDef.prefix)}' defined in `${firstDef.file}' does not exist."; baseMsg = "The option `${showOption (prefix ++ firstDef.prefix)}' does not exist. Definition values:${showDefs [ firstDef ]}";
in in
if attrNames options == [ "_module" ] if attrNames options == [ "_module" ]
then throw '' then throw ''
@ -449,7 +449,13 @@ rec {
# Handle properties, check types, and merge everything together. # Handle properties, check types, and merge everything together.
res = res =
if opt.readOnly or false && length defs' > 1 then if opt.readOnly or false && length defs' > 1 then
throw "The option `${showOption loc}' is read-only, but it's set multiple times." let
# For a better error message, evaluate all readOnly definitions as
# if they were the only definition.
separateDefs = map (def: def // {
value = (mergeDefinitions loc opt.type [ def ]).mergedValue;
}) defs';
in throw "The option `${showOption loc}' is read-only, but it's set multiple times. Definition values:${showDefs separateDefs}"
else else
mergeDefinitions loc opt.type defs'; mergeDefinitions loc opt.type defs';
@ -457,7 +463,11 @@ rec {
# yield a value computed from the definitions # yield a value computed from the definitions
value = if opt ? apply then opt.apply res.mergedValue else res.mergedValue; value = if opt ? apply then opt.apply res.mergedValue else res.mergedValue;
in opt // warnDeprecation =
if opt.type.deprecationMessage == null then id
else warn "The type `types.${opt.type.name}' of option `${showOption loc}' defined in ${showFiles opt.declarations} is deprecated. ${opt.type.deprecationMessage}";
in warnDeprecation opt //
{ value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value; { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value;
inherit (res.defsFinal') highestPrio; inherit (res.defsFinal') highestPrio;
definitions = map (def: def.value) res.defsFinal; definitions = map (def: def.value) res.defsFinal;
@ -493,8 +503,8 @@ rec {
mergedValue = mergedValue =
if isDefined then if isDefined then
if all (def: type.check def.value) defsFinal then type.merge loc defsFinal if all (def: type.check def.value) defsFinal then type.merge loc defsFinal
else let firstInvalid = findFirst (def: ! type.check def.value) null defsFinal; else let allInvalid = filter (def: ! type.check def.value) defsFinal;
in throw "The option value `${showOption loc}' in `${firstInvalid.file}' is not of type `${type.description}'." in throw "A definition for option `${showOption loc}' is not of type `${type.description}'. Definition values:${showDefs allInvalid}"
else else
# (nixos-option detects this specific error message and gives it special # (nixos-option detects this specific error message and gives it special
# handling. If changed here, please change it there too.) # handling. If changed here, please change it there too.)
@ -613,7 +623,6 @@ rec {
if tp.name == "option set" || tp.name == "submodule" then if tp.name == "option set" || tp.name == "submodule" then
throw "The option ${showOption loc} uses submodules without a wrapping type, in ${showFiles opt.declarations}." throw "The option ${showOption loc} uses submodules without a wrapping type, in ${showFiles opt.declarations}."
else if optionSetIn "attrsOf" then types.attrsOf (types.submodule options) else if optionSetIn "attrsOf" then types.attrsOf (types.submodule options)
else if optionSetIn "loaOf" then types.loaOf (types.submodule options)
else if optionSetIn "listOf" then types.listOf (types.submodule options) else if optionSetIn "listOf" then types.listOf (types.submodule options)
else if optionSetIn "nullOr" then types.nullOr (types.submodule options) else if optionSetIn "nullOr" then types.nullOr (types.submodule options)
else tp; else tp;

View file

@ -96,22 +96,26 @@ rec {
else if all isBool list then foldl' lib.or false list else if all isBool list then foldl' lib.or false list
else if all isString list then lib.concatStrings list else if all isString list then lib.concatStrings list
else if all isInt list && all (x: x == head list) list then head list else if all isInt list && all (x: x == head list) list then head list
else throw "Cannot merge definitions of `${showOption loc}' given in ${showFiles (getFiles defs)}."; else throw "Cannot merge definitions of `${showOption loc}'. Definition values:${showDefs defs}";
mergeOneOption = loc: defs: mergeOneOption = loc: defs:
if defs == [] then abort "This case should never happen." if defs == [] then abort "This case should never happen."
else if length defs != 1 then else if length defs != 1 then
throw "The unique option `${showOption loc}' is defined multiple times, in:\n - ${concatStringsSep "\n - " (getFiles defs)}." throw "The unique option `${showOption loc}' is defined multiple times. Definition values:${showDefs defs}"
else (head defs).value; else (head defs).value;
/* "Merge" option definitions by checking that they all have the same value. */ /* "Merge" option definitions by checking that they all have the same value. */
mergeEqualOption = loc: defs: mergeEqualOption = loc: defs:
if defs == [] then abort "This case should never happen." if defs == [] then abort "This case should never happen."
else foldl' (val: def: # Return early if we only have one element
if def.value != val then # This also makes it work for functions, because the foldl' below would try
throw "The option `${showOption loc}' has conflicting definitions, in ${showFiles (getFiles defs)}." # to compare the first element with itself, which is false for functions
else if length defs == 1 then (elemAt defs 0).value
else (foldl' (first: def:
if def.value != first.value then
throw "The option `${showOption loc}' has conflicting definition values:${showDefs [ first def ]}"
else else
val) (head defs).value defs; first) (head defs) defs).value;
/* Extracts values of all "value" keys of the given list. /* Extracts values of all "value" keys of the given list.
@ -209,6 +213,24 @@ rec {
else escaped; else escaped;
in (concatStringsSep ".") (map escapeOptionPart parts); in (concatStringsSep ".") (map escapeOptionPart parts);
showFiles = files: concatStringsSep " and " (map (f: "`${f}'") files); showFiles = files: concatStringsSep " and " (map (f: "`${f}'") files);
showDefs = defs: concatMapStrings (def:
let
# Pretty print the value for display, if successful
prettyEval = builtins.tryEval (lib.generators.toPretty {} def.value);
# Split it into its lines
lines = filter (v: ! isList v) (builtins.split "\n" prettyEval.value);
# Only display the first 5 lines, and indent them for better visibility
value = concatStringsSep "\n " (take 5 lines ++ optional (length lines > 5) "...");
result =
# Don't print any value if evaluating the value strictly fails
if ! prettyEval.success then ""
# Put it on a new line if it consists of multiple
else if length lines > 1 then ":\n " + value
else ": " + value;
in "\n- In `${def.file}'${result}"
) defs;
unknownModule = "<unknown-file>"; unknownModule = "<unknown-file>";
} }

View file

@ -689,14 +689,15 @@ rec {
"/prefix/nix-profiles-library-paths.patch" "/prefix/nix-profiles-library-paths.patch"
"/prefix/compose-search-path.patch" ] "/prefix/compose-search-path.patch" ]
*/ */
readPathsFromFile = rootPath: file: readPathsFromFile = lib.warn "lib.readPathsFromFile is deprecated, use a list instead"
let (rootPath: file:
lines = lib.splitString "\n" (builtins.readFile file); let
removeComments = lib.filter (line: line != "" && !(lib.hasPrefix "#" line)); lines = lib.splitString "\n" (builtins.readFile file);
relativePaths = removeComments lines; removeComments = lib.filter (line: line != "" && !(lib.hasPrefix "#" line));
absolutePaths = builtins.map (path: rootPath + "/${path}") relativePaths; relativePaths = removeComments lines;
in absolutePaths = builtins.map (path: rootPath + "/${path}") relativePaths;
absolutePaths; in
absolutePaths);
/* Read the contents of a file removing the trailing \n /* Read the contents of a file removing the trailing \n

View file

@ -0,0 +1,77 @@
{ lib }:
rec {
# platform.gcc.arch to its features (as in /proc/cpuinfo)
features = {
default = [ ];
# x86_64 Intel
westmere = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" ];
sandybridge = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" ];
ivybridge = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" ];
haswell = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "fma" ];
broadwell = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "fma" ];
skylake = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "fma" ];
skylake-avx512 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" "avx2" "avx512" "fma" ];
# x86_64 AMD
btver1 = [ "sse3" "ssse3" "sse4_1" "sse4_2" ];
btver2 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "aes" "avx" ];
bdver1 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "fma" "fma4" ];
bdver2 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "fma" "fma4" ];
bdver3 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "fma" "fma4" ];
bdver4 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "avx2" "fma" "fma4" ];
znver1 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "avx2" "fma" ];
znver2 = [ "sse3" "ssse3" "sse4_1" "sse4_2" "sse4a" "aes" "avx" "avx2" "fma" ];
# other
armv5te = [ ];
armv6 = [ ];
armv7-a = [ ];
armv8-a = [ ];
mips32 = [ ];
loongson2f = [ ];
};
# a superior CPU has all the features of an inferior and is able to build and test code for it
inferiors = {
# x86_64 Intel
default = [ ];
westmere = [ ];
sandybridge = [ "westmere" ] ++ inferiors.westmere;
ivybridge = [ "sandybridge" ] ++ inferiors.sandybridge;
haswell = [ "ivybridge" ] ++ inferiors.ivybridge;
broadwell = [ "haswell" ] ++ inferiors.haswell;
skylake = [ "broadwell" ] ++ inferiors.broadwell;
skylake-avx512 = [ "skylake" ] ++ inferiors.skylake;
# x86_64 AMD
btver1 = [ ];
btver2 = [ ]; # TODO: fill this (need testing)
bdver1 = [ ]; # TODO: fill this (need testing)
bdver2 = [ ]; # TODO: fill this (need testing)
bdver3 = [ ]; # TODO: fill this (need testing)
bdver4 = [ ]; # TODO: fill this (need testing)
znver1 = [ ]; # TODO: fill this (need testing)
znver2 = [ ]; # TODO: fill this (need testing)
# other
armv5te = [ ];
armv6 = [ ];
armv7-a = [ ];
armv8-a = [ ];
mips32 = [ ];
loongson2f = [ ];
};
predicates = let
featureSupport = feature: x: builtins.elem feature features.${x} or [];
in {
sse3Support = featureSupport "sse3";
ssse3Support = featureSupport "ssse3";
sse4_1Support = featureSupport "sse4_1";
sse4_2Support = featureSupport "sse4_2";
sse4_aSupport = featureSupport "sse4a";
avxSupport = featureSupport "avx";
avx2Support = featureSupport "avx2";
avx512Support = featureSupport "avx512";
aesSupport = featureSupport "aes";
fmaSupport = featureSupport "fma";
fma4Support = featureSupport "fma4";
};
}

View file

@ -7,6 +7,7 @@ rec {
inspect = import ./inspect.nix { inherit lib; }; inspect = import ./inspect.nix { inherit lib; };
platforms = import ./platforms.nix { inherit lib; }; platforms = import ./platforms.nix { inherit lib; };
examples = import ./examples.nix { inherit lib; }; examples = import ./examples.nix { inherit lib; };
architectures = import ./architectures.nix { inherit lib; };
# Elaborate a `localSystem` or `crossSystem` so that it contains everything # Elaborate a `localSystem` or `crossSystem` so that it contains everything
# necessary. # necessary.
@ -76,6 +77,7 @@ rec {
# uname -r # uname -r
release = null; release = null;
}; };
isStatic = final.isWasm || final.isRedox;
kernelArch = kernelArch =
if final.isAarch32 then "arm" if final.isAarch32 then "arm"
@ -125,6 +127,7 @@ rec {
else throw "Don't know how to run ${final.config} executables."; else throw "Don't know how to run ${final.config} executables.";
} // mapAttrs (n: v: v final.parsed) inspect.predicates } // mapAttrs (n: v: v final.parsed) inspect.predicates
// mapAttrs (n: v: v final.platform.gcc.arch or "default") architectures.predicates
// args; // args;
in assert final.useAndroidPrebuilt -> final.isAndroid; in assert final.useAndroidPrebuilt -> final.isAndroid;
assert lib.foldl assert lib.foldl

View file

@ -50,32 +50,35 @@ in {
none = []; none = [];
arm = filterDoubles predicates.isAarch32; arm = filterDoubles predicates.isAarch32;
aarch64 = filterDoubles predicates.isAarch64; aarch64 = filterDoubles predicates.isAarch64;
x86 = filterDoubles predicates.isx86; x86 = filterDoubles predicates.isx86;
i686 = filterDoubles predicates.isi686; i686 = filterDoubles predicates.isi686;
x86_64 = filterDoubles predicates.isx86_64; x86_64 = filterDoubles predicates.isx86_64;
mips = filterDoubles predicates.isMips; mips = filterDoubles predicates.isMips;
riscv = filterDoubles predicates.isRiscV; riscv = filterDoubles predicates.isRiscV;
vc4 = filterDoubles predicates.isVc4; vc4 = filterDoubles predicates.isVc4;
js = filterDoubles predicates.isJavaScript; js = filterDoubles predicates.isJavaScript;
cygwin = filterDoubles predicates.isCygwin; bigEndian = filterDoubles predicates.isBigEndian;
darwin = filterDoubles predicates.isDarwin; littleEndian = filterDoubles predicates.isLittleEndian;
freebsd = filterDoubles predicates.isFreeBSD;
cygwin = filterDoubles predicates.isCygwin;
darwin = filterDoubles predicates.isDarwin;
freebsd = filterDoubles predicates.isFreeBSD;
# Should be better, but MinGW is unclear. # Should be better, but MinGW is unclear.
gnu = filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnu; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabi; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabihf; }); gnu = filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnu; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabi; }) ++ filterDoubles (matchAttrs { kernel = parse.kernels.linux; abi = parse.abis.gnueabihf; });
illumos = filterDoubles predicates.isSunOS; illumos = filterDoubles predicates.isSunOS;
linux = filterDoubles predicates.isLinux; linux = filterDoubles predicates.isLinux;
netbsd = filterDoubles predicates.isNetBSD; netbsd = filterDoubles predicates.isNetBSD;
openbsd = filterDoubles predicates.isOpenBSD; openbsd = filterDoubles predicates.isOpenBSD;
unix = filterDoubles predicates.isUnix; unix = filterDoubles predicates.isUnix;
wasi = filterDoubles predicates.isWasi; wasi = filterDoubles predicates.isWasi;
redox = filterDoubles predicates.isRedox; redox = filterDoubles predicates.isRedox;
windows = filterDoubles predicates.isWindows; windows = filterDoubles predicates.isWindows;
genode = filterDoubles predicates.isGenode; genode = filterDoubles predicates.isGenode;
embedded = filterDoubles predicates.isNone; embedded = filterDoubles predicates.isNone;
mesaPlatforms = ["i686-linux" "x86_64-linux" "x86_64-darwin" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "armv7a-linux" "aarch64-linux" "powerpc64le-linux"]; mesaPlatforms = ["i686-linux" "x86_64-linux" "x86_64-darwin" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "armv7a-linux" "aarch64-linux" "powerpc64le-linux"];
} }

View file

@ -46,16 +46,16 @@ rec {
armv7a-android-prebuilt = { armv7a-android-prebuilt = {
config = "armv7a-unknown-linux-androideabi"; config = "armv7a-unknown-linux-androideabi";
sdkVer = "24"; sdkVer = "29";
ndkVer = "18b"; ndkVer = "21";
platform = platforms.armv7a-android; platform = platforms.armv7a-android;
useAndroidPrebuilt = true; useAndroidPrebuilt = true;
}; };
aarch64-android-prebuilt = { aarch64-android-prebuilt = {
config = "aarch64-unknown-linux-android"; config = "aarch64-unknown-linux-android";
sdkVer = "24"; sdkVer = "29";
ndkVer = "18b"; ndkVer = "21";
platform = platforms.aarch64-multiplatform; platform = platforms.aarch64-multiplatform;
useAndroidPrebuilt = true; useAndroidPrebuilt = true;
}; };

View file

@ -445,32 +445,90 @@ runTests {
expected = builtins.toJSON val; expected = builtins.toJSON val;
}; };
testToPretty = { testToPretty =
expr = mapAttrs (const (generators.toPretty {})) rec { let
deriv = derivation { name = "test"; builder = "/bin/sh"; system = builtins.currentSystem; };
in {
expr = mapAttrs (const (generators.toPretty { multiline = false; })) rec {
int = 42; int = 42;
float = 0.1337; float = 0.1337;
bool = true; bool = true;
emptystring = "";
string = ''fno"rd''; string = ''fno"rd'';
newlinestring = "\n";
path = /. + "/foo"; path = /. + "/foo";
null_ = null; null_ = null;
function = x: x; function = x: x;
functionArgs = { arg ? 4, foo }: arg; functionArgs = { arg ? 4, foo }: arg;
list = [ 3 4 function [ false ] ]; list = [ 3 4 function [ false ] ];
emptylist = [];
attrs = { foo = null; "foo bar" = "baz"; }; attrs = { foo = null; "foo bar" = "baz"; };
drv = derivation { name = "test"; system = builtins.currentSystem; }; emptyattrs = {};
drv = deriv;
}; };
expected = rec { expected = rec {
int = "42"; int = "42";
float = "~0.133700"; float = "~0.133700";
bool = "true"; bool = "true";
emptystring = ''""'';
string = ''"fno\"rd"''; string = ''"fno\"rd"'';
newlinestring = "\"\\n\"";
path = "/foo"; path = "/foo";
null_ = "null"; null_ = "null";
function = "<λ>"; function = "<function>";
functionArgs = "<λ:{(arg),foo}>"; functionArgs = "<function, args: {arg?, foo}>";
list = "[ 3 4 ${function} [ false ] ]"; list = "[ 3 4 ${function} [ false ] ]";
attrs = "{ \"foo\" = null; \"foo bar\" = \"baz\"; }"; emptylist = "[ ]";
drv = "<δ:test>"; attrs = "{ foo = null; \"foo bar\" = \"baz\"; }";
emptyattrs = "{ }";
drv = "<derivation ${deriv.drvPath}>";
};
};
testToPrettyMultiline = {
expr = mapAttrs (const (generators.toPretty { })) rec {
list = [ 3 4 [ false ] ];
attrs = { foo = null; bar.foo = "baz"; };
newlinestring = "\n";
multilinestring = ''
hello
there
test
'';
multilinestring' = ''
hello
there
test'';
};
expected = rec {
list = ''
[
3
4
[
false
]
]'';
attrs = ''
{
bar = {
foo = "baz";
};
foo = null;
}'';
newlinestring = "''\n \n''";
multilinestring = ''
'''
hello
there
test
''''';
multilinestring' = ''
'''
hello
there
test''''';
}; };
}; };
@ -542,4 +600,30 @@ runTests {
name = ""; name = "";
expected = "unknown"; expected = "unknown";
}; };
testFreeformOptions = {
expr =
let
submodule = { lib, ... }: {
freeformType = lib.types.attrsOf (lib.types.submodule {
options.bar = lib.mkOption {};
});
options.bar = lib.mkOption {};
};
module = { lib, ... }: {
options.foo = lib.mkOption {
type = lib.types.submodule submodule;
};
};
options = (evalModules {
modules = [ module ];
}).options;
locs = filter (o: ! o.internal) (optionAttrSetToDocList options);
in map (o: o.loc) locs;
expected = [ [ "foo" ] [ "foo" "<name>" "bar" ] [ "foo" "bar" ] ];
};
} }

View file

@ -49,7 +49,7 @@ checkConfigError() {
reportFailure "$@" reportFailure "$@"
return 1 return 1
else else
if echo "$err" | grep --silent "$errorContains" ; then if echo "$err" | grep -zP --silent "$errorContains" ; then
pass=$((pass + 1)) pass=$((pass + 1))
return 0; return 0;
else else
@ -62,17 +62,17 @@ checkConfigError() {
# Check boolean option. # Check boolean option.
checkConfigOutput "false" config.enable ./declare-enable.nix checkConfigOutput "false" config.enable ./declare-enable.nix
checkConfigError 'The option .* defined in .* does not exist.' config.enable ./define-enable.nix checkConfigError 'The option .* does not exist. Definition values:\n- In .*: true' config.enable ./define-enable.nix
# Check integer types. # Check integer types.
# unsigned # unsigned
checkConfigOutput "42" config.value ./declare-int-unsigned-value.nix ./define-value-int-positive.nix checkConfigOutput "42" config.value ./declare-int-unsigned-value.nix ./define-value-int-positive.nix
checkConfigError 'The option value .* in .* is not of type.*unsigned integer.*' config.value ./declare-int-unsigned-value.nix ./define-value-int-negative.nix checkConfigError 'A definition for option .* is not of type.*unsigned integer.*. Definition values:\n- In .*: -23' config.value ./declare-int-unsigned-value.nix ./define-value-int-negative.nix
# positive # positive
checkConfigError 'The option value .* in .* is not of type.*positive integer.*' config.value ./declare-int-positive-value.nix ./define-value-int-zero.nix checkConfigError 'A definition for option .* is not of type.*positive integer.*. Definition values:\n- In .*: 0' config.value ./declare-int-positive-value.nix ./define-value-int-zero.nix
# between # between
checkConfigOutput "42" config.value ./declare-int-between-value.nix ./define-value-int-positive.nix checkConfigOutput "42" config.value ./declare-int-between-value.nix ./define-value-int-positive.nix
checkConfigError 'The option value .* in .* is not of type.*between.*-21 and 43.*inclusive.*' config.value ./declare-int-between-value.nix ./define-value-int-negative.nix checkConfigError 'A definition for option .* is not of type.*between.*-21 and 43.*inclusive.*. Definition values:\n- In .*: -23' config.value ./declare-int-between-value.nix ./define-value-int-negative.nix
# Check either types # Check either types
# types.either # types.either
@ -125,7 +125,7 @@ checkConfigOutput 'true' "$@" ./define-enable.nix ./define-attrsOfSub-foo-enable
set -- config.enable ./define-enable.nix ./declare-enable.nix set -- config.enable ./define-enable.nix ./declare-enable.nix
checkConfigOutput "true" "$@" checkConfigOutput "true" "$@"
checkConfigOutput "false" "$@" ./disable-define-enable.nix checkConfigOutput "false" "$@" ./disable-define-enable.nix
checkConfigError "The option .*enable.* defined in .* does not exist" "$@" ./disable-declare-enable.nix checkConfigError "The option .*enable.* does not exist. Definition values:\n- In .*: true" "$@" ./disable-declare-enable.nix
checkConfigError "attribute .*enable.* in selection path .*config.enable.* not found" "$@" ./disable-define-enable.nix ./disable-declare-enable.nix checkConfigError "attribute .*enable.* in selection path .*config.enable.* not found" "$@" ./disable-define-enable.nix ./disable-declare-enable.nix
checkConfigError "attribute .*enable.* in selection path .*config.enable.* not found" "$@" ./disable-enable-modules.nix checkConfigError "attribute .*enable.* in selection path .*config.enable.* not found" "$@" ./disable-enable-modules.nix
@ -142,17 +142,17 @@ checkConfigError 'infinite recursion encountered' "$@"
# Check _module.check. # Check _module.check.
set -- config.enable ./declare-enable.nix ./define-enable.nix ./define-attrsOfSub-foo.nix set -- config.enable ./declare-enable.nix ./define-enable.nix ./define-attrsOfSub-foo.nix
checkConfigError 'The option .* defined in .* does not exist.' "$@" checkConfigError 'The option .* does not exist. Definition values:\n- In .*' "$@"
checkConfigOutput "true" "$@" ./define-module-check.nix checkConfigOutput "true" "$@" ./define-module-check.nix
# Check coerced value. # Check coerced value.
checkConfigOutput "\"42\"" config.value ./declare-coerced-value.nix checkConfigOutput "\"42\"" config.value ./declare-coerced-value.nix
checkConfigOutput "\"24\"" config.value ./declare-coerced-value.nix ./define-value-string.nix checkConfigOutput "\"24\"" config.value ./declare-coerced-value.nix ./define-value-string.nix
checkConfigError 'The option value .* in .* is not.*string or signed integer convertible to it' config.value ./declare-coerced-value.nix ./define-value-list.nix checkConfigError 'A definition for option .* is not.*string or signed integer convertible to it.*. Definition values:\n- In .*: \[ \]' config.value ./declare-coerced-value.nix ./define-value-list.nix
# Check coerced value with unsound coercion # Check coerced value with unsound coercion
checkConfigOutput "12" config.value ./declare-coerced-value-unsound.nix checkConfigOutput "12" config.value ./declare-coerced-value-unsound.nix
checkConfigError 'The option value .* in .* is not.*8 bit signed integer.* or string convertible to it' config.value ./declare-coerced-value-unsound.nix ./define-value-string-bigint.nix checkConfigError 'A definition for option .* is not of type .*. Definition values:\n- In .*: "1000"' config.value ./declare-coerced-value-unsound.nix ./define-value-string-bigint.nix
checkConfigError 'unrecognised JSON value' config.value ./declare-coerced-value-unsound.nix ./define-value-string-arbitrary.nix checkConfigError 'unrecognised JSON value' config.value ./declare-coerced-value-unsound.nix ./define-value-string-arbitrary.nix
# Check mkAliasOptionModule. # Check mkAliasOptionModule.
@ -183,7 +183,7 @@ checkConfigOutput "true" config.submodule.enable ./declare-submoduleWith-path.ni
checkConfigOutput "true" config.enable ./disable-recursive/main.nix checkConfigOutput "true" config.enable ./disable-recursive/main.nix
checkConfigOutput "true" config.enable ./disable-recursive/{main.nix,disable-foo.nix} checkConfigOutput "true" config.enable ./disable-recursive/{main.nix,disable-foo.nix}
checkConfigOutput "true" config.enable ./disable-recursive/{main.nix,disable-bar.nix} checkConfigOutput "true" config.enable ./disable-recursive/{main.nix,disable-bar.nix}
checkConfigError 'The option .* defined in .* does not exist' config.enable ./disable-recursive/{main.nix,disable-foo.nix,disable-bar.nix} checkConfigError 'The option .* does not exist. Definition values:\n- In .*: true' config.enable ./disable-recursive/{main.nix,disable-foo.nix,disable-bar.nix}
# Check that imports can depend on derivations # Check that imports can depend on derivations
checkConfigOutput "true" config.enable ./import-from-store.nix checkConfigOutput "true" config.enable ./import-from-store.nix
@ -207,7 +207,7 @@ checkConfigOutput "empty" config.value.foo ./declare-lazyAttrsOf.nix ./attrsOf-c
# Even with multiple assignments, a type error should be thrown if any of them aren't valid # Even with multiple assignments, a type error should be thrown if any of them aren't valid
checkConfigError 'The option value .* in .* is not of type .*' \ checkConfigError 'A definition for option .* is not of type .*' \
config.value ./declare-int-unsigned-value.nix ./define-value-list.nix ./define-value-int-positive.nix config.value ./declare-int-unsigned-value.nix ./define-value-list.nix ./define-value-int-positive.nix
## Freeform modules ## Freeform modules
@ -216,7 +216,7 @@ checkConfigOutput 24 config.value ./freeform-attrsOf.nix ./define-value-string.n
# No freeform assigments shouldn't make it error # No freeform assigments shouldn't make it error
checkConfigOutput '{ }' config ./freeform-attrsOf.nix checkConfigOutput '{ }' config ./freeform-attrsOf.nix
# but only if the type matches # but only if the type matches
checkConfigError 'The option value .* in .* is not of type .*' config.value ./freeform-attrsOf.nix ./define-value-list.nix checkConfigError 'A definition for option .* is not of type .*' config.value ./freeform-attrsOf.nix ./define-value-list.nix
# and properties should be applied # and properties should be applied
checkConfigOutput yes config.value ./freeform-attrsOf.nix ./define-value-string-properties.nix checkConfigOutput yes config.value ./freeform-attrsOf.nix ./define-value-string-properties.nix
# Options should still be declarable, and be able to have a type that doesn't match the freeform type # Options should still be declarable, and be able to have a type that doesn't match the freeform type
@ -233,6 +233,35 @@ checkConfigError 'infinite recursion encountered' config.foo ./freeform-attrsOf.
checkConfigError 'The option .* is used but not defined' config.foo ./freeform-lazyAttrsOf.nix ./freeform-unstr-dep-str.nix checkConfigError 'The option .* is used but not defined' config.foo ./freeform-lazyAttrsOf.nix ./freeform-unstr-dep-str.nix
checkConfigOutput 24 config.foo ./freeform-lazyAttrsOf.nix ./freeform-unstr-dep-str.nix ./define-value-string.nix checkConfigOutput 24 config.foo ./freeform-lazyAttrsOf.nix ./freeform-unstr-dep-str.nix ./define-value-string.nix
## types.anything
# Check that attribute sets are merged recursively
checkConfigOutput null config.value.foo ./types-anything/nested-attrs.nix
checkConfigOutput null config.value.l1.foo ./types-anything/nested-attrs.nix
checkConfigOutput null config.value.l1.l2.foo ./types-anything/nested-attrs.nix
checkConfigOutput null config.value.l1.l2.l3.foo ./types-anything/nested-attrs.nix
# Attribute sets that are coercible to strings shouldn't be recursed into
checkConfigOutput foo config.value.outPath ./types-anything/attrs-coercible.nix
# Multiple lists aren't concatenated together
checkConfigError 'The option .* has conflicting definitions' config.value ./types-anything/lists.nix
# Check that all equalizable atoms can be used as long as all definitions are equal
checkConfigOutput 0 config.value.int ./types-anything/equal-atoms.nix
checkConfigOutput false config.value.bool ./types-anything/equal-atoms.nix
checkConfigOutput '""' config.value.string ./types-anything/equal-atoms.nix
checkConfigOutput / config.value.path ./types-anything/equal-atoms.nix
checkConfigOutput null config.value.null ./types-anything/equal-atoms.nix
checkConfigOutput 0.1 config.value.float ./types-anything/equal-atoms.nix
# Functions can't be merged together
checkConfigError "The option .* has conflicting definition values" config.value.multiple-lambdas ./types-anything/functions.nix
checkConfigOutput '<LAMBDA>' config.value.single-lambda ./types-anything/functions.nix
# Check that all mk* modifiers are applied
checkConfigError 'attribute .* not found' config.value.mkiffalse ./types-anything/mk-mods.nix
checkConfigOutput '{ }' config.value.mkiftrue ./types-anything/mk-mods.nix
checkConfigOutput 1 config.value.mkdefault ./types-anything/mk-mods.nix
checkConfigOutput '{ }' config.value.mkmerge ./types-anything/mk-mods.nix
checkConfigOutput true config.value.mkbefore ./types-anything/mk-mods.nix
checkConfigOutput 1 config.value.nested.foo ./types-anything/mk-mods.nix
checkConfigOutput baz config.value.nested.bar.baz ./types-anything/mk-mods.nix
cat <<EOF cat <<EOF
====== module tests ====== ====== module tests ======
$pass Pass $pass Pass

View file

@ -0,0 +1,12 @@
{ lib, ... }: {
options.value = lib.mkOption {
type = lib.types.anything;
};
config.value = {
outPath = "foo";
err = throw "err";
};
}

View file

@ -0,0 +1,26 @@
{ lib, ... }: {
options.value = lib.mkOption {
type = lib.types.anything;
};
config = lib.mkMerge [
{
value.int = 0;
value.bool = false;
value.string = "";
value.path = /.;
value.null = null;
value.float = 0.1;
}
{
value.int = 0;
value.bool = false;
value.string = "";
value.path = /.;
value.null = null;
value.float = 0.1;
}
];
}

View file

@ -0,0 +1,17 @@
{ lib, ... }: {
options.value = lib.mkOption {
type = lib.types.anything;
};
config = lib.mkMerge [
{
value.single-lambda = x: x;
value.multiple-lambdas = x: x;
}
{
value.multiple-lambdas = x: x;
}
];
}

View file

@ -0,0 +1,16 @@
{ lib, ... }: {
options.value = lib.mkOption {
type = lib.types.anything;
};
config = lib.mkMerge [
{
value = [ null ];
}
{
value = [ null ];
}
];
}

View file

@ -0,0 +1,44 @@
{ lib, ... }: {
options.value = lib.mkOption {
type = lib.types.anything;
};
config = lib.mkMerge [
{
value.mkiffalse = lib.mkIf false {};
}
{
value.mkiftrue = lib.mkIf true {};
}
{
value.mkdefault = lib.mkDefault 0;
}
{
value.mkdefault = 1;
}
{
value.mkmerge = lib.mkMerge [
{}
];
}
{
value.mkbefore = lib.mkBefore true;
}
{
value.nested = lib.mkMerge [
{
foo = lib.mkDefault 0;
bar = lib.mkIf false 0;
}
(lib.mkIf true {
foo = lib.mkIf true (lib.mkForce 1);
bar = {
baz = lib.mkDefault "baz";
};
})
];
}
];
}

View file

@ -0,0 +1,22 @@
{ lib, ... }: {
options.value = lib.mkOption {
type = lib.types.anything;
};
config = lib.mkMerge [
{
value.foo = null;
}
{
value.l1.foo = null;
}
{
value.l1.l2.foo = null;
}
{
value.l1.l2.l3.foo = null;
}
];
}

View file

@ -17,7 +17,6 @@ pkgs.runCommandNoCC "nixpkgs-lib-tests" {
export TEST_ROOT=$(pwd)/test-tmp export TEST_ROOT=$(pwd)/test-tmp
export NIX_BUILD_HOOK= export NIX_BUILD_HOOK=
export NIX_CONF_DIR=$TEST_ROOT/etc export NIX_CONF_DIR=$TEST_ROOT/etc
export NIX_DB_DIR=$TEST_ROOT/db
export NIX_LOCALSTATE_DIR=$TEST_ROOT/var export NIX_LOCALSTATE_DIR=$TEST_ROOT/var
export NIX_LOG_DIR=$TEST_ROOT/var/log/nix export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
export NIX_STATE_DIR=$TEST_ROOT/var/nix export NIX_STATE_DIR=$TEST_ROOT/var/nix

View file

@ -171,7 +171,7 @@ rec {
On each release the first letter is bumped and a new animal is chosen On each release the first letter is bumped and a new animal is chosen
starting with that new letter. starting with that new letter.
*/ */
codeName = "Nightingale"; codeName = "Okapi";
/* Returns the current nixpkgs version suffix as string. */ /* Returns the current nixpkgs version suffix as string. */
versionSuffix = versionSuffix =

View file

@ -91,9 +91,12 @@ rec {
# combinable with the binOp binary operation. # combinable with the binOp binary operation.
# binOp: binary operation that merge two payloads of the same type. # binOp: binary operation that merge two payloads of the same type.
functor ? defaultFunctor name functor ? defaultFunctor name
, # The deprecation message to display when this type is used by an option
# If null, the type isn't deprecated
deprecationMessage ? null
}: }:
{ _type = "option-type"; { _type = "option-type";
inherit name check merge emptyValue getSubOptions getSubModules substSubModules typeMerge functor; inherit name check merge emptyValue getSubOptions getSubModules substSubModules typeMerge functor deprecationMessage;
description = if description == null then name else description; description = if description == null then name else description;
}; };
@ -101,6 +104,42 @@ rec {
# When adding new types don't forget to document them in # When adding new types don't forget to document them in
# nixos/doc/manual/development/option-types.xml! # nixos/doc/manual/development/option-types.xml!
types = rec { types = rec {
anything = mkOptionType {
name = "anything";
description = "anything";
check = value: true;
merge = loc: defs:
let
getType = value:
if isAttrs value && isCoercibleToString value
then "stringCoercibleSet"
else builtins.typeOf value;
# Returns the common type of all definitions, throws an error if they
# don't have the same type
commonType = foldl' (type: def:
if getType def.value == type
then type
else throw "The option `${showOption loc}' has conflicting option types in ${showFiles (getFiles defs)}"
) (getType (head defs).value) defs;
mergeFunction = {
# Recursively merge attribute sets
set = (attrsOf anything).merge;
# Safe and deterministic behavior for lists is to only accept one definition
# listOf only used to apply mkIf and co.
list =
if length defs > 1
then throw "The option `${showOption loc}' has conflicting definitions, in ${showFiles (getFiles defs)}."
else (listOf anything).merge;
# This is the type of packages, only accept a single definition
stringCoercibleSet = mergeOneOption;
# Otherwise fall back to only allowing all equal definitions
}.${commonType} or mergeEqualOption;
in mergeFunction loc defs;
};
unspecified = mkOptionType { unspecified = mkOptionType {
name = "unspecified"; name = "unspecified";
}; };
@ -222,8 +261,10 @@ rec {
# Deprecated; should not be used because it quietly concatenates # Deprecated; should not be used because it quietly concatenates
# strings, which is usually not what you want. # strings, which is usually not what you want.
string = warn "types.string is deprecated because it quietly concatenates strings" string = separatedString "" // {
(separatedString ""); name = "string";
deprecationMessage = "See https://github.com/NixOS/nixpkgs/pull/66346 for better alternative types.";
};
attrs = mkOptionType { attrs = mkOptionType {
name = "attrs"; name = "attrs";
@ -252,25 +293,20 @@ rec {
merge = mergeEqualOption; merge = mergeEqualOption;
}; };
# drop this in the future:
list = builtins.trace "`types.list` is deprecated; use `types.listOf` instead" types.listOf;
listOf = elemType: mkOptionType rec { listOf = elemType: mkOptionType rec {
name = "listOf"; name = "listOf";
description = "list of ${elemType.description}s"; description = "list of ${elemType.description}s";
check = isList; check = isList;
merge = loc: defs: merge = loc: defs:
map (x: x.value) (filter (x: x ? value) (concatLists (imap1 (n: def: map (x: x.value) (filter (x: x ? value) (concatLists (imap1 (n: def:
if isList def.value then imap1 (m: def':
imap1 (m: def': (mergeDefinitions
(mergeDefinitions (loc ++ ["[definition ${toString n}-entry ${toString m}]"])
(loc ++ ["[definition ${toString n}-entry ${toString m}]"]) elemType
elemType [{ inherit (def) file; value = def'; }]
[{ inherit (def) file; value = def'; }] ).optionalValue
).optionalValue ) def.value
) def.value ) defs)));
else
throw "The option value `${showOption loc}` in `${def.file}` is not a list.") defs)));
emptyValue = { value = {}; }; emptyValue = { value = {}; };
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["*"]); getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["*"]);
getSubModules = elemType.getSubModules; getSubModules = elemType.getSubModules;
@ -326,110 +362,13 @@ rec {
functor = (defaultFunctor name) // { wrapped = elemType; }; functor = (defaultFunctor name) // { wrapped = elemType; };
}; };
# List or attribute set of ... # TODO: drop this in the future:
loaOf = elemType: loaOf = elemType: types.attrsOf elemType // {
let name = "loaOf";
convertAllLists = loc: defs: deprecationMessage = "Mixing lists with attribute values is no longer"
let + " possible; please use `types.attrsOf` instead. See"
padWidth = stringLength (toString (length defs)); + " https://github.com/NixOS/nixpkgs/issues/1800 for the motivation.";
unnamedPrefix = i: "unnamed-" + fixedWidthNumber padWidth i + "."; };
in
imap1 (i: convertIfList loc (unnamedPrefix i)) defs;
convertIfList = loc: unnamedPrefix: def:
if isList def.value then
let
padWidth = stringLength (toString (length def.value));
unnamed = i: unnamedPrefix + fixedWidthNumber padWidth i;
anyString = placeholder "name";
nameAttrs = [
{ path = [ "environment" "etc" ];
name = "target";
}
{ path = [ "containers" anyString "bindMounts" ];
name = "mountPoint";
}
{ path = [ "programs" "ssh" "knownHosts" ];
# hostNames is actually a list so we would need to handle it only when singleton
name = "hostNames";
}
{ path = [ "fileSystems" ];
name = "mountPoint";
}
{ path = [ "boot" "specialFileSystems" ];
name = "mountPoint";
}
{ path = [ "services" "znapzend" "zetup" ];
name = "dataset";
}
{ path = [ "services" "znapzend" "zetup" anyString "destinations" ];
name = "label";
}
{ path = [ "services" "geoclue2" "appConfig" ];
name = "desktopID";
}
];
matched = let
equals = a: b: b == anyString || a == b;
fallback = { name = "name"; };
in findFirst ({ path, ... }: all (v: v == true) (zipListsWith equals loc path)) fallback nameAttrs;
nameAttr = matched.name;
nameValueOld = value:
if isList value then
if length value > 0 then
"[ " + concatMapStringsSep " " escapeNixString value + " ]"
else
"[ ]"
else
escapeNixString value;
nameValueNew = value: unnamed:
if isList value then
if length value > 0 then
head value
else
unnamed
else
value;
res =
{ inherit (def) file;
value = listToAttrs (
imap1 (elemIdx: elem:
{ name = nameValueNew (elem.${nameAttr} or (unnamed elemIdx)) (unnamed elemIdx);
value = elem;
}) def.value);
};
option = concatStringsSep "." loc;
sample = take 3 def.value;
more = lib.optionalString (length def.value > 3) "... ";
list = concatMapStrings (x: ''{ ${nameAttr} = ${nameValueOld (x.${nameAttr} or "unnamed")}; ...} '') sample;
set = concatMapStrings (x: ''${nameValueNew (x.${nameAttr} or "unnamed") "unnamed"} = {...}; '') sample;
msg = ''
In file ${def.file}
a list is being assigned to the option config.${option}.
This will soon be an error as type loaOf is deprecated.
See https://github.com/NixOS/nixpkgs/pull/63103 for more information.
Do
${option} =
{ ${set}${more}}
instead of
${option} =
[ ${list}${more}]
'';
in
lib.warn msg res
else
def;
attrOnly = attrsOf elemType;
in mkOptionType rec {
name = "loaOf";
description = "list or attribute set of ${elemType.description}s";
check = x: isList x || isAttrs x;
merge = loc: defs: attrOnly.merge loc (convertAllLists loc defs);
emptyValue = { value = {}; };
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name?>"]);
getSubModules = elemType.getSubModules;
substSubModules = m: loaOf (elemType.substSubModules m);
functor = (defaultFunctor name) // { wrapped = elemType; };
};
# Value of given type but with no merging (i.e. `uniq list`s are not concatenated). # Value of given type but with no merging (i.e. `uniq list`s are not concatenated).
uniq = elemType: mkOptionType rec { uniq = elemType: mkOptionType rec {
@ -522,7 +461,12 @@ rec {
# would be used, and use of `<` and `>` would break the XML document. # would be used, and use of `<` and `>` would break the XML document.
# It shouldn't cause an issue since this is cosmetic for the manual. # It shouldn't cause an issue since this is cosmetic for the manual.
args.name = "name"; args.name = "name";
}).options; }).options // optionalAttrs (freeformType != null) {
# Expose the sub options of the freeform type. Note that the option
# discovery doesn't care about the attribute name used here, so this
# is just to avoid conflicts with potential options from the submodule
_freeformOptions = freeformType.getSubOptions prefix;
};
getSubModules = modules; getSubModules = modules;
substSubModules = m: submoduleWith (attrs // { substSubModules = m: submoduleWith (attrs // {
modules = m; modules = m;
@ -624,8 +568,9 @@ rec {
# declarations from the options attribute of containing option # declarations from the options attribute of containing option
# declaration. # declaration.
optionSet = mkOptionType { optionSet = mkOptionType {
name = builtins.trace "types.optionSet is deprecated; use types.submodule instead" "optionSet"; name = "optionSet";
description = "option set"; description = "option set";
deprecationMessage = "Use `types.submodule' instead";
}; };
# Augment the given type with an additional type check function. # Augment the given type with an additional type check function.
addCheck = elemType: check: elemType // { check = x: elemType.check x && check x; }; addCheck = elemType: check: elemType // { check = x: elemType.check x && check x; };

View file

@ -254,6 +254,12 @@
githubId = 732652; githubId = 732652;
name = "Andreas Herrmann"; name = "Andreas Herrmann";
}; };
ahrzb = {
email = "ahrzb5@gmail.com";
github = "ahrzb";
githubId = 5220438;
name = "AmirHossein Roozbahani";
};
ahuzik = { ahuzik = {
email = "ales.guzik@gmail.com"; email = "ales.guzik@gmail.com";
github = "alesguzik"; github = "alesguzik";
@ -466,6 +472,12 @@
githubId = 858965; githubId = 858965;
name = "Andrew Morsillo"; name = "Andrew Morsillo";
}; };
andehen = {
email = "git@andehen.net";
github = "andehen";
githubId = 754494;
name = "Anders Asheim Hennum";
};
andersk = { andersk = {
email = "andersk@mit.edu"; email = "andersk@mit.edu";
github = "andersk"; github = "andersk";
@ -874,9 +886,9 @@
githubId = 1017537; githubId = 1017537;
name = "Bruno Bieth"; name = "Bruno Bieth";
}; };
badi = { badmutex = {
email = "abdulwahidc@gmail.com"; email = "github@badi.sh";
github = "badi"; github = "badmutex";
githubId = 35324; githubId = 35324;
name = "Badi' Abdul-Wahid"; name = "Badi' Abdul-Wahid";
}; };
@ -1188,6 +1200,12 @@
githubId = 5525646; githubId = 5525646;
name = "Brice Waegeneire"; name = "Brice Waegeneire";
}; };
bsima = {
email = "ben@bsima.me";
github = "bsima";
githubId = 200617;
name = "Ben Sima";
};
bstrik = { bstrik = {
email = "dutchman55@gmx.com"; email = "dutchman55@gmx.com";
github = "bstrik"; github = "bstrik";
@ -1206,6 +1224,12 @@
githubId = 3043718; githubId = 3043718;
name = "Brett Lyons"; name = "Brett Lyons";
}; };
bryanasdev000 = {
email = "bryanasdev000@gmail.com";
github = "bryanasdev000";
githubId = 53131727;
name = "Bryan Albuquerque";
};
btlvr = { btlvr = {
email = "btlvr@protonmail.com"; email = "btlvr@protonmail.com";
github = "btlvr"; github = "btlvr";
@ -1421,6 +1445,12 @@
githubId = 89596; githubId = 89596;
name = "Florian Friesdorf"; name = "Florian Friesdorf";
}; };
charvp = {
email = "nixpkgs@cvpetegem.be";
github = "charvp";
githubId = 42220376;
name = "Charlotte Van Petegem";
};
chattered = { chattered = {
email = "me@philscotted.com"; email = "me@philscotted.com";
name = "Phil Scott"; name = "Phil Scott";
@ -1623,6 +1653,12 @@
githubId = 5561189; githubId = 5561189;
name = "Cody Opel"; name = "Cody Opel";
}; };
cohei = {
email = "a.d.xvii.kal.mai@gmail.com";
github = "cohei";
githubId = 3477497;
name = "TANIGUCHI Kohei";
};
cohencyril = { cohencyril = {
email = "cyril.cohen@inria.fr"; email = "cyril.cohen@inria.fr";
github = "CohenCyril"; github = "CohenCyril";
@ -1861,6 +1897,12 @@
githubId = 1918; githubId = 1918;
name = "David Anderson"; name = "David Anderson";
}; };
dandellion = {
email = "daniel@dodsorf.as";
github = "dali99";
githubId = 990767;
name = "Daniel Olsen";
};
danharaj = { danharaj = {
email = "dan@obsidian.systems"; email = "dan@obsidian.systems";
github = "danharaj"; github = "danharaj";
@ -2203,6 +2245,12 @@
fingerprint = "4749 0887 CF3B 85A1 6355 C671 78C7 DD40 DF23 FB16"; fingerprint = "4749 0887 CF3B 85A1 6355 C671 78C7 DD40 DF23 FB16";
}]; }];
}; };
dpercy = {
email = "dpercy@dpercy.dev";
github = "dpercy";
githubId = 349909;
name = "David Percy";
};
dpflug = { dpflug = {
email = "david@pflug.email"; email = "david@pflug.email";
github = "dpflug"; github = "dpflug";
@ -2705,6 +2753,12 @@
githubId = 857308; githubId = 857308;
name = "Joe Hermaszewski"; name = "Joe Hermaszewski";
}; };
extends = {
email = "sharosari@gmail.com";
github = "ImExtends";
githubId = 55919390;
name = "Vincent VILLIAUMEY";
};
eyjhb = { eyjhb = {
email = "eyjhbb@gmail.com"; email = "eyjhbb@gmail.com";
github = "eyJhb"; github = "eyJhb";
@ -2763,6 +2817,16 @@
githubId = 541748; githubId = 541748;
name = "Felipe Espinoza"; name = "Felipe Espinoza";
}; };
felschr = {
email = "dev@felschr.com";
github = "felschr";
githubId = 3314323;
name = "Felix Tenley";
keys = [{
longkeyid = "ed25519/0x910ACB9F6BD26F58";
fingerprint = "6AB3 7A28 5420 9A41 82D9 0068 910A CB9F 6BD2 6F58";
}];
};
ffinkdevs = { ffinkdevs = {
email = "fink@h0st.space"; email = "fink@h0st.space";
github = "ffinkdevs"; github = "ffinkdevs";
@ -2861,6 +2925,12 @@
githubId = 5918766; githubId = 5918766;
name = "Franz Thoma"; name = "Franz Thoma";
}; };
fooker = {
email = "fooker@lab.sh";
github = "fooker";
githubId = 405105;
name = "Dustin Frisch";
};
forkk = { forkk = {
email = "forkk@forkk.net"; email = "forkk@forkk.net";
github = "forkk"; github = "forkk";
@ -3079,6 +3149,12 @@
githubId = 3217744; githubId = 3217744;
name = "Peter Ferenczy"; name = "Peter Ferenczy";
}; };
ghuntley = {
email = "ghuntley@ghuntley.com";
github = "ghuntley";
githubId = 127353;
name = "Geoffrey Huntley";
};
gila = { gila = {
email = "jeffry.molanus@gmail.com"; email = "jeffry.molanus@gmail.com";
github = "gila"; github = "gila";
@ -3343,6 +3419,12 @@
githubId = 131599; githubId = 131599;
name = "Martin Weinelt"; name = "Martin Weinelt";
}; };
hh = {
email = "hh@m-labs.hk";
github = "HarryMakes";
githubId = 66358631;
name = "Harry Ho";
};
hhm = { hhm = {
email = "heehooman+nixpkgs@gmail.com"; email = "heehooman+nixpkgs@gmail.com";
github = "hhm0"; github = "hhm0";
@ -3370,10 +3452,14 @@
name = "Hlodver Sigurdsson"; name = "Hlodver Sigurdsson";
}; };
hugoreeves = { hugoreeves = {
email = "hugolreeves@gmail.com"; email = "hugo@hugoreeves.com";
github = "hugoreeves"; github = "hugoreeves";
githubId = 20039091; githubId = 20039091;
name = "Hugo Reeves"; name = "Hugo Reeves";
keys = [{
longkeyid = "rsa4096/0x49FA39F8A7F735F9";
fingerprint = "78C2 E81C 828A 420B 269A EBC1 49FA 39F8 A7F7 35F9";
}];
}; };
hodapp = { hodapp = {
email = "hodapp87@gmail.com"; email = "hodapp87@gmail.com";
@ -3501,6 +3587,12 @@
githubId = 993484; githubId = 993484;
name = "Greg Hale"; name = "Greg Hale";
}; };
immae = {
email = "ismael@bouya.org";
github = "immae";
githubId = 510202;
name = "Ismaël Bouya";
};
imuli = { imuli = {
email = "i@imu.li"; email = "i@imu.li";
github = "imuli"; github = "imuli";
@ -3599,6 +3691,12 @@
githubId = 26877687; githubId = 26877687;
name = "Yurii Izorkin"; name = "Yurii Izorkin";
}; };
j0hax = {
name = "Johannes Arnold";
email = "johannes.arnold@stud.uni-hannover.de";
github = "j0hax";
githubId = 3802620;
};
jacg = { jacg = {
name = "Jacek Generowicz"; name = "Jacek Generowicz";
email = "jacg@my-post-office.net"; email = "jacg@my-post-office.net";
@ -3647,6 +3745,12 @@
githubId = 5283991; githubId = 5283991;
name = "Jake Waksbaum"; name = "Jake Waksbaum";
}; };
jamiemagee = {
email = "jamie.magee@gmail.com";
github = "JamieMagee";
githubId = 1358764;
name = "Jamie Magee";
};
jammerful = { jammerful = {
email = "jammerful@gmail.com"; email = "jammerful@gmail.com";
github = "jammerful"; github = "jammerful";
@ -3715,6 +3819,12 @@
}]; }];
name = "Jiri Daněk"; name = "Jiri Daněk";
}; };
jdbaldry = {
email = "jack.baldry@grafana.com";
github = "jdbaldry";
githubId = 4599384;
name = "Jack Baldry";
};
jdehaas = { jdehaas = {
email = "qqlq@nullptr.club"; email = "qqlq@nullptr.club";
github = "jeroendehaas"; github = "jeroendehaas";
@ -3835,6 +3945,12 @@
githubId = 51518420; githubId = 51518420;
name = "jitwit"; name = "jitwit";
}; };
jjjollyjim = {
email = "jamie@kwiius.com";
github = "JJJollyjim";
githubId = 691552;
name = "Jamie McClymont";
};
jk = { jk = {
email = "hello+nixpkgs@j-k.io"; email = "hello+nixpkgs@j-k.io";
github = "06kellyjac"; github = "06kellyjac";
@ -4010,12 +4126,6 @@
githubId = 1843676; githubId = 1843676;
name = "Jonathan Reeve"; name = "Jonathan Reeve";
}; };
joncojonathan = {
email = "joncojonathan@gmail.com";
github = "joncojonathan";
githubId = 11414454;
name = "Jonathan Haddock";
};
jonringer = { jonringer = {
email = "jonringer117@gmail.com"; email = "jonringer117@gmail.com";
github = "jonringer"; github = "jonringer";
@ -4052,6 +4162,12 @@
githubId = 1918771; githubId = 1918771;
name = "Joe Doyle"; name = "Joe Doyle";
}; };
jperras = {
email = "joel@nerderati.com";
github = "jperras";
githubId = 20675;
name = "Joël Perras";
};
jpierre03 = { jpierre03 = {
email = "nix@prunetwork.fr"; email = "nix@prunetwork.fr";
github = "jpierre03"; github = "jpierre03";
@ -4264,6 +4380,12 @@
githubId = 494012; githubId = 494012;
name = "Kevin Cox"; name = "Kevin Cox";
}; };
kfollesdal = {
email = "kfollesdal@gmail.com";
github = "kfollesdal";
githubId = 546087;
name = "Kristoffer K. Føllesdal";
};
khumba = { khumba = {
email = "bog@khumba.net"; email = "bog@khumba.net";
github = "khumba"; github = "khumba";
@ -4836,6 +4958,12 @@
githubId = 1202012; githubId = 1202012;
name = "Ignat Loskutov"; name = "Ignat Loskutov";
}; };
lostnet = {
email = "lost.networking@gmail.com";
github = "lostnet";
githubId = 1422781;
name = "Will Young";
};
louisdk1 = { louisdk1 = {
email = "louis@louis.dk"; email = "louis@louis.dk";
github = "louisdk1"; github = "louisdk1";
@ -5206,6 +5334,12 @@
githubId = 35892750; githubId = 35892750;
name = "Maxine Aubrey"; name = "Maxine Aubrey";
}; };
maxxk = {
email = "maxim.krivchikov@gmail.com";
github = "maxxk";
githubId = 1191859;
name = "Maxim Krivchikov";
};
mbakke = { mbakke = {
email = "mbakke@fastmail.com"; email = "mbakke@fastmail.com";
github = "mbakke"; github = "mbakke";
@ -5436,10 +5570,14 @@
name = "Michael Mercier"; name = "Michael Mercier";
}; };
midchildan = { midchildan = {
email = "midchildan+nix@gmail.com"; email = "git@midchildan.org";
github = "midchildan"; github = "midchildan";
githubId = 7343721; githubId = 7343721;
name = "midchildan"; name = "midchildan";
keys = [{
longkeyid = "rsa4096/0x186A1EDAC5C63F83";
fingerprint = "FEF0 AE2D 5449 3482 5F06 40AA 186A 1EDA C5C6 3F83";
}];
}; };
mikefaille = { mikefaille = {
email = "michael@faille.io"; email = "michael@faille.io";
@ -5571,6 +5709,12 @@
githubId = 622577; githubId = 622577;
name = "Michael Lieberman"; name = "Michael Lieberman";
}; };
mlvzk = {
name = "mlvzk";
email = "mlvzk@users.noreply.github.com";
github = "mlvzk";
githubId = 44906333;
};
mmahut = { mmahut = {
email = "marek.mahut@gmail.com"; email = "marek.mahut@gmail.com";
github = "mmahut"; github = "mmahut";
@ -5583,6 +5727,12 @@
githubId = 117842; githubId = 117842;
name = "Henri Bourcereau"; name = "Henri Bourcereau";
}; };
mmesch = {
email = "mmesch@noreply.github.com";
github = "mmesch";
githubId = 2597803;
name = "Matthias Meschede";
};
mmilata = { mmilata = {
email = "martin@martinmilata.cz"; email = "martin@martinmilata.cz";
github = "mmilata"; github = "mmilata";
@ -5799,6 +5949,12 @@
githubId = 2176611; githubId = 2176611;
name = "Marko Poikonen"; name = "Marko Poikonen";
}; };
mtreca = {
email = "maxime@treca.dev";
name = "Maxime Tréca";
github = "mtreca";
githubId = 16440823;
};
mtreskin = { mtreskin = {
email = "zerthurd@gmail.com"; email = "zerthurd@gmail.com";
github = "Zert"; github = "Zert";
@ -5957,6 +6113,16 @@
githubId = 8214542; githubId = 8214542;
name = "Nicolò Balzarotti"; name = "Nicolò Balzarotti";
}; };
NieDzejkob = {
email = "kuba@kadziolka.net";
github = "NieDzejkob";
githubId = 23580910;
name = "Jakub Kądziołka";
keys = [{
longkeyid = "rsa4096/0xE315A75846131564";
fingerprint = "E576 BFB2 CF6E B13D F571 33B9 E315 A758 4613 1564";
}];
};
NikolaMandic = { NikolaMandic = {
email = "nikola@mandic.email"; email = "nikola@mandic.email";
github = "NikolaMandic"; github = "NikolaMandic";
@ -6011,6 +6177,12 @@
githubId = 6930756; githubId = 6930756;
name = "Nicolas Mattia"; name = "Nicolas Mattia";
}; };
nobbz = {
name = "Norbert Melzer";
email = "timmelzer+nixpkgs@gmail.com";
github = "NobbZ";
githubId = 58951;
};
nocent = { nocent = {
email = "nocent@protonmail.ch"; email = "nocent@protonmail.ch";
github = "nocent"; github = "nocent";
@ -6359,6 +6531,12 @@
githubId = 157610; githubId = 157610;
name = "Piotr Bogdan"; name = "Piotr Bogdan";
}; };
pblkt = {
email = "pebblekite@gmail.com";
github = "pblkt";
githubId = 6498458;
name = "pebble kite";
};
pcarrier = { pcarrier = {
email = "pc@rrier.ca"; email = "pc@rrier.ca";
github = "pcarrier"; github = "pcarrier";
@ -6707,6 +6885,12 @@
githubId = 37715; githubId = 37715;
name = "Brian McKenna"; name = "Brian McKenna";
}; };
purcell = {
email = "steve@sanityinc.com";
github = "purcell";
githubId = 5636;
name = "Steve Purcell";
};
puzzlewolf = { puzzlewolf = {
email = "nixos@nora.pink"; email = "nixos@nora.pink";
github = "puzzlewolf"; github = "puzzlewolf";
@ -6743,6 +6927,12 @@
githubId = 115877; githubId = 115877;
name = "Kenny Shen"; name = "Kenny Shen";
}; };
quentini = {
email = "quentini@airmail.cc";
github = "QuentinI";
githubId = 18196237;
name = "Quentin Inkling";
};
qyliss = { qyliss = {
email = "hi@alyssa.is"; email = "hi@alyssa.is";
github = "alyssais"; github = "alyssais";
@ -7105,6 +7295,16 @@
githubId = 3621083; githubId = 3621083;
name = "Roosembert (Roosemberth) Palacios"; name = "Roosembert (Roosemberth) Palacios";
}; };
rople380 = {
name = "rople380";
email = "55679162+rople380@users.noreply.github.com";
github = "rople380";
githubId = 55679162;
keys = [{
longkeyid = "rsa2048/0x8526B7574A536236";
fingerprint = "1401 1B63 393D 16C1 AA9C C521 8526 B757 4A53 6236";
}];
};
royneary = { royneary = {
email = "christian@ulrich.earth"; email = "christian@ulrich.earth";
github = "royneary"; github = "royneary";
@ -7291,6 +7491,12 @@
githubId = 1153271; githubId = 1153271;
name = "Sander van der Burg"; name = "Sander van der Burg";
}; };
sarcasticadmin = {
email = "rob@sarcasticadmin.com";
github = "sarcasticadmin";
githubId = 30531572;
name = "Robert James Hernandez";
};
sargon = { sargon = {
email = "danielehlers@mindeye.net"; email = "danielehlers@mindeye.net";
github = "sargon"; github = "sargon";
@ -7737,6 +7943,12 @@
githubId = 3371635; githubId = 3371635;
name = "Salar Rahmanian"; name = "Salar Rahmanian";
}; };
sohalt = {
email = "nixos@sohalt.net";
github = "sohalt";
githubId = 2157287;
name = "sohalt";
};
solson = { solson = {
email = "scott@solson.me"; email = "scott@solson.me";
github = "solson"; github = "solson";
@ -7849,6 +8061,12 @@
githubId = 231788; githubId = 231788;
name = "Stephen Weinberg"; name = "Stephen Weinberg";
}; };
stephenwithph = {
name = "StephenWithPH";
email = "StephenWithPH@users.noreply.github.com";
github = "StephenWithPH";
githubId = 2990492;
};
sterfield = { sterfield = {
email = "sterfield@gmail.com"; email = "sterfield@gmail.com";
github = "sterfield"; github = "sterfield";
@ -7925,6 +8143,18 @@
githubId = 65870; githubId = 65870;
name = "Сухарик"; name = "Сухарик";
}; };
superbo = {
email = "supernbo@gmail.com";
github = "SuperBo";
githubId = 2666479;
name = "Y Nguyen";
};
SuperSandro2000 = {
email = "sandro.jaeckel@gmail.com";
github = "SuperSandro2000";
githubId = 7258858;
name = "Sandro Jäckel";
};
SuprDewd = { SuprDewd = {
email = "suprdewd@gmail.com"; email = "suprdewd@gmail.com";
github = "SuprDewd"; github = "SuprDewd";
@ -8121,6 +8351,12 @@
githubId = 863327; githubId = 863327;
name = "Tyler Benster"; name = "Tyler Benster";
}; };
tcbravo = {
email = "tomas.bravo@protonmail.ch";
github = "tcbravo";
githubId = 66133083;
name = "Tomas Bravo";
};
tckmn = { tckmn = {
email = "andy@tck.mn"; email = "andy@tck.mn";
github = "tckmn"; github = "tckmn";
@ -8299,6 +8535,12 @@
githubId = 1391883; githubId = 1391883;
name = "Tom Hall"; name = "Tom Hall";
}; };
tiagolobocastro = {
email = "tiagolobocastro@gmail.com";
github = "tiagolobocastro";
githubId = 1618946;
name = "Tiago Castro";
};
tilpner = { tilpner = {
email = "till@hoeppner.ws"; email = "till@hoeppner.ws";
github = "tilpner"; github = "tilpner";
@ -8511,6 +8753,12 @@
githubId = 699403; githubId = 699403;
name = "Tomas Vestelind"; name = "Tomas Vestelind";
}; };
tviti = {
email = "tviti@hawaii.edu";
github = "tviti";
githubId = 2251912;
name = "Taylor Viti";
};
tvorog = { tvorog = {
email = "marszaripov@gmail.com"; email = "marszaripov@gmail.com";
github = "tvorog"; github = "tvorog";
@ -8726,6 +8974,16 @@
fingerprint = "B3C0 DA1A C18B 82E8 CA8B B1D1 4F62 CD07 CE64 796A"; fingerprint = "B3C0 DA1A C18B 82E8 CA8B B1D1 4F62 CD07 CE64 796A";
}]; }];
}; };
vincentbernat = {
email = "vincent@bernat.ch";
github = "vincentbernat";
githubId = 631446;
name = "Vincent Bernat";
keys = [{
longkeyid = "rsa4096/0x95A42FE8353525F9";
fingerprint = "AEF2 3487 66F3 71C6 89A7 3600 95A4 2FE8 3535 25F9";
}];
};
vinymeuh = { vinymeuh = {
email = "vinymeuh@gmail.com"; email = "vinymeuh@gmail.com";
github = "vinymeuh"; github = "vinymeuh";
@ -9120,6 +9378,16 @@
fingerprint = "85F8 E850 F8F2 F823 F934 535B EC50 6589 9AEA AF4C"; fingerprint = "85F8 E850 F8F2 F823 F934 535B EC50 6589 9AEA AF4C";
}]; }];
}; };
yusdacra = {
email = "y.bera003.06@protonmail.com";
github = "yusdacra";
githubId = 19897088;
name = "Yusuf Bera Ertan";
keys = [{
longkeyid = "rsa2048/0x61807181F60EFCB2";
fingerprint = "9270 66BD 8125 A45B 4AC4 0326 6180 7181 F60E FCB2";
}];
};
yvesf = { yvesf = {
email = "yvesf+nix@xapek.org"; email = "yvesf+nix@xapek.org";
github = "yvesf"; github = "yvesf";
@ -9392,4 +9660,26 @@
github = "fzakaria"; github = "fzakaria";
githubId = 605070; githubId = 605070;
}; };
nagisa = {
name = "Simonas Kazlauskas";
email = "nixpkgs@kazlauskas.me";
github = "nagisa";
githubId = 679122;
};
yevhenshymotiuk = {
name = "Yevhen Shymotiuk";
email = "yevhenshymotiuk@gmail.com";
github = "yevhenshymotiuk";
githubId = 44244245;
};
hmenke = {
name = "Henri Menke";
email = "henri@henrimenke.de";
github = "hmenke";
githubId = 1903556;
keys = [{
longkeyid = "rsa4096/0xD65C9AFB4C224DA3";
fingerprint = "F1C5 760E 45B9 9A44 72E9 6BFB D65C 9AFB 4C22 4DA3";
}];
};
} }

View file

@ -13,8 +13,12 @@ let
let let
result = builtins.tryEval result = builtins.tryEval
( (
if pkgs.lib.isDerivation pkg && cond name pkg if pkgs.lib.isDerivation pkg && cond name pkg then
then [ (return name pkg) ] # Skip packages whose closure fails on evaluation.
# This happens for pkgs like `python27Packages.djangoql`
# that have disabled Python pkgs as dependencies.
builtins.seq pkg.outPath
[ (return name pkg) ]
else if pkg.recurseForDerivations or false || pkg.recurseForRelease or false else if pkg.recurseForDerivations or false || pkg.recurseForRelease or false
then packagesWith cond return pkg then packagesWith cond return pkg
else [ ] else [ ]
@ -30,7 +34,7 @@ in
packagesWith packagesWith
(name: pkg: (name: pkg:
( (
if builtins.hasAttr "maintainers" pkg.meta if builtins.hasAttr "meta" pkg && builtins.hasAttr "maintainers" pkg.meta
then ( then (
if builtins.isList pkg.meta.maintainers if builtins.isList pkg.meta.maintainers
then builtins.elem maintainer_ pkg.meta.maintainers then builtins.elem maintainer_ pkg.meta.maintainers

View file

@ -35,6 +35,10 @@ lua-cmsgpack,,,,,
lua-iconv,,,,, lua-iconv,,,,,
lua-lsp,,http://luarocks.org/dev,,, lua-lsp,,http://luarocks.org/dev,,,
lua-messagepack,,,,, lua-messagepack,,,,,
lua-resty-http,,,,,
lua-resty-jwt,,,,,
lua-resty-openidc,,,,,
lua-resty-session,,,,,
lua-term,,,,, lua-term,,,,,
lua-toml,,,,, lua-toml,,,,,
lua-zlib,,,,,koral lua-zlib,,,,,koral

1 # nix name luarocks name server version luaversion maintainers
35 lua-iconv
36 lua-lsp http://luarocks.org/dev
37 lua-messagepack
38 lua-resty-http
39 lua-resty-jwt
40 lua-resty-openidc
41 lua-resty-session
42 lua-term
43 lua-toml
44 lua-zlib koral

View file

@ -29,6 +29,13 @@ with lib.maintainers; {
scope = "Maintain ACME-related packages and modules."; scope = "Maintain ACME-related packages and modules.";
}; };
cinnamon = {
members = [
mkg20001
];
scope = "Maintain Cinnamon desktop environment and applications made by the LinuxMint team.";
};
freedesktop = { freedesktop = {
members = [ jtojnar worldofpeace ]; members = [ jtojnar worldofpeace ];
scope = "Maintain Freedesktop.org packages for graphical desktop."; scope = "Maintain Freedesktop.org packages for graphical desktop.";

View file

@ -58,9 +58,9 @@
Like <literal>boot.debug1</literal> or Like <literal>boot.debug1</literal> or
<literal>boot.debug1devices</literal>, but runs stage1 until all <literal>boot.debug1devices</literal>, but runs stage1 until all
filesystems that are mounted during initrd are mounted (see filesystems that are mounted during initrd are mounted (see
<option><link linkend="opt-fileSystems._name__.neededForBoot">neededForBoot</link></option> <option><link linkend="opt-fileSystems._name_.neededForBoot">neededForBoot</link></option>
). As a motivating example, this could be useful if you've forgotten to set ). As a motivating example, this could be useful if you've forgotten to set
<option><link linkend="opt-fileSystems._name__.neededForBoot">neededForBoot</link></option> <option><link linkend="opt-fileSystems._name_.neededForBoot">neededForBoot</link></option>
on a file system. on a file system.
</para> </para>
</listitem> </listitem>

View file

@ -14,27 +14,27 @@
<para> <para>
You create a container with identifier <literal>foo</literal> as follows: You create a container with identifier <literal>foo</literal> as follows:
<screen> <screen>
# nixos-container create foo <prompt># </prompt>nixos-container create <replaceable>foo</replaceable>
</screen> </screen>
This creates the containers root directory in This creates the containers root directory in
<filename>/var/lib/containers/foo</filename> and a small configuration file <filename>/var/lib/containers/<replaceable>foo</replaceable></filename> and a small configuration file
in <filename>/etc/containers/foo.conf</filename>. It also builds the in <filename>/etc/containers/<replaceable>foo</replaceable>.conf</filename>. It also builds the
containers initial system configuration and stores it in containers initial system configuration and stores it in
<filename>/nix/var/nix/profiles/per-container/foo/system</filename>. You can <filename>/nix/var/nix/profiles/per-container/<replaceable>foo</replaceable>/system</filename>. You can
modify the initial configuration of the container on the command line. For modify the initial configuration of the container on the command line. For
instance, to create a container that has <command>sshd</command> running, instance, to create a container that has <command>sshd</command> running,
with the given public key for <literal>root</literal>: with the given public key for <literal>root</literal>:
<screen> <screen>
# nixos-container create foo --config ' <prompt># </prompt>nixos-container create <replaceable>foo</replaceable> --config '
<xref linkend="opt-services.openssh.enable"/> = true; <xref linkend="opt-services.openssh.enable"/> = true;
<link linkend="opt-users.users._name__.openssh.authorizedKeys.keys">users.users.root.openssh.authorizedKeys.keys</link> = ["ssh-dss AAAAB3N…"]; <link linkend="opt-users.users._name_.openssh.authorizedKeys.keys">users.users.root.openssh.authorizedKeys.keys</link> = ["ssh-dss AAAAB3N…"];
' '
</screen> </screen>
By default the next free address in the <literal>10.233.0.0/16</literal> subnet will be chosen By default the next free address in the <literal>10.233.0.0/16</literal> subnet will be chosen
as container IP. This behavior can be altered by setting <literal>--host-address</literal> and as container IP. This behavior can be altered by setting <literal>--host-address</literal> and
<literal>--local-address</literal>: <literal>--local-address</literal>:
<screen> <screen>
# nixos-container create test --config-file test-container.nix \ <prompt># </prompt>nixos-container create test --config-file test-container.nix \
--local-address 10.235.1.2 --host-address 10.235.1.1 --local-address 10.235.1.2 --host-address 10.235.1.1
</screen> </screen>
</para> </para>
@ -42,7 +42,7 @@
<para> <para>
Creating a container does not start it. To start the container, run: Creating a container does not start it. To start the container, run:
<screen> <screen>
# nixos-container start foo <prompt># </prompt>nixos-container start <replaceable>foo</replaceable>
</screen> </screen>
This command will return as soon as the container has booted and has reached This command will return as soon as the container has booted and has reached
<literal>multi-user.target</literal>. On the host, the container runs within <literal>multi-user.target</literal>. On the host, the container runs within
@ -51,7 +51,7 @@
Thus, if something went wrong, you can get status info using Thus, if something went wrong, you can get status info using
<command>systemctl</command>: <command>systemctl</command>:
<screen> <screen>
# systemctl status container@foo <prompt># </prompt>systemctl status container@<replaceable>foo</replaceable>
</screen> </screen>
</para> </para>
@ -59,22 +59,22 @@
If the container has started successfully, you can log in as root using the If the container has started successfully, you can log in as root using the
<command>root-login</command> operation: <command>root-login</command> operation:
<screen> <screen>
# nixos-container root-login foo <prompt># </prompt>nixos-container root-login <replaceable>foo</replaceable>
[root@foo:~]# <prompt>[root@foo:~]#</prompt>
</screen> </screen>
Note that only root on the host can do this (since there is no Note that only root on the host can do this (since there is no
authentication). You can also get a regular login prompt using the authentication). You can also get a regular login prompt using the
<command>login</command> operation, which is available to all users on the <command>login</command> operation, which is available to all users on the
host: host:
<screen> <screen>
# nixos-container login foo <prompt># </prompt>nixos-container login <replaceable>foo</replaceable>
foo login: alice foo login: alice
Password: *** Password: ***
</screen> </screen>
With <command>nixos-container run</command>, you can execute arbitrary With <command>nixos-container run</command>, you can execute arbitrary
commands in the container: commands in the container:
<screen> <screen>
# nixos-container run foo -- uname -a <prompt># </prompt>nixos-container run <replaceable>foo</replaceable> -- uname -a
Linux foo 3.4.82 #1-NixOS SMP Thu Mar 20 14:44:05 UTC 2014 x86_64 GNU/Linux Linux foo 3.4.82 #1-NixOS SMP Thu Mar 20 14:44:05 UTC 2014 x86_64 GNU/Linux
</screen> </screen>
</para> </para>
@ -85,18 +85,18 @@ Linux foo 3.4.82 #1-NixOS SMP Thu Mar 20 14:44:05 UTC 2014 x86_64 GNU/Linux
<literal>/var/lib/container/<replaceable>name</replaceable>/etc/nixos/configuration.nix</literal>, <literal>/var/lib/container/<replaceable>name</replaceable>/etc/nixos/configuration.nix</literal>,
and run and run
<screen> <screen>
# nixos-container update foo <prompt># </prompt>nixos-container update <replaceable>foo</replaceable>
</screen> </screen>
This will build and activate the new configuration. You can also specify a This will build and activate the new configuration. You can also specify a
new configuration on the command line: new configuration on the command line:
<screen> <screen>
# nixos-container update foo --config ' <prompt># </prompt>nixos-container update <replaceable>foo</replaceable> --config '
<xref linkend="opt-services.httpd.enable"/> = true; <xref linkend="opt-services.httpd.enable"/> = true;
<xref linkend="opt-services.httpd.adminAddr"/> = "foo@example.org"; <xref linkend="opt-services.httpd.adminAddr"/> = "foo@example.org";
<xref linkend="opt-networking.firewall.allowedTCPPorts"/> = [ 80 ]; <xref linkend="opt-networking.firewall.allowedTCPPorts"/> = [ 80 ];
' '
# curl http://$(nixos-container show-ip foo)/ <prompt># </prompt>curl http://$(nixos-container show-ip <replaceable>foo</replaceable>)/
&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">… &lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">…
</screen> </screen>
However, note that this will overwrite the containers However, note that this will overwrite the containers
@ -117,7 +117,7 @@ Linux foo 3.4.82 #1-NixOS SMP Thu Mar 20 14:44:05 UTC 2014 x86_64 GNU/Linux
by using <command>systemctl</command> on the containers service unit. To by using <command>systemctl</command> on the containers service unit. To
destroy a container, including its file system, do destroy a container, including its file system, do
<screen> <screen>
# nixos-container destroy foo <prompt># </prompt>nixos-container destroy <replaceable>foo</replaceable>
</screen> </screen>
</para> </para>
</section> </section>

View file

@ -8,7 +8,7 @@
<para> <para>
You can enter rescue mode by running: You can enter rescue mode by running:
<screen> <screen>
# systemctl rescue</screen> <prompt># </prompt>systemctl rescue</screen>
This will eventually give you a single-user root shell. Systemd will stop This will eventually give you a single-user root shell. Systemd will stop
(almost) all system services. To get out of maintenance mode, just exit from (almost) all system services. To get out of maintenance mode, just exit from
the rescue shell. the rescue shell.

View file

@ -16,12 +16,12 @@
disable the use of the binary cache by adding <option>--option disable the use of the binary cache by adding <option>--option
use-binary-caches false</option>, e.g. use-binary-caches false</option>, e.g.
<screen> <screen>
# nixos-rebuild switch --option use-binary-caches false <prompt># </prompt>nixos-rebuild switch --option use-binary-caches false
</screen> </screen>
If you have an alternative binary cache at your disposal, you can use it If you have an alternative binary cache at your disposal, you can use it
instead: instead:
<screen> <screen>
# nixos-rebuild switch --option binary-caches http://my-cache.example.org/ <prompt># </prompt>nixos-rebuild switch --option binary-caches <replaceable>http://my-cache.example.org/</replaceable>
</screen> </screen>
</para> </para>
</section> </section>

View file

@ -7,20 +7,20 @@
<para> <para>
The system can be shut down (and automatically powered off) by doing: The system can be shut down (and automatically powered off) by doing:
<screen> <screen>
# shutdown <prompt># </prompt>shutdown
</screen> </screen>
This is equivalent to running <command>systemctl poweroff</command>. This is equivalent to running <command>systemctl poweroff</command>.
</para> </para>
<para> <para>
To reboot the system, run To reboot the system, run
<screen> <screen>
# reboot <prompt># </prompt>reboot
</screen> </screen>
which is equivalent to <command>systemctl reboot</command>. Alternatively, which is equivalent to <command>systemctl reboot</command>. Alternatively,
you can quickly reboot the system using <literal>kexec</literal>, which you can quickly reboot the system using <literal>kexec</literal>, which
bypasses the BIOS by directly loading the new kernel into memory: bypasses the BIOS by directly loading the new kernel into memory:
<screen> <screen>
# systemctl kexec <prompt># </prompt>systemctl kexec
</screen> </screen>
</para> </para>
<para> <para>

View file

@ -20,16 +20,16 @@
has booted, you can make the selected configuration the default for has booted, you can make the selected configuration the default for
subsequent boots: subsequent boots:
<screen> <screen>
# /run/current-system/bin/switch-to-configuration boot</screen> <prompt># </prompt>/run/current-system/bin/switch-to-configuration boot</screen>
</para> </para>
<para> <para>
Second, you can switch to the previous configuration in a running system: Second, you can switch to the previous configuration in a running system:
<screen> <screen>
# nixos-rebuild switch --rollback</screen> <prompt># </prompt>nixos-rebuild switch --rollback</screen>
This is equivalent to running: This is equivalent to running:
<screen> <screen>
# /nix/var/nix/profiles/system-<replaceable>N</replaceable>-link/bin/switch-to-configuration switch</screen> <prompt># </prompt>/nix/var/nix/profiles/system-<replaceable>N</replaceable>-link/bin/switch-to-configuration switch</screen>
where <replaceable>N</replaceable> is the number of the NixOS system where <replaceable>N</replaceable> is the number of the NixOS system
configuration. To get a list of the available configurations, do: configuration. To get a list of the available configurations, do:
<screen> <screen>

View file

@ -58,9 +58,9 @@ Jan 07 15:55:57 hagbard systemd[1]: Started PostgreSQL Server.
<para> <para>
Units can be stopped, started or restarted: Units can be stopped, started or restarted:
<screen> <screen>
# systemctl stop postgresql.service <prompt># </prompt>systemctl stop postgresql.service
# systemctl start postgresql.service <prompt># </prompt>systemctl start postgresql.service
# systemctl restart postgresql.service <prompt># </prompt>systemctl restart postgresql.service
</screen> </screen>
These operations are synchronous: they wait until the service has finished These operations are synchronous: they wait until the service has finished
starting or stopping (or has failed). Starting a unit will cause the starting or stopping (or has failed). Starting a unit will cause the

View file

@ -39,7 +39,7 @@ c3 - root (0)
can terminate a session in a way that ensures that all the sessions can terminate a session in a way that ensures that all the sessions
processes are gone: processes are gone:
<screen> <screen>
# loginctl terminate-session c3 <prompt># </prompt>loginctl terminate-session c3
</screen> </screen>
</para> </para>
</chapter> </chapter>

View file

@ -25,7 +25,7 @@ xlink:href="https://nixos.org/nixpkgs/manual">Nixpkgs
and you run <command>nixos-rebuild</command>, specifying your own Nixpkgs and you run <command>nixos-rebuild</command>, specifying your own Nixpkgs
tree: tree:
<screen> <screen>
# nixos-rebuild switch -I nixpkgs=/path/to/my/nixpkgs</screen> <prompt># </prompt>nixos-rebuild switch -I nixpkgs=/path/to/my/nixpkgs</screen>
</para> </para>
<para> <para>

View file

@ -23,12 +23,12 @@
<link xlink:href="https://www.freedesktop.org/software/systemd/man/systemd-fstab-generator.html">systemd-fstab-generator</link>. <link xlink:href="https://www.freedesktop.org/software/systemd/man/systemd-fstab-generator.html">systemd-fstab-generator</link>.
The filesystem will be mounted automatically unless The filesystem will be mounted automatically unless
<literal>"noauto"</literal> is present in <link <literal>"noauto"</literal> is present in <link
linkend="opt-fileSystems._name__.options">options</link>. linkend="opt-fileSystems._name_.options">options</link>.
<literal>"noauto"</literal> filesystems can be mounted explicitly using <literal>"noauto"</literal> filesystems can be mounted explicitly using
<command>systemctl</command> e.g. <command>systemctl start <command>systemctl</command> e.g. <command>systemctl start
data.mount</command>. data.mount</command>.
Mount points are created automatically if they dont already exist. For Mount points are created automatically if they dont already exist. For
<option><link linkend="opt-fileSystems._name__.device">device</link></option>, <option><link linkend="opt-fileSystems._name_.device">device</link></option>,
its best to use the topology-independent device aliases in its best to use the topology-independent device aliases in
<filename>/dev/disk/by-label</filename> and <filename>/dev/disk/by-label</filename> and
<filename>/dev/disk/by-uuid</filename>, as these dont change if the <filename>/dev/disk/by-uuid</filename>, as these dont change if the
@ -36,7 +36,7 @@
</para> </para>
<para> <para>
You can usually omit the file system type You can usually omit the file system type
(<option><link linkend="opt-fileSystems._name__.fsType">fsType</link></option>), (<option><link linkend="opt-fileSystems._name_.fsType">fsType</link></option>),
since <command>mount</command> can usually detect the type and load the since <command>mount</command> can usually detect the type and load the
necessary kernel module automatically. However, if the file system is needed necessary kernel module automatically. However, if the file system is needed
at early boot (in the initial ramdisk) and is not <literal>ext2</literal>, at early boot (in the initial ramdisk) and is not <literal>ext2</literal>,
@ -49,7 +49,7 @@
System startup will fail if any of the filesystems fails to mount, dropping System startup will fail if any of the filesystems fails to mount, dropping
you to the emergency shell. You can make a mount asynchronous and you to the emergency shell. You can make a mount asynchronous and
non-critical by adding non-critical by adding
<literal><link linkend="opt-fileSystems._name__.options">options</link> = [ <literal><link linkend="opt-fileSystems._name_.options">options</link> = [
"nofail" ];</literal>. "nofail" ];</literal>.
</para> </para>
</note> </note>

View file

@ -70,35 +70,12 @@ Platform Vendor Advanced Micro Devices, Inc.</screen>
Core Next</link> (GCN) GPUs are supported through the Core Next</link> (GCN) GPUs are supported through the
<package>rocm-opencl-icd</package> package. Adding this package to <package>rocm-opencl-icd</package> package. Adding this package to
<xref linkend="opt-hardware.opengl.extraPackages"/> enables OpenCL <xref linkend="opt-hardware.opengl.extraPackages"/> enables OpenCL
support. However, OpenCL Image support is provided through the support:
non-free <package>rocm-runtime-ext</package> package. This package can
be added to the same configuration option, but requires that
<varname>allowUnfree</varname> option is is enabled for nixpkgs. Full
OpenCL support on supported AMD GPUs is thus enabled as follows:
<programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [ <programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [
rocm-opencl-icd rocm-opencl-icd
rocm-runtime-ext
];</programlisting> ];</programlisting>
</para> </para>
<para>
It is also possible to use the OpenCL Image extension without a
system-wide installation of the <package>rocm-runtime-ext</package>
package by setting the <varname>ROCR_EXT_DIR</varname> environment
variable to the directory that contains the extension:
<screen><prompt>$</prompt> export \
ROCR_EXT_DIR=`nix-build '&lt;nixpkgs&gt;' --no-out-link -A rocm-runtime-ext`/lib/rocm-runtime-ext</screen>
</para>
<para>
With either approach, you can verify that OpenCL Image support
is indeed working with the <command>clinfo</command> command:
<screen><prompt>$</prompt> clinfo | grep Image
Image support Yes</screen>
</para>
</section> </section>
<section xml:id="sec-gpu-accel-opencl-intel"> <section xml:id="sec-gpu-accel-opencl-intel">
@ -206,7 +183,12 @@ GPU1:
be forced as follows: be forced as follows:
<programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [ <programlisting><xref linkend="opt-hardware.opengl.extraPackages"/> = [
<package>amdvlk</package> pkgs.<package>amdvlk</package>
];
# To enable Vulkan support for 32-bit applications, also add:
<xref linkend="opt-hardware.opengl.extraPackages32"/> = [
pkgs.driversi686Linux.<package>amdvlk</package>
]; ];
# For amdvlk # For amdvlk

View file

@ -10,7 +10,7 @@
automatically configure network interfaces. However, you can configure an automatically configure network interfaces. However, you can configure an
interface manually as follows: interface manually as follows:
<programlisting> <programlisting>
<link linkend="opt-networking.interfaces._name__.ipv4.addresses">networking.interfaces.eth0.ipv4.addresses</link> = [ { <link linkend="opt-networking.interfaces._name_.ipv4.addresses">networking.interfaces.eth0.ipv4.addresses</link> = [ {
address = "192.168.1.2"; address = "192.168.1.2";
prefixLength = 24; prefixLength = 24;
} ]; } ];

View file

@ -26,7 +26,7 @@
As with IPv4 networking interfaces are automatically configured via DHCPv6. As with IPv4 networking interfaces are automatically configured via DHCPv6.
You can configure an interface manually: You can configure an interface manually:
<programlisting> <programlisting>
<link linkend="opt-networking.interfaces._name__.ipv6.addresses">networking.interfaces.eth0.ipv6.addresses</link> = [ { <link linkend="opt-networking.interfaces._name_.ipv6.addresses">networking.interfaces.eth0.ipv6.addresses</link> = [ {
address = "fe00:aa:bb:cc::2"; address = "fe00:aa:bb:cc::2";
prefixLength = 64; prefixLength = 64;
} ]; } ];

View file

@ -126,13 +126,13 @@ nixpkgs.config.packageOverrides = pkgs:
<literal>mellanox</literal> drivers. <literal>mellanox</literal> drivers.
</para> </para>
<screen><![CDATA[ <screen>
$ nix-build '<nixpkgs>' -A linuxPackages.kernel.dev <prompt>$ </prompt>nix-build '&lt;nixpkgs>' -A linuxPackages.kernel.dev
$ nix-shell '<nixpkgs>' -A linuxPackages.kernel <prompt>$ </prompt>nix-shell '&lt;nixpkgs>' -A linuxPackages.kernel
$ unpackPhase <prompt>$ </prompt>unpackPhase
$ cd linux-* <prompt>$ </prompt>cd linux-*
$ make -C $dev/lib/modules/*/build M=$(pwd)/drivers/net/ethernet/mellanox modules <prompt>$ </prompt>make -C $dev/lib/modules/*/build M=$(pwd)/drivers/net/ethernet/mellanox modules
# insmod ./drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko <prompt># </prompt>insmod ./drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.ko
]]></screen> </screen>
</section> </section>
</chapter> </chapter>

View file

@ -11,7 +11,7 @@
you create an encrypted Ext4 file system on the device you create an encrypted Ext4 file system on the device
<filename>/dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d</filename>: <filename>/dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d</filename>:
<screen> <screen>
# cryptsetup luksFormat /dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d <prompt># </prompt>cryptsetup luksFormat <replaceable>/dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d</replaceable>
WARNING! WARNING!
======== ========
@ -21,17 +21,17 @@ Are you sure? (Type uppercase yes): YES
Enter LUKS passphrase: *** Enter LUKS passphrase: ***
Verify passphrase: *** Verify passphrase: ***
# cryptsetup luksOpen /dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d crypted <prompt># </prompt>cryptsetup luksOpen <replaceable>/dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d</replaceable> <replaceable>crypted</replaceable>
Enter passphrase for /dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d: *** Enter passphrase for /dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d: ***
# mkfs.ext4 /dev/mapper/crypted <prompt># </prompt>mkfs.ext4 /dev/mapper/<replaceable>crypted</replaceable>
</screen> </screen>
To ensure that this file system is automatically mounted at boot time as To ensure that this file system is automatically mounted at boot time as
<filename>/</filename>, add the following to <filename>/</filename>, add the following to
<filename>configuration.nix</filename>: <filename>configuration.nix</filename>:
<programlisting> <programlisting>
<link linkend="opt-boot.initrd.luks.devices._name__.device">boot.initrd.luks.devices.crypted.device</link> = "/dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d"; <link linkend="opt-boot.initrd.luks.devices._name_.device">boot.initrd.luks.devices.crypted.device</link> = "<replaceable>/dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d</replaceable>";
<xref linkend="opt-fileSystems"/>."/".device = "/dev/mapper/crypted"; <xref linkend="opt-fileSystems"/>."/".device = "/dev/mapper/<replaceable>crypted</replaceable>";
</programlisting> </programlisting>
Should grub be used as bootloader, and <filename>/boot</filename> is located Should grub be used as bootloader, and <filename>/boot</filename> is located
on an encrypted partition, it is necessary to add the following grub option: on an encrypted partition, it is necessary to add the following grub option:
@ -45,11 +45,11 @@ Enter passphrase for /dev/disk/by-uuid/3f6b0024-3a44-4fde-a43a-767b872abe5d: ***
and add it as a new key to our existing device <filename>/dev/sda2</filename>: and add it as a new key to our existing device <filename>/dev/sda2</filename>:
<screen> <screen>
# export FIDO2_LABEL="/dev/sda2 @ $HOSTNAME" <prompt># </prompt>export FIDO2_LABEL="<replaceable>/dev/sda2</replaceable> @ $HOSTNAME"
# fido2luks credential "$FIDO2_LABEL" <prompt># </prompt>fido2luks credential "$FIDO2_LABEL"
f1d00200108b9d6e849a8b388da457688e3dd653b4e53770012d8f28e5d3b269865038c346802f36f3da7278b13ad6a3bb6a1452e24ebeeaa24ba40eef559b1b287d2a2f80b7 f1d00200108b9d6e849a8b388da457688e3dd653b4e53770012d8f28e5d3b269865038c346802f36f3da7278b13ad6a3bb6a1452e24ebeeaa24ba40eef559b1b287d2a2f80b7
# fido2luks -i add-key /dev/sda2 f1d00200108b9d6e849a8b388da457688e3dd653b4e53770012d8f28e5d3b269865038c346802f36f3da7278b13ad6a3bb6a1452e24ebeeaa24ba40eef559b1b287d2a2f80b7 <prompt># </prompt>fido2luks -i add-key <replaceable>/dev/sda2</replaceable> <replaceable>f1d00200108b9d6e849a8b388da457688e3dd653b4e53770012d8f28e5d3b269865038c346802f36f3da7278b13ad6a3bb6a1452e24ebeeaa24ba40eef559b1b287d2a2f80b7</replaceable>
Password: Password:
Password (again): Password (again):
Old password: Old password:
@ -60,13 +60,13 @@ Added to key to device /dev/sda2, slot: 2
To ensure that this file system is decrypted using the FIDO2 compatible key, add the following to <filename>configuration.nix</filename>: To ensure that this file system is decrypted using the FIDO2 compatible key, add the following to <filename>configuration.nix</filename>:
<programlisting> <programlisting>
<link linkend="opt-boot.initrd.luks.fido2Support">boot.initrd.luks.fido2Support</link> = true; <link linkend="opt-boot.initrd.luks.fido2Support">boot.initrd.luks.fido2Support</link> = true;
<link linkend="opt-boot.initrd.luks.devices._name__.fido2.credential">boot.initrd.luks.devices."/dev/sda2".fido2.credential</link> = "f1d00200108b9d6e849a8b388da457688e3dd653b4e53770012d8f28e5d3b269865038c346802f36f3da7278b13ad6a3bb6a1452e24ebeeaa24ba40eef559b1b287d2a2f80b7"; <link linkend="opt-boot.initrd.luks.devices._name_.fido2.credential">boot.initrd.luks.devices."<replaceable>/dev/sda2</replaceable>".fido2.credential</link> = "<replaceable>f1d00200108b9d6e849a8b388da457688e3dd653b4e53770012d8f28e5d3b269865038c346802f36f3da7278b13ad6a3bb6a1452e24ebeeaa24ba40eef559b1b287d2a2f80b7</replaceable>";
</programlisting> </programlisting>
You can also use the FIDO2 passwordless setup, but for security reasons, you might want to enable it only when your device is PIN protected, such as <link xlink:href="https://trezor.io/">Trezor</link>. You can also use the FIDO2 passwordless setup, but for security reasons, you might want to enable it only when your device is PIN protected, such as <link xlink:href="https://trezor.io/">Trezor</link>.
<programlisting> <programlisting>
<link linkend="opt-boot.initrd.luks.devices._name__.fido2.passwordLess">boot.initrd.luks.devices."/dev/sda2".fido2.passwordLess</link> = true; <link linkend="opt-boot.initrd.luks.devices._name_.fido2.passwordLess">boot.initrd.luks.devices."<replaceable>/dev/sda2</replaceable>".fido2.passwordLess</link> = true;
</programlisting> </programlisting>
</para> </para>
</section> </section>

View file

@ -19,7 +19,7 @@
All users that should have permission to change network settings must belong All users that should have permission to change network settings must belong
to the <code>networkmanager</code> group: to the <code>networkmanager</code> group:
<programlisting> <programlisting>
<link linkend="opt-users.users._name__.extraGroups">users.users.alice.extraGroups</link> = [ "networkmanager" ]; <link linkend="opt-users.users._name_.extraGroups">users.users.alice.extraGroups</link> = [ "networkmanager" ];
</programlisting> </programlisting>
</para> </para>

View file

@ -20,7 +20,7 @@
follows: follows:
<!-- FIXME: this might not work if the user is unmanaged. --> <!-- FIXME: this might not work if the user is unmanaged. -->
<programlisting> <programlisting>
<link linkend="opt-users.users._name__.openssh.authorizedKeys.keys">users.users.alice.openssh.authorizedKeys.keys</link> = <link linkend="opt-users.users._name_.openssh.authorizedKeys.keys">users.users.alice.openssh.authorizedKeys.keys</link> =
[ "ssh-dss AAAAB3NzaC1kc3MAAACBAPIkGWVEt4..." ]; [ "ssh-dss AAAAB3NzaC1kc3MAAACBAPIkGWVEt4..." ];
</programlisting> </programlisting>
</para> </para>

View file

@ -11,11 +11,11 @@
that a user account named <literal>alice</literal> shall exist: that a user account named <literal>alice</literal> shall exist:
<programlisting> <programlisting>
<xref linkend="opt-users.users"/>.alice = { <xref linkend="opt-users.users"/>.alice = {
<link linkend="opt-users.users._name__.isNormalUser">isNormalUser</link> = true; <link linkend="opt-users.users._name_.isNormalUser">isNormalUser</link> = true;
<link linkend="opt-users.users._name__.home">home</link> = "/home/alice"; <link linkend="opt-users.users._name_.home">home</link> = "/home/alice";
<link linkend="opt-users.users._name__.description">description</link> = "Alice Foobar"; <link linkend="opt-users.users._name_.description">description</link> = "Alice Foobar";
<link linkend="opt-users.users._name__.extraGroups">extraGroups</link> = [ "wheel" "networkmanager" ]; <link linkend="opt-users.users._name_.extraGroups">extraGroups</link> = [ "wheel" "networkmanager" ];
<link linkend="opt-users.users._name__.openssh.authorizedKeys.keys">openssh.authorizedKeys.keys</link> = [ "ssh-dss AAAAB3Nza... alice@foobar" ]; <link linkend="opt-users.users._name_.openssh.authorizedKeys.keys">openssh.authorizedKeys.keys</link> = [ "ssh-dss AAAAB3Nza... alice@foobar" ];
}; };
</programlisting> </programlisting>
Note that <literal>alice</literal> is a member of the Note that <literal>alice</literal> is a member of the
@ -36,7 +36,7 @@
account will cease to exist. Also, imperative commands for managing users and account will cease to exist. Also, imperative commands for managing users and
groups, such as useradd, are no longer available. Passwords may still be groups, such as useradd, are no longer available. Passwords may still be
assigned by setting the user's assigned by setting the user's
<link linkend="opt-users.users._name__.hashedPassword">hashedPassword</link> <link linkend="opt-users.users._name_.hashedPassword">hashedPassword</link>
option. A hashed password can be generated using <command>mkpasswd -m option. A hashed password can be generated using <command>mkpasswd -m
sha-512</command> after installing the <literal>mkpasswd</literal> package. sha-512</command> after installing the <literal>mkpasswd</literal> package.
</para> </para>
@ -62,24 +62,24 @@ uid = 1000;
<command>useradd</command>, <command>groupmod</command> and so on. For <command>useradd</command>, <command>groupmod</command> and so on. For
instance, to create a user account named <literal>alice</literal>: instance, to create a user account named <literal>alice</literal>:
<screen> <screen>
# useradd -m alice</screen> <prompt># </prompt>useradd -m <replaceable>alice</replaceable></screen>
To make all nix tools available to this new user use `su - USER` which opens To make all nix tools available to this new user use `su - USER` which opens
a login shell (==shell that loads the profile) for given user. This will a login shell (==shell that loads the profile) for given user. This will
create the ~/.nix-defexpr symlink. So run: create the ~/.nix-defexpr symlink. So run:
<screen> <screen>
# su - alice -c "true"</screen> <prompt># </prompt>su - <replaceable>alice</replaceable> -c "true"</screen>
The flag <option>-m</option> causes the creation of a home directory for the The flag <option>-m</option> causes the creation of a home directory for the
new user, which is generally what you want. The user does not have an initial new user, which is generally what you want. The user does not have an initial
password and therefore cannot log in. A password can be set using the password and therefore cannot log in. A password can be set using the
<command>passwd</command> utility: <command>passwd</command> utility:
<screen> <screen>
# passwd alice <prompt># </prompt>passwd <replaceable>alice</replaceable>
Enter new UNIX password: *** Enter new UNIX password: ***
Retype new UNIX password: *** Retype new UNIX password: ***
</screen> </screen>
A user can be deleted using <command>userdel</command>: A user can be deleted using <command>userdel</command>:
<screen> <screen>
# userdel -r alice</screen> <prompt># </prompt>userdel -r <replaceable>alice</replaceable></screen>
The flag <option>-r</option> deletes the users home directory. Accounts The flag <option>-r</option> deletes the users home directory. Accounts
can be modified using <command>usermod</command>. Unix groups can be managed can be modified using <command>usermod</command>. Unix groups can be managed
using <command>groupadd</command>, <command>groupmod</command> and using <command>groupadd</command>, <command>groupmod</command> and

View file

@ -58,7 +58,7 @@
</programlisting> </programlisting>
The X server can then be started manually: The X server can then be started manually:
<screen> <screen>
# systemctl start display-manager.service <prompt># </prompt>systemctl start display-manager.service
</screen> </screen>
</para> </para>
<para> <para>

View file

@ -57,7 +57,7 @@
linkend="ch-configuration"/>. Changes to a module documentation linkend="ch-configuration"/>. Changes to a module documentation
have to be checked to not break building the NixOS manual: have to be checked to not break building the NixOS manual:
</para> </para>
<programlisting>$ nix-build nixos/release.nix -A manual</programlisting> <screen><prompt>$ </prompt>nix-build nixos/release.nix -A manual</screen>
</callout> </callout>
</calloutlist> </calloutlist>
</section> </section>

View file

@ -21,16 +21,6 @@
</para> </para>
<variablelist> <variablelist>
<varlistentry>
<term>
<varname>types.attrs</varname>
</term>
<listitem>
<para>
A free-form attribute set.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<varname>types.bool</varname> <varname>types.bool</varname>
@ -64,6 +54,64 @@
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>
<varname>types.anything</varname>
</term>
<listitem>
<para>
A type that accepts any value and recursively merges attribute sets together.
This type is recommended when the option type is unknown.
<example xml:id="ex-types-anything">
<title><literal>types.anything</literal> Example</title>
<para>
Two definitions of this type like
<programlisting>
{
str = lib.mkDefault "foo";
pkg.hello = pkgs.hello;
fun.fun = x: x + 1;
}
</programlisting>
<programlisting>
{
str = lib.mkIf true "bar";
pkg.gcc = pkgs.gcc;
fun.fun = lib.mkForce (x: x + 2);
}
</programlisting>
will get merged to
<programlisting>
{
str = "bar";
pkg.gcc = pkgs.gcc;
pkg.hello = pkgs.hello;
fun.fun = x: x + 2;
}
</programlisting>
</para>
</example>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>types.attrs</varname>
</term>
<listitem>
<para>
A free-form attribute set.
<warning><para>
This type will be deprecated in the future because it doesn't recurse
into attribute sets, silently drops earlier attribute definitions, and
doesn't discharge <literal>lib.mkDefault</literal>, <literal>lib.mkIf
</literal> and co. For allowing arbitrary attribute sets, prefer
<literal>types.attrsOf types.anything</literal> instead which doesn't
have these problems.
</para></warning>
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
<para> <para>
@ -385,17 +433,6 @@
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>
<varname>types.loaOf</varname> <replaceable>t</replaceable>
</term>
<listitem>
<para>
An attribute set or a list of <replaceable>t</replaceable> type. Multiple
definitions are merged according to the value.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<varname>types.nullOr</varname> <replaceable>t</replaceable> <varname>types.nullOr</varname> <replaceable>t</replaceable>

View file

@ -8,24 +8,26 @@
<title>Release process</title> <title>Release process</title>
<para> <para>
Going through an example of releasing NixOS 17.09: Going through an example of releasing NixOS 19.09:
</para> </para>
<section xml:id="one-month-before-the-beta"> <section xml:id="one-month-before-the-beta">
<title>One month before the beta</title> <title>One month before the beta</title>
<itemizedlist spacing="compact"> <itemizedlist>
<listitem> <listitem>
<para> <para>
Send an email to the nix-devel mailinglist as a warning about upcoming Create an announcement on <link xlink:href="https://discourse.nixos.org">Discourse</link> as a warning about upcoming beta <quote>feature freeze</quote> in a month. <link xlink:href="https://discourse.nixos.org/t/nixos-19-09-feature-freeze/3707">See this post as an example</link>.
beta "feature freeze" in a month.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Discuss with Eelco Dolstra and the community (via IRC, ML) about what Discuss with Eelco Dolstra and the community (via IRC, ML) about what will reach the deadline. Any issue or Pull Request targeting the release should be included in the release milestone.
will reach the deadline. Any issue or Pull Request targeting the release </para>
should be included in the release milestone. </listitem>
<listitem>
<para>
Remove attributes that we know we will not be able to support, especially if there is a stable alternative. E.g. Check that our Linux kernels <link xlink:href="https://www.kernel.org/category/releases.html">projected end-of-life</link> are after our release projected end-of-life.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
@ -34,113 +36,113 @@
<section xml:id="at-beta-release-time"> <section xml:id="at-beta-release-time">
<title>At beta release time</title> <title>At beta release time</title>
<itemizedlist spacing="compact"> <orderedlist>
<listitem> <listitem>
<para> <para>
<link xlink:href="https://github.com/NixOS/nixpkgs/issues/13559">Create From the master branch run:
an issue for tracking Zero Hydra Failures progress. ZHF is an effort to </para>
get build failures down to zero.</link> <programlisting>
git checkout -b release-19.09
</programlisting>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixpkgs/commit/10e61bf5be57736035ec7a804cb0bf3d083bf2cf#diff-9c798092bac0caeb5c52d509be0ca263R69">Bump the <literal>system.defaultChannel</literal> attribute in <literal>nixos/modules/misc/version.nix</literal></link>
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<literal>git tag -a -s -m &quot;Release 17.09-beta&quot; 17.09-beta <link xlink:href="https://github.com/NixOS/nixpkgs/commit/10e61bf5be57736035ec7a804cb0bf3d083bf2cf#diff-831e8d9748240fb23e6734fdc2a6d16eR15">Update <literal>versionSuffix</literal> in <literal>nixos/release.nix</literal></link>
&amp;&amp; git push origin 17.09-beta</literal>
</para> </para>
</listitem> </listitem>
</orderedlist>
<para>
To get the commit count, use the following command:
</para>
<programlisting>
git rev-list --count release-19.09
</programlisting>
<orderedlist>
<listitem> <listitem>
<para> <para>
From the master branch run <literal>git checkout -b Edit changelog at <literal>nixos/doc/manual/release-notes/rl-1909.xml</literal>.
release-17.09</literal>.
</para> </para>
</listitem> <itemizedlist>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixos-org-configurations/pull/18">
Make sure a channel is created at https://nixos.org/channels/. </link>
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixpkgs/compare/bdf161ed8d21...6b63c4616790">
Bump the <literal>system.defaultChannel</literal> attribute in
<literal>nixos/modules/misc/version.nix</literal> </link>
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixpkgs/commit/d6b08acd1ccac0d9d502c4b635e00b04d3387f06">
Update <literal>versionSuffix</literal> in
<literal>nixos/release.nix</literal></link>, use
<literal>git rev-list --count 17.09-beta</literal>
to get the commit count.
</para>
</listitem>
<listitem>
<para>
<literal>echo -n &quot;18.03&quot; &gt; .version</literal> on master.
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixpkgs/commit/b8a4095003e27659092892a4708bb3698231a842">
Pick a new name for the unstable branch. </link>
</para>
</listitem>
<listitem>
<para>
Create a new release notes file for the upcoming release + 1, in this
case <literal>rl-1803.xml</literal>.
</para>
</listitem>
<listitem>
<para>
Create two Hydra jobsets: release-17.09 and release-17.09-small with
<literal>stableBranch</literal> set to false.
</para>
</listitem>
<listitem>
<para>
Remove attributes that we know we will not be able to support,
especially if there is a stable alternative. E.g. Check that our
Linux kernels'
<link xlink:href="https://www.kernel.org/category/releases.html">
projected end-of-life</link> are after our release projected
end-of-life
</para>
</listitem>
<listitem>
<para>
Edit changelog at
<literal>nixos/doc/manual/release-notes/rl-1709.xml</literal> (double
check desktop versions are noted)
</para>
<itemizedlist spacing="compact">
<listitem> <listitem>
<para> <para>
Get all new NixOS modules <literal>git diff Get all new NixOS modules:
release-17.03..release-17.09 nixos/modules/module-list.nix|grep
^+</literal>
</para> </para>
<programlisting>
git diff release-19.03..release-19.09 nixos/modules/module-list.nix | grep ^+
</programlisting>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Note systemd, kernel, glibc and Nix upgrades. Note systemd, kernel, glibc, desktop environment, and Nix upgrades.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
</listitem> </listitem>
</itemizedlist> <listitem>
<para>
Tag the release:
</para>
<programlisting>
git tag --annotate --message="Release 19.09-beta" 19.09-beta
git push upstream 19.09-beta
</programlisting>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixpkgs/commit/01268fda85b7eee4e462c873d8654f975067731f#diff-2bc0e46110b507d6d5a344264ef15adaR1">On the <literal>master</literal> branch, increment the <literal>.version</literal> file</link>
</para>
<programlisting>
echo -n "20.03" > .version
</programlisting>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixpkgs/commit/01268fda85b7eee4e462c873d8654f975067731f#diff-03f3d41b68f62079c55001f1a1c55c1dR137">Update <literal>codeName</literal> in <literal>lib/trivial.nix</literal></link> This will be the name for the next release.
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixpkgs/commit/01268fda85b7eee4e462c873d8654f975067731f#diff-e7ee5ff686cdcc513ca089d6e5682587R11">Create a new release notes file for the upcoming release + 1</link>, in our case this is <literal>rl-2003.xml</literal>.
</para>
</listitem>
<listitem>
<para>
Contact the infrastructure team to create the necessary Hydra Jobsets.
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixos-org-configurations/blob/master/channels.nix">Create a channel at https://nixos.org/channels by creating a PR to nixos-org-configurations, changing <literal>channels.nix</literal></link>
</para>
</listitem>
<listitem>
<para>
Get all Hydra jobsets for the release to have their first evaluation.
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixpkgs/issues/13559">Create an issue for tracking Zero Hydra Failures progress. ZHF is an effort to get build failures down to zero.</link>
</para>
</listitem>
</orderedlist>
</section> </section>
<section xml:id="during-beta"> <section xml:id="during-beta">
<title>During Beta</title> <title>During Beta</title>
<itemizedlist spacing="compact"> <itemizedlist>
<listitem> <listitem>
<para> <para>
Monitor the master branch for bugfixes and minor updates and cherry-pick Monitor the master branch for bugfixes and minor updates and cherry-pick them to the release branch.
them to the release branch.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
@ -149,7 +151,7 @@
<section xml:id="before-the-final-release"> <section xml:id="before-the-final-release">
<title>Before the final release</title> <title>Before the final release</title>
<itemizedlist spacing="compact"> <itemizedlist>
<listitem> <listitem>
<para> <para>
Re-check that the release notes are complete. Re-check that the release notes are complete.
@ -157,21 +159,17 @@
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Release Nix (currently only Eelco Dolstra can do that). Release Nix (currently only Eelco Dolstra can do that). <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/installer/tools/nix-fallback-paths.nix">Make sure fallback is updated.</link>
<link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/installer/tools/nix-fallback-paths.nix">
Make sure fallback is updated. </link>
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<link xlink:href="https://github.com/NixOS/nixpkgs/commit/40fd9ae3ac8048758abdcfc7d28a78b5f22fe97e"> <link xlink:href="https://github.com/NixOS/nixpkgs/commit/40fd9ae3ac8048758abdcfc7d28a78b5f22fe97e">Update README.md with new stable NixOS version information.</link>
Update README.md with new stable NixOS version information. </link>
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Change <literal>stableBranch</literal> to <literal>true</literal> in Hydra and wait for Change <literal>stableBranch</literal> to <literal>true</literal> in Hydra and wait for the channel to update.
the channel to update.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
@ -180,76 +178,143 @@
<section xml:id="at-final-release-time"> <section xml:id="at-final-release-time">
<title>At final release time</title> <title>At final release time</title>
<itemizedlist spacing="compact"> <orderedlist>
<listitem> <listitem>
<para> <para>
<literal>git tag -s -a -m &quot;Release 15.09&quot; 15.09</literal> Update <xref linkend="sec-upgrading" /> section of the manual to match new stable release version.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Update "Chapter 4. Upgrading NixOS" section of the manual to match Update <literal>rl-1909.xml</literal> with the release date.
new stable release version.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Update the Tag the final release
<link xlink:href="https://github.com/NixOS/nixos-homepage/commit/2a37975d5a617ecdfca94696242b6f32ffcba9f1"><code>NIXOS_SERIES</code></link>
in the
<link xlink:href="https://github.com/NixOS/nixos-homepage">nixos-homepage</link>
repository.
</para> </para>
<programlisting>
git tag --annotate --message="Release 19.09" 19.09
git push upstream 19.09
</programlisting>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Get number of commits for the release: <literal>git log Update <link xlink:href="https://github.com/NixOS/nixos-homepage">nixos-homepage</link> for the release.
release-14.04..release-14.12 --format=%an|wc -l</literal>
</para> </para>
<orderedlist>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixos-homepage/blob/47ac3571c4d71e841fd4e6c6e1872e762b9c4942/Makefile#L1">Update <literal>NIXOS_SERIES</literal> in the <literal>Makefile</literal></link>.
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixos-homepage/blob/47ac3571c4d71e841fd4e6c6e1872e762b9c4942/nixos-release.tt#L1">Update <literal>nixos-release.tt</literal> with the new NixOS version</link>.
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixos-homepage/blob/47ac3571c4d71e841fd4e6c6e1872e762b9c4942/flake.nix#L10">Update the <literal>flake.nix</literal> input <literal>released-nixpkgs</literal> to 19.09</link>.
</para>
</listitem>
<listitem>
<para>
Run <literal>./update.sh</literal> (this updates flake.lock to updated channel).
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixos-homepage/blob/a5626c71c03a2dd69086564e56f1a230a2bb177a/logo/nixos-logo-19.09-loris-lores.png">Add a compressed version of the NixOS logo for 19.09</link>.
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/NixOS/nixos-homepage/commit/a5626c71c03a2dd69086564e56f1a230a2bb177a#diff-9cdc6434d3e4fd93a6e5bb0a531a7c71R5">Compose a news item for the website RSS feed</link>.
</para>
</listitem>
</orderedlist>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Commits by contributor: <literal>git log release-14.04..release-14.12 Create a new topic on <link xlink:href="https://discourse.nixos.org/">the Discourse instance</link> to announce the release.
--format=%an|sort|uniq -c|sort -rn</literal>
</para> </para>
</listitem> </listitem>
</orderedlist>
<para>
You should include the following information:
</para>
<itemizedlist>
<listitem>
<para>
Number of commits for the release:
</para>
<programlisting>
bash git log release-19.03..release-19.09 --format=%an | wc -l
</programlisting>
</listitem>
<listitem> <listitem>
<para> <para>
Create a new topic on <link xlink:href="https://discourse.nixos.org/">the Commits by contributor:
Discourse instance</link> to announce the release with the above information.
Best to check how previous email was formulated to see what needs to be
included.
</para> </para>
<programlisting>
git shortlog --summary --numbered release-19.03..release-19.09
</programlisting>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>
Best to check how the previous post was formulated to see what needs to be included.
</para>
</section> </section>
</section> </section>
<section xml:id="release-managers"> <section xml:id="release-management-team">
<title>Release Management Team</title> <title>Release Management Team</title>
<para> <para>
For each release there are two release managers. After each release the For each release there are two release managers. After each release the release manager having managed two releases steps down and the release management team of the last release appoints a new release manager.
release manager having managed two releases steps down and the release
management team of the last release appoints a new release manager.
</para> </para>
<para> <para>
This makes sure a release management team always consists of one release This makes sure a release management team always consists of one release manager who already has managed one release and one release manager being introduced to their role, making it easier to pass on knowledge and experience.
manager who already has managed one release and one release manager being
introduced to their role, making it easier to pass on knowledge and
experience.
</para> </para>
<para> <para>
Release managers for the current NixOS release are tracked by GitHub team Release managers for the current NixOS release are tracked by GitHub team <link xlink:href="https://github.com/orgs/NixOS/teams/nixos-release-managers/members"><literal>@NixOS/nixos-release-managers</literal></link>.
<link xlink:href="https://github.com/orgs/NixOS/teams/nixos-release-managers/members"><literal>@NixOS/nixos-release-managers</literal></link>.
</para> </para>
<para> <para>
A release manager's role and responsibilities are: A release managers role and responsibilities are:
</para> </para>
<itemizedlist> <itemizedlist>
<listitem><para>manage the release process</para></listitem> <listitem>
<listitem><para>start discussions about features and changes for a given release</para></listitem> <para>
<listitem><para>create a roadmap</para></listitem> manage the release process
<listitem><para>release in cooperation with Eelco Dolstra</para></listitem> </para>
<listitem><para>decide which bug fixes, features, etc... get backported after a release</para></listitem> </listitem>
<listitem>
<para>
start discussions about features and changes for a given release
</para>
</listitem>
<listitem>
<para>
create a roadmap
</para>
</listitem>
<listitem>
<para>
release in cooperation with Eelco Dolstra
</para>
</listitem>
<listitem>
<para>
decide which bug fixes, features, etc… get backported after a release
</para>
</listitem>
</itemizedlist> </itemizedlist>
</section> </section>
<section xml:id="release-schedule"> <section xml:id="release-schedule">

View file

@ -24,8 +24,8 @@
</para> </para>
<screen> <screen>
$ cd /path/to/nixpkgs/nixos/doc/manual <prompt>$ </prompt>cd /path/to/nixpkgs/nixos/doc/manual
$ make <prompt>$ </prompt>make
</screen> </screen>
<para> <para>

View file

@ -43,7 +43,7 @@ xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/login.nix">
console, whether device ownership is correctly maintained when switching console, whether device ownership is correctly maintained when switching
between consoles, and so on. On the other hand, between consoles, and so on. On the other hand,
<filename <filename
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/nfs.nix">nfs.nix</filename>, xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/nfs/simple.nix">nfs/simple.nix</filename>,
which tests NFS client and server functionality in the Linux kernel which tests NFS client and server functionality in the Linux kernel
(including whether locks are maintained across server crashes), requires (including whether locks are maintained across server crashes), requires
three machines: a server and two clients. three machines: a server and two clients.

View file

@ -78,7 +78,7 @@
<literal>mutableUsers = false</literal>. Another way is to temporarily add <literal>mutableUsers = false</literal>. Another way is to temporarily add
the following to your configuration: the following to your configuration:
<screen> <screen>
<link linkend="opt-users.users._name__.initialHashedPassword">users.users.your-user.initialHashedPassword</link> = "test"; <link linkend="opt-users.users._name_.initialHashedPassword">users.users.your-user.initialHashedPassword</link> = "test";
</screen> </screen>
<emphasis>Important:</emphasis> delete the $hostname.qcow2 file if you have <emphasis>Important:</emphasis> delete the $hostname.qcow2 file if you have
started the virtual machine at least once without the right users, otherwise started the virtual machine at least once without the right users, otherwise

View file

@ -27,13 +27,13 @@ networking.proxy.noProxy = &quot;127.0.0.1,localhost,internal.domain&quot;;
Setup the proxy environment variables in the shell where you are running Setup the proxy environment variables in the shell where you are running
<literal>nixos-install</literal>. <literal>nixos-install</literal>.
</para> </para>
<programlisting> <screen>
# proxy_url=&quot;http://user:password@proxy:port/&quot; <prompt># </prompt>proxy_url=&quot;http://user:password@proxy:port/&quot;
# export http_proxy=&quot;$proxy_url&quot; <prompt># </prompt>export http_proxy=&quot;$proxy_url&quot;
# export HTTP_PROXY=&quot;$proxy_url&quot; <prompt># </prompt>export HTTP_PROXY=&quot;$proxy_url&quot;
# export https_proxy=&quot;$proxy_url&quot; <prompt># </prompt>export https_proxy=&quot;$proxy_url&quot;
# export HTTPS_PROXY=&quot;$proxy_url&quot; <prompt># </prompt>export HTTPS_PROXY=&quot;$proxy_url&quot;
</programlisting> </screen>
</listitem> </listitem>
</orderedlist> </orderedlist>

View file

@ -211,7 +211,7 @@ nixpkgs https://nixos.org/channels/nixpkgs-unstable</screen>
use <literal>sudo</literal>) use <literal>sudo</literal>)
</para> </para>
<programlisting> <programlisting>
<link linkend="opt-users.users._name__.initialHashedPassword">users.users.root.initialHashedPassword</link> = ""; <link linkend="opt-users.users._name_.initialHashedPassword">users.users.root.initialHashedPassword</link> = "";
</programlisting> </programlisting>
</listitem> </listitem>
<listitem> <listitem>
@ -325,14 +325,14 @@ sudo /nix/var/nix/profiles/system/bin/switch-to-configuration boot
to boot on a USB rescue disk and do something along these lines: to boot on a USB rescue disk and do something along these lines:
</para> </para>
<screen> <screen>
# mkdir root <prompt># </prompt>mkdir root
# mount /dev/sdaX root <prompt># </prompt>mount /dev/sdaX root
# mkdir root/nixos-root <prompt># </prompt>mkdir root/nixos-root
# mv -v root/* root/nixos-root/ <prompt># </prompt>mv -v root/* root/nixos-root/
# mv -v root/nixos-root/old-root/* root/ <prompt># </prompt>mv -v root/nixos-root/old-root/* root/
# mv -v root/boot.bak root/boot # We had renamed this by hand earlier <prompt># </prompt>mv -v root/boot.bak root/boot # We had renamed this by hand earlier
# umount root <prompt># </prompt>umount root
# reboot</screen> <prompt># </prompt>reboot</screen>
<para> <para>
This may work as is or you might also need to reinstall the boot loader This may work as is or you might also need to reinstall the boot loader
</para> </para>

View file

@ -70,9 +70,13 @@
<para> <para>
If you would like to continue the installation from a different machine you If you would like to continue the installation from a different machine you
need to activate the SSH daemon via <command>systemctl start can use activated SSH daemon. You need to copy your ssh key to either
sshd</command>. You then must set a password for either <literal>root</literal> or <literal>/home/nixos/.ssh/authorized_keys</literal> or
<literal>nixos</literal> with <command>passwd</command> to be able to login. <literal>/root/.ssh/authorized_keys</literal> (Tip: For installers with a
modifiable filesystem such as the sd-card installer image a key can be manually
placed by mounting the image on a different machine). Alternatively you must set
a password for either <literal>root</literal> or <literal>nixos</literal> with
<command>passwd</command> to be able to login.
</para> </para>
</section> </section>
</section> </section>
@ -550,7 +554,7 @@ Retype new UNIX password: ***</screen>
# Note: setting fileSystems is generally not # Note: setting fileSystems is generally not
# necessary, since nixos-generate-config figures them out # necessary, since nixos-generate-config figures them out
# automatically in hardware-configuration.nix. # automatically in hardware-configuration.nix.
#<link linkend="opt-fileSystems._name__.device">fileSystems."/".device</link> = "/dev/disk/by-label/nixos"; #<link linkend="opt-fileSystems._name_.device">fileSystems."/".device</link> = "/dev/disk/by-label/nixos";
# Enable the OpenSSH server. # Enable the OpenSSH server.
services.sshd.enable = true; services.sshd.enable = true;

View file

@ -67,32 +67,32 @@
<literal>nixos-20.03</literal> channel. To see which NixOS channel youre <literal>nixos-20.03</literal> channel. To see which NixOS channel youre
subscribed to, run the following as root: subscribed to, run the following as root:
<screen> <screen>
# nix-channel --list | grep nixos <prompt># </prompt>nix-channel --list | grep nixos
nixos https://nixos.org/channels/nixos-unstable nixos https://nixos.org/channels/nixos-unstable
</screen> </screen>
To switch to a different NixOS channel, do To switch to a different NixOS channel, do
<screen> <screen>
# nix-channel --add https://nixos.org/channels/<replaceable>channel-name</replaceable> nixos <prompt># </prompt>nix-channel --add https://nixos.org/channels/<replaceable>channel-name</replaceable> nixos
</screen> </screen>
(Be sure to include the <literal>nixos</literal> parameter at the end.) For (Be sure to include the <literal>nixos</literal> parameter at the end.) For
instance, to use the NixOS 20.03 stable channel: instance, to use the NixOS 20.03 stable channel:
<screen> <screen>
# nix-channel --add https://nixos.org/channels/nixos-20.03 nixos <prompt># </prompt>nix-channel --add https://nixos.org/channels/nixos-20.03 nixos
</screen> </screen>
If you have a server, you may want to use the “small” channel instead: If you have a server, you may want to use the “small” channel instead:
<screen> <screen>
# nix-channel --add https://nixos.org/channels/nixos-20.03-small nixos <prompt># </prompt>nix-channel --add https://nixos.org/channels/nixos-20.03-small nixos
</screen> </screen>
And if you want to live on the bleeding edge: And if you want to live on the bleeding edge:
<screen> <screen>
# nix-channel --add https://nixos.org/channels/nixos-unstable nixos <prompt># </prompt>nix-channel --add https://nixos.org/channels/nixos-unstable nixos
</screen> </screen>
</para> </para>
<para> <para>
You can then upgrade NixOS to the latest version in your chosen channel by You can then upgrade NixOS to the latest version in your chosen channel by
running running
<screen> <screen>
# nixos-rebuild switch --upgrade <prompt># </prompt>nixos-rebuild switch --upgrade
</screen> </screen>
which is equivalent to the more verbose <literal>nix-channel --update nixos; which is equivalent to the more verbose <literal>nix-channel --update nixos;
nixos-rebuild switch</literal>. nixos-rebuild switch</literal>.

View file

@ -136,13 +136,13 @@
<filename>/mnt</filename>: <filename>/mnt</filename>:
</para> </para>
<screen> <screen>
# nixos-enter /mnt <prompt># </prompt>nixos-enter --root /mnt
</screen> </screen>
<para> <para>
Run a shell command: Run a shell command:
</para> </para>
<screen> <screen>
# nixos-enter -c 'ls -l /; cat /proc/mounts' <prompt># </prompt>nixos-enter -c 'ls -l /; cat /proc/mounts'
</screen> </screen>
<para> <para>
Run a non-shell command: Run a non-shell command:

View file

@ -45,6 +45,10 @@
<replaceable>path</replaceable> <replaceable>path</replaceable>
</arg> </arg>
<arg>
<option>--flake</option> <replaceable>flake-uri</replaceable>
</arg>
<arg> <arg>
<arg choice='plain'> <arg choice='plain'>
<option>--channel</option> <option>--channel</option>
@ -199,6 +203,18 @@
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>
<option>--flake</option> <replaceable>flake-uri</replaceable>#<replaceable>name</replaceable>
</term>
<listitem>
<para>
Build the NixOS system from the specified flake.
The flake must contain an output named
<literal>nixosConfigurations.<replaceable>name</replaceable></literal>.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<option>--channel</option> <option>--channel</option>

View file

@ -521,7 +521,7 @@
<varlistentry> <varlistentry>
<term> <term>
<option>--flake</option> <replaceable>flake-uri</replaceable>[<replaceable>name</replaceable>] <option>--flake</option> <replaceable>flake-uri</replaceable><optional>#<replaceable>name</replaceable></optional>
</term> </term>
<listitem> <listitem>
<para> <para>

View file

@ -33,7 +33,7 @@
<para> <para>
This command shows the version of the currently active NixOS configuration. This command shows the version of the currently active NixOS configuration.
For example: For example:
<screen>$ nixos-version <screen><prompt>$ </prompt>nixos-version
16.03.1011.6317da4 (Emu) 16.03.1011.6317da4 (Emu)
</screen> </screen>
The version consists of the following elements: The version consists of the following elements:
@ -111,7 +111,7 @@
<para> <para>
Show the full SHA1 hash of the Git commit from which this configuration Show the full SHA1 hash of the Git commit from which this configuration
was built, e.g. was built, e.g.
<screen>$ nixos-version --hash <screen><prompt>$ </prompt>nixos-version --hash
6317da40006f6bc2480c6781999c52d88dde2acf 6317da40006f6bc2480c6781999c52d88dde2acf
</screen> </screen>
</para> </para>

View file

@ -8,6 +8,7 @@
This section lists the release notes for each stable version of NixOS and This section lists the release notes for each stable version of NixOS and
current unstable revision. current unstable revision.
</para> </para>
<xi:include href="rl-2103.xml" />
<xi:include href="rl-2009.xml" /> <xi:include href="rl-2009.xml" />
<xi:include href="rl-2003.xml" /> <xi:include href="rl-2003.xml" />
<xi:include href="rl-1909.xml" /> <xi:include href="rl-1909.xml" />

View file

@ -796,7 +796,7 @@ users.users.me =
or any other display manager in NixOS as they all support auto-login. If you used this module specifically or any other display manager in NixOS as they all support auto-login. If you used this module specifically
because it permitted root auto-login you can override the lightdm-autologin pam module like: because it permitted root auto-login you can override the lightdm-autologin pam module like:
<programlisting> <programlisting>
<link xlink:href="#opt-security.pam.services._name__.text">security.pam.services.lightdm-autologin.text</link> = lib.mkForce '' <link xlink:href="#opt-security.pam.services._name_.text">security.pam.services.lightdm-autologin.text</link> = lib.mkForce ''
auth requisite pam_nologin.so auth requisite pam_nologin.so
auth required pam_succeed_if.so quiet auth required pam_succeed_if.so quiet
auth required pam_permit.so auth required pam_permit.so

View file

@ -26,6 +26,18 @@
<listitem> <listitem>
<para>GNOME desktop environment was upgraded to 3.36, see its <link xlink:href="https://help.gnome.org/misc/release-notes/3.36/">release notes</link>.</para> <para>GNOME desktop environment was upgraded to 3.36, see its <link xlink:href="https://help.gnome.org/misc/release-notes/3.36/">release notes</link>.</para>
</listitem> </listitem>
<listitem>
<para>
The Cinnamon desktop environment (v4.6) has been added. <varname>services.xserver.desktopManager.cinnamon.enable = true;</varname> to try it out!
Remember that, with any new feature it's possible you could run into issues, so please send all support requests to <link xlink:href="https://github.com/NixOS/nixpkgs/issues">github.com/NixOS/nixpkgs</link> to notify the maintainers.
</para>
</listitem>
<listitem>
<para>
Quickly configure a complete, private, self-hosted video
conferencing solution with the new Jitsi Meet module.
</para>
</listitem>
<listitem> <listitem>
<para> <para>
<package>maxx</package> package removed along with <varname>services.xserver.desktopManager.maxx</varname> module. <package>maxx</package> package removed along with <varname>services.xserver.desktopManager.maxx</varname> module.
@ -128,7 +140,7 @@ GRANT ALL PRIVILEGES ON *.* TO 'mysql'@'localhost' WITH GRANT OPTION;
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Two new option <link linkend="opt-documentation.man.generateCaches">documentation.man.generateCaches</link> The new option <link linkend="opt-documentation.man.generateCaches">documentation.man.generateCaches</link>
has been added to automatically generate the <literal>man-db</literal> caches, which are needed by utilities has been added to automatically generate the <literal>man-db</literal> caches, which are needed by utilities
like <command>whatis</command> and <command>apropos</command>. The caches are generated during the build of like <command>whatis</command> and <command>apropos</command>. The caches are generated during the build of
the NixOS configuration: since this can be expensive when a large number of packages are installed, the the NixOS configuration: since this can be expensive when a large number of packages are installed, the
@ -137,7 +149,7 @@ GRANT ALL PRIVILEGES ON *.* TO 'mysql'@'localhost' WITH GRANT OPTION;
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<varname>services.postfix.sslCACert</varname> was replaced by <varname>services.postfix.tlsTrustedAuthorities</varname> which now defaults to system certifcate authorities. <varname>services.postfix.sslCACert</varname> was replaced by <varname>services.postfix.tlsTrustedAuthorities</varname> which now defaults to system certificate authorities.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
@ -156,6 +168,64 @@ GRANT ALL PRIVILEGES ON *.* TO 'mysql'@'localhost' WITH GRANT OPTION;
Support for built-in LCDs in various pieces of Logitech hardware (keyboards and USB speakers). <varname>hardware.logitech.lcd.enable</varname> enables support for all hardware supported by the g15daemon project. Support for built-in LCDs in various pieces of Logitech hardware (keyboards and USB speakers). <varname>hardware.logitech.lcd.enable</varname> enables support for all hardware supported by the g15daemon project.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
Zabbix now defaults to 5.0, updated from 4.4. Please carefully read through
<link xlink:href="https://www.zabbix.com/documentation/current/manual/installation/upgrade/sources">the upgrade guide</link>
and apply any changes required. Be sure to take special note of the section on
<link xlink:href="https://www.zabbix.com/documentation/current/manual/installation/upgrade_notes_500#enabling_extended_range_of_numeric_float_values">enabling extended range of numeric (float) values</link>
as you will need to apply this database migration manually.
</para>
<para>
If you are using Zabbix Server with a MySQL or MariaDB database you should note that using a character set of <literal>utf8</literal> and a collate of <literal>utf8_bin</literal> has become mandatory with
this release. See the upstream <link xlink:href="https://support.zabbix.com/browse/ZBX-17357">issue</link> for further discussion. Before upgrading you should check the character set and collation used by
your database and ensure they are correct:
<programlisting>
SELECT
default_character_set_name,
default_collation_name
FROM
information_schema.schemata
WHERE
schema_name = 'zabbix';
</programlisting>
If these values are not correct you should take a backup of your database and convert the character set and collation as required. Here is an
<link xlink:href="https://www.zabbix.com/forum/zabbix-help/396573-reinstall-after-upgrade?p=396891#post396891">example</link> of how to do so, taken from
the Zabbix forums:
<programlisting>
ALTER DATABASE `zabbix` DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
-- the following will produce a list of SQL commands you should subsequently execute
SELECT CONCAT("ALTER TABLE ", TABLE_NAME," CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;") AS ExecuteTheString
FROM information_schema.`COLUMNS`
WHERE table_schema = "zabbix" AND COLLATION_NAME = "utf8_general_ci";
</programlisting>
</para>
</listitem>
<listitem>
<para>
The NixOS module system now supports freeform modules as a mix between <literal>types.attrsOf</literal> and <literal>types.submodule</literal>. These allow you to explicitly declare a subset of options while still permitting definitions without an associated option. See <xref linkend='sec-freeform-modules'/> for how to use them.
</para>
</listitem>
<listitem>
<para>
The GRUB module gained support for basic password protection, which
allows to restrict non-default entries in the boot menu to one or more
users. The users and passwords are defined via the option
<option>boot.loader.grub.users</option>.
Note: Password support is only avaiable in GRUB version 2.
</para>
</listitem>
<listitem>
<para>
Following its deprecation in 20.03, the Perl NixOS test driver has been removed.
All remaining tests have been ported to the Python test framework.
Code outside nixpkgs using <filename>make-test.nix</filename> or
<filename>testing.nix</filename> needs to be ported to
<filename>make-test-python.nix</filename> and
<filename>testing-python.nix</filename> respectively.
</para>
</listitem>
</itemizedlist> </itemizedlist>
</section> </section>
@ -175,6 +245,11 @@ GRANT ALL PRIVILEGES ON *.* TO 'mysql'@'localhost' WITH GRANT OPTION;
<para> <para>
There is a new <xref linkend="opt-security.doas.enable"/> module that provides <command>doas</command>, a lighter alternative to <command>sudo</command> with many of the same features. There is a new <xref linkend="opt-security.doas.enable"/> module that provides <command>doas</command>, a lighter alternative to <command>sudo</command> with many of the same features.
</para> </para>
</listitem>
<listitem>
<para>
<link xlink:href="https://hercules-ci.com">Hercules CI</link> Agent is a specialized build agent for projects built with Nix. See the <link xlink:href="https://nixos.org/nixos/options.html#services.hercules-ci-agent">options</link> and <link xlink:href="https://docs.hercules-ci.com/hercules-ci/getting-started/#deploy-agent">setup</link>.
</para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
@ -199,7 +274,7 @@ GRANT ALL PRIVILEGES ON *.* TO 'mysql'@'localhost' WITH GRANT OPTION;
in the source tree for downloaded modules instead of using go's <link in the source tree for downloaded modules instead of using go's <link
xlink:href="https://golang.org/cmd/go/#hdr-Module_proxy_protocol">module xlink:href="https://golang.org/cmd/go/#hdr-Module_proxy_protocol">module
proxy protocol</link>. This storage format is simpler and therefore less proxy protocol</link>. This storage format is simpler and therefore less
likekly to break with future versions of go. As a result likely to break with future versions of go. As a result
<literal>buildGoModule</literal> switched from <literal>buildGoModule</literal> switched from
<literal>modSha256</literal> to the <literal>vendorSha256</literal> <literal>modSha256</literal> to the <literal>vendorSha256</literal>
attribute to pin fetched version data. attribute to pin fetched version data.
@ -211,7 +286,7 @@ GRANT ALL PRIVILEGES ON *.* TO 'mysql'@'localhost' WITH GRANT OPTION;
<link xlink:href="https://grafana.com/docs/grafana/latest/guides/whats-new-in-v6-4/">deprecated in Grafana</link> <link xlink:href="https://grafana.com/docs/grafana/latest/guides/whats-new-in-v6-4/">deprecated in Grafana</link>
and the <package>phantomjs</package> project is and the <package>phantomjs</package> project is
<link xlink:href="https://github.com/ariya/phantomjs/issues/15344#issue-302015362">currently unmaintained</link>. <link xlink:href="https://github.com/ariya/phantomjs/issues/15344#issue-302015362">currently unmaintained</link>.
It can still be enabled by providing <literal>phantomJsSupport = true</literal> to the package instanciation: It can still be enabled by providing <literal>phantomJsSupport = true</literal> to the package instantiation:
<programlisting>{ <programlisting>{
services.grafana.package = pkgs.grafana.overrideAttrs (oldAttrs: rec { services.grafana.package = pkgs.grafana.overrideAttrs (oldAttrs: rec {
phantomJsSupport = false; phantomJsSupport = false;
@ -223,7 +298,7 @@ GRANT ALL PRIVILEGES ON *.* TO 'mysql'@'localhost' WITH GRANT OPTION;
<para> <para>
The <link linkend="opt-services.supybot.enable">supybot</link> module now uses <literal>/var/lib/supybot</literal> The <link linkend="opt-services.supybot.enable">supybot</link> module now uses <literal>/var/lib/supybot</literal>
as its default <link linkend="opt-services.supybot.stateDir">stateDir</link> path if <literal>stateVersion</literal> as its default <link linkend="opt-services.supybot.stateDir">stateDir</link> path if <literal>stateVersion</literal>
is 20.09 or higher. It also enables number of is 20.09 or higher. It also enables a number of
<link xlink:href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Sandboxing">systemd sandboxing options</link> <link xlink:href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Sandboxing">systemd sandboxing options</link>
which may possibly interfere with some plugins. If this is the case you can disable the options through attributes in which may possibly interfere with some plugins. If this is the case you can disable the options through attributes in
<option>systemd.services.supybot.serviceConfig</option>. <option>systemd.services.supybot.serviceConfig</option>.
@ -331,6 +406,20 @@ php.override {
</para> </para>
</listitem> </listitem>
<listitem>
<para>
The ACME module has been overhauled for simplicity and maintainability.
Cert generation now implicitly uses the <literal>acme</literal>
user, and the <literal>security.acme.certs._name_.user</literal> option
has been removed. Instead, certificate access from other services is now
managed through group permissions. The module no longer runs lego
twice under certain conditions, and will correctly renew certificates if
their configuration is changed. Services which reload nginx and httpd after
certificate renewal are now properly configured too so you no longer have
to do this manually if you are using HTTPS enabled virtual hosts. A mechanism
for regenerating certs on demand has also been added and documented.
</para>
</listitem>
<listitem> <listitem>
<para> <para>
Gollum received a major update to version 5.x and you may have to change Gollum received a major update to version 5.x and you may have to change
@ -350,8 +439,8 @@ php.override {
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Add option <literal>services.nginx.enableSandbox</literal> to starting Nginx web server with additional sandbox/hardening options. Nginx web server now starting with additional sandbox/hardening options. By default, write access
By default, write access to <literal>services.nginx.stateDir</literal> is allowed. To allow writing to other folders, to <literal>services.nginx.stateDir</literal> is allowed. To allow writing to other folders,
use <literal>systemd.services.nginx.serviceConfig.ReadWritePaths</literal> use <literal>systemd.services.nginx.serviceConfig.ReadWritePaths</literal>
<programlisting> <programlisting>
systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/www" ]; systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/www" ];
@ -676,11 +765,19 @@ services.dokuwiki."mywiki" = {
<listitem> <listitem>
<para> <para>
The <xref linkend="opt-services.postgresql.dataDir"/> option is now set to <literal>"/var/lib/postgresql/${cfg.package.psqlSchema}"</literal> regardless of your The <xref linkend="opt-services.postgresql.dataDir"/> option is now set to <literal>"/var/lib/postgresql/${cfg.package.psqlSchema}"</literal> regardless of your
<xref linkend="opt-system.stateVersion"/>. Users with an existing postgresql install that have a <xref linkend="opt-system.stateVersion"/> of <literal>17.09</literal> or below <xref linkend="opt-system.stateVersion"/>. Users with an existing postgresql install that have a <xref linkend="opt-system.stateVersion"/> of <literal>17.03</literal> or below
should double check what the value of their <xref linkend="opt-services.postgresql.dataDir"/> option is (<literal>/var/db/postgresql</literal>) and then explicitly should double check what the value of their <xref linkend="opt-services.postgresql.dataDir"/> option is (<literal>/var/db/postgresql</literal>) and then explicitly
set this value to maintain compatibility: set this value to maintain compatibility:
<programlisting> <programlisting>
services.postgresql.dataDir = "/var/db/postgresql"; services.postgresql.dataDir = "/var/db/postgresql";
</programlisting>
</para>
<para>
The postgresql module now expects there to be a database super user account called <literal>postgres</literal> regardless of your <xref linkend="opt-system.stateVersion"/>. Users
with an existing postgresql install that have a <xref linkend="opt-system.stateVersion"/> of <literal>17.03</literal> or below should run the following SQL statements as a
database super admin user before upgrading:
<programlisting>
CREATE ROLE postgres LOGIN SUPERUSER;
</programlisting> </programlisting>
</para> </para>
</listitem> </listitem>
@ -689,6 +786,54 @@ services.postgresql.dataDir = "/var/db/postgresql";
The USBGuard module now removes options and instead hardcodes values for <literal>IPCAccessControlFiles</literal>, <literal>ruleFiles</literal>, and <literal>auditFilePath</literal>. Audit logs can be found in the journal. The USBGuard module now removes options and instead hardcodes values for <literal>IPCAccessControlFiles</literal>, <literal>ruleFiles</literal>, and <literal>auditFilePath</literal>. Audit logs can be found in the journal.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
The NixOS module system now evaluates option definitions more strictly, allowing it to detect a larger set of problems.
As a result, what previously evaluated may not do so anymore.
See <link xlink:href="https://github.com/NixOS/nixpkgs/pull/82743#issuecomment-674520472">the PR that changed this</link> for more info.
</para>
</listitem>
<listitem>
<para>
For NixOS configuration options, the type <literal>loaOf</literal>, after
its initial deprecation in release 20.03, has been removed. In NixOS and
Nixpkgs options using this type have been converted to <literal>attrsOf</literal>.
For more information on this change have look at these links:
<link xlink:href="https://github.com/NixOS/nixpkgs/issues/1800">issue #1800</link>,
<link xlink:href="https://github.com/NixOS/nixpkgs/pull/63103">PR #63103</link>.
</para>
</listitem>
<listitem>
<para>
<literal>config.systemd.services.${name}.path</literal> now returns a list of paths instead of a colon-separated string.
</para>
</listitem>
<listitem>
<para>
Caddy module now uses Caddy v2 by default. Caddy v1 can still be used by setting
<xref linkend="opt-services.caddy.package"/> to <literal>pkgs.caddy1</literal>.
</para>
<para>
New option <xref linkend="opt-services.caddy.adapter"/> has been added.
</para>
</listitem>
<listitem>
<para>
The <link linkend="opt-services.jellyfin.enable">jellyfin</link> module will use and stay on the Jellyfin version <literal>10.5.5</literal>
if <literal>stateVersion</literal> is lower than <literal>20.09</literal>. This is because significant changes were made to the database schema,
and it is highly recommended to backup your instance before upgrading. After making your backup, you can upgrade to the latest version either by
setting your <literal>stateVersion</literal> to <literal>20.09</literal> or higher, or set the <option>services.jellyfin.package</option> to
<literal>pkgs.jellyfin</literal>. If you do not wish to upgrade Jellyfin, but want to change your <literal>stateVersion</literal>, you can set
the value of <option>services.jellyfin.package</option> to <literal>pkgs.jellyfin_10_5</literal>.
</para>
</listitem>
<listitem>
<para>
The <literal>security.rngd</literal> service is now disabled by default.
This choice was made because there's krngd in the linux kernel space making it (for most usecases)
functionally redundent.
</para>
</listitem>
</itemizedlist> </itemizedlist>
</section> </section>
@ -717,6 +862,17 @@ services.postgresql.dataDir = "/var/db/postgresql";
of the default <literal>out</literal> output anymore - if you relied on the of the default <literal>out</literal> output anymore - if you relied on the
<literal>notmuch-emacs-mua</literal> binary or the emacs lisp files, access them via <literal>notmuch-emacs-mua</literal> binary or the emacs lisp files, access them via
the <literal>notmuch.emacs</literal> output. the <literal>notmuch.emacs</literal> output.
Device tree overlay support was improved in
<link xlink:href="https://github.com/NixOS/nixpkgs/pull/79370">#79370</link>
and now uses <xref linkend="opt-hardware.deviceTree.kernelPackage"/>
instead of <option>hardware.deviceTree.base</option>.
<xref linkend="opt-hardware.deviceTree.overlays"/> configuration was
extended to support <literal>.dts</literal> files with symbols.
Device trees can now be filtered by setting
<xref linkend="opt-hardware.deviceTree.filter"/> option.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
@ -757,6 +913,12 @@ services.postgresql.dataDir = "/var/db/postgresql";
Default algorithm for ZRAM swap was changed to <literal>zstd</literal>. Default algorithm for ZRAM swap was changed to <literal>zstd</literal>.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
The installer now enables sshd by default. This improves installation on headless machines especially ARM single-board-computer.
To login through ssh, either a password or an ssh key must be set for the root user or the nixos user.
</para>
</listitem>
<listitem> <listitem>
<para> <para>
The scripted networking system now uses <literal>.link</literal> files in The scripted networking system now uses <literal>.link</literal> files in
@ -907,7 +1069,88 @@ services.transmission.settings.rpc-bind-address = "0.0.0.0";
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
The packages <package>perl</package>, <package>rsync</package> and <package>strace</package> were removed from <option>systemPackages</option>. If you need them, install them again with <code><xref linkend="opt-environment.systemPackages"/> = with pkgs; [ perl rsync strace ];</code> in your <filename>configuration.nix</filename>. Nginx module <literal>nginxModules.fastcgi-cache-purge</literal> renamed to official name <literal>nginxModules.cache-purge</literal>.
Nginx module <literal>nginxModules.ngx_aws_auth</literal> renamed to official name <literal>nginxModules.aws-auth</literal>.
</para>
</listitem>
<listitem>
<para>
The option <option>defaultPackages</option> was added. It installs the packages <package>perl</package>, <package>rsync</package> and <package>strace</package> for now. They were added unconditionally to <option>systemPackages</option> before, but are not strictly necessary for a minimal NixOS install. You can set it to an empty list to have a more minimal system. Be aware that some functionality might still have an impure dependency on those packages, so things might break.
</para>
</listitem>
<listitem>
<para>
The <literal>undervolt</literal> option no longer needs to apply its
settings every 30s. If they still become undone, open an issue and restore
the previous behaviour using <literal>undervolt.useTimer</literal>.
</para>
</listitem>
<listitem>
<para>
Agda has been heavily reworked.
<itemizedlist>
<listitem>
<para>
<literal>agda.mkDerivation</literal> has been heavily changed and
is now located at <package>agdaPackages.mkDerivation</package>.
</para>
</listitem>
<listitem>
<para>
New top-level packages <package>agda</package> and
<literal>agda.withPackages</literal> have been added, the second
of which sets up agda with access to chosen libraries.
</para>
</listitem>
<listitem>
<para>
All agda libraries now live under
<literal>agdaPackages</literal>.
</para>
</listitem>
<listitem>
<para>
Many broken libraries have been removed.
</para>
</listitem>
</itemizedlist>
See the <link
xlink:href="https://nixos.org/nixpkgs/manual/#agda">new
documentation</link> for more information.
</para>
</listitem>
<listitem>
<para>
The <literal>deepin</literal> package set has been removed from
nixpkgs. It was a work in progress to package the
<link xlink:href="https://www.deepin.org/en/dde/">Deepin Desktop Environment (DDE)</link>,
including libraries, tools and applications, and it was still
missing a service to lauch the desktop environment. It has shown
to no longer be a feasible goal due to reasons discussed in
<link xlink:href="https://github.com/NixOS/nixpkgs/issues/94870">issue #94870</link>.
The package <literal>netease-cloud-music</literal> has also been
removed, as it depends on libraries from deepin.
</para>
</listitem>
<listitem>
<para>
The <literal>opendkim</literal> module now uses systemd sandboxing features
to limit the exposure of the system towards the opendkim service.
</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para />
<para>
Kubernetes has been upgraded to 1.19.1, which also means that the
golang version to build it has been bumped to 1.15. This may have
consequences for your existing clusters and their certificates. Please
consider
<link xlink:href="https://relnotes.k8s.io/?markdown=93264">
the release notes for Kubernetes 1.19 carefully
</link>
before upgrading.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>

View file

@ -0,0 +1,80 @@
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-release-21.03">
<title>Release 21.03 (“Okapi”, 2021.03/??)</title>
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-release-21.03-highlights">
<title>Highlights</title>
<para>
In addition to numerous new and upgraded packages, this release has the
following highlights:
</para>
<itemizedlist>
<listitem>
<para>
Support is planned until the end of October 2021, handing over to 21.09.
</para>
</listitem>
</itemizedlist>
</section>
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-release-21.03-new-services">
<title>New Services</title>
<para>
The following new services were added since the last release:
</para>
<itemizedlist>
<listitem>
<para />
</listitem>
</itemizedlist>
</section>
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-release-21.03-incompatibilities">
<title>Backward Incompatibilities</title>
<para>
When upgrading from a previous release, please be aware of the following
incompatible changes:
</para>
<itemizedlist>
<listitem>
<para />
</listitem>
</itemizedlist>
</section>
<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-release-21.03-notable-changes">
<title>Other Notable Changes</title>
<itemizedlist>
<listitem>
<para />
</listitem>
</itemizedlist>
</section>
</section>

View file

@ -3,8 +3,10 @@
minimal ? false minimal ? false
, # Ignored , # Ignored
config ? null config ? null
# Nixpkgs, for qemu, lib and more , # Nixpkgs, for qemu, lib and more
, pkgs pkgs
, # !!! See comment about args in lib/modules.nix
specialArgs ? {}
, # NixOS configuration to add to the VMs , # NixOS configuration to add to the VMs
extraConfigurations ? [] extraConfigurations ? []
}: }:
@ -31,7 +33,7 @@ rec {
nodes: configurations: nodes: configurations:
import ./eval-config.nix { import ./eval-config.nix {
inherit system; inherit system specialArgs;
modules = configurations ++ extraConfigurations; modules = configurations ++ extraConfigurations;
baseModules = (import ../modules/module-list.nix) ++ baseModules = (import ../modules/module-list.nix) ++
[ ../modules/virtualisation/qemu-vm.nix [ ../modules/virtualisation/qemu-vm.nix

View file

@ -24,11 +24,11 @@
check ? true check ? true
, prefix ? [] , prefix ? []
, lib ? import ../../lib , lib ? import ../../lib
, extraModules ? let e = builtins.getEnv "NIXOS_EXTRA_MODULE_PATH";
in if e == "" then [] else [(import e)]
}: }:
let extraArgs_ = extraArgs; pkgs_ = pkgs; let extraArgs_ = extraArgs; pkgs_ = pkgs;
extraModules = let e = builtins.getEnv "NIXOS_EXTRA_MODULE_PATH";
in if e == "" then [] else [(import e)];
in in
let let

View file

@ -20,7 +20,7 @@
<title>Configuration Options</title> <title>Configuration Options</title>
<variablelist xml:id="configuration-variable-list"> <variablelist xml:id="configuration-variable-list">
<xsl:for-each select="attrs"> <xsl:for-each select="attrs">
<xsl:variable name="id" select="concat('opt-', str:replace(str:replace(str:replace(str:replace(attr[@name = 'name']/string/@value, '*', '_'), '&lt;', '_'), '>', '_'), '?', '_'))" /> <xsl:variable name="id" select="concat('opt-', str:replace(str:replace(str:replace(attr[@name = 'name']/string/@value, '*', '_'), '&lt;', '_'), '>', '_'))" />
<varlistentry> <varlistentry>
<term xlink:href="#{$id}"> <term xlink:href="#{$id}">
<xsl:attribute name="xml:id"><xsl:value-of select="$id"/></xsl:attribute> <xsl:attribute name="xml:id"><xsl:value-of select="$id"/></xsl:attribute>

View file

@ -22,9 +22,9 @@ rec {
else throw "Unknown QEMU serial device for system '${pkgs.stdenv.hostPlatform.system}'"; else throw "Unknown QEMU serial device for system '${pkgs.stdenv.hostPlatform.system}'";
qemuBinary = qemuPkg: { qemuBinary = qemuPkg: {
x86_64-linux = "${qemuPkg}/bin/qemu-kvm -cpu host"; x86_64-linux = "${qemuPkg}/bin/qemu-kvm -cpu max";
armv7l-linux = "${qemuPkg}/bin/qemu-system-arm -enable-kvm -machine virt -cpu host"; armv7l-linux = "${qemuPkg}/bin/qemu-system-arm -enable-kvm -machine virt -cpu host";
aarch64-linux = "${qemuPkg}/bin/qemu-system-aarch64 -enable-kvm -machine virt,gic-version=host -cpu host"; aarch64-linux = "${qemuPkg}/bin/qemu-system-aarch64 -enable-kvm -machine virt,gic-version=host -cpu host";
x86_64-darwin = "${qemuPkg}/bin/qemu-kvm -cpu host"; x86_64-darwin = "${qemuPkg}/bin/qemu-kvm -cpu max";
}.${pkgs.stdenv.hostPlatform.system} or "${qemuPkg}/bin/qemu-kvm"; }.${pkgs.stdenv.hostPlatform.system} or "${qemuPkg}/bin/qemu-kvm";
} }

View file

@ -1,75 +0,0 @@
package Logger;
use strict;
use Thread::Queue;
use XML::Writer;
use Encode qw(decode encode);
use Time::HiRes qw(clock_gettime CLOCK_MONOTONIC);
sub new {
my ($class) = @_;
my $logFile = defined $ENV{LOGFILE} ? "$ENV{LOGFILE}" : "/dev/null";
my $log = new XML::Writer(OUTPUT => new IO::File(">$logFile"));
my $self = {
log => $log,
logQueue => Thread::Queue->new()
};
$self->{log}->startTag("logfile");
bless $self, $class;
return $self;
}
sub close {
my ($self) = @_;
$self->{log}->endTag("logfile");
$self->{log}->end;
}
sub drainLogQueue {
my ($self) = @_;
while (defined (my $item = $self->{logQueue}->dequeue_nb())) {
$self->{log}->dataElement("line", sanitise($item->{msg}), 'machine' => $item->{machine}, 'type' => 'serial');
}
}
sub maybePrefix {
my ($msg, $attrs) = @_;
$msg = $attrs->{machine} . ": " . $msg if defined $attrs->{machine};
return $msg;
}
sub nest {
my ($self, $msg, $coderef, $attrs) = @_;
print STDERR maybePrefix("$msg\n", $attrs);
$self->{log}->startTag("nest");
$self->{log}->dataElement("head", $msg, %{$attrs});
my $now = clock_gettime(CLOCK_MONOTONIC);
$self->drainLogQueue();
eval { &$coderef };
my $res = $@;
$self->drainLogQueue();
$self->log(sprintf("(%.2f seconds)", clock_gettime(CLOCK_MONOTONIC) - $now));
$self->{log}->endTag("nest");
die $@ if $@;
}
sub sanitise {
my ($s) = @_;
$s =~ s/[[:cntrl:]\xff]//g;
$s = decode('UTF-8', $s, Encode::FB_DEFAULT);
return encode('UTF-8', $s, Encode::FB_CROAK);
}
sub log {
my ($self, $msg, $attrs) = @_;
chomp $msg;
print STDERR maybePrefix("$msg\n", $attrs);
$self->drainLogQueue();
$self->{log}->dataElement("line", $msg, %{$attrs});
}
1;

View file

@ -1,734 +0,0 @@
package Machine;
use strict;
use threads;
use Socket;
use IO::Handle;
use POSIX qw(dup2);
use FileHandle;
use Cwd;
use File::Basename;
use File::Path qw(make_path);
use File::Slurp;
use Time::HiRes qw(clock_gettime CLOCK_MONOTONIC);
my $showGraphics = defined $ENV{'DISPLAY'};
my $sharedDir;
sub new {
my ($class, $args) = @_;
my $startCommand = $args->{startCommand};
my $name = $args->{name};
if (!$name) {
$startCommand =~ /run-(.*)-vm$/ if defined $startCommand;
$name = $1 || "machine";
}
if (!$startCommand) {
# !!! merge with qemu-vm.nix.
my $netBackend = "-netdev user,id=net0";
my $netFrontend = "-device virtio-net-pci,netdev=net0";
$netBackend .= "," . $args->{netBackendArgs}
if defined $args->{netBackendArgs};
$netFrontend .= "," . $args->{netFrontendArgs}
if defined $args->{netFrontendArgs};
$startCommand =
"qemu-kvm -m 384 $netBackend $netFrontend \$QEMU_OPTS ";
if (defined $args->{hda}) {
if ($args->{hdaInterface} eq "scsi") {
$startCommand .= "-drive id=hda,file="
. Cwd::abs_path($args->{hda})
. ",werror=report,if=none "
. "-device scsi-hd,drive=hda ";
} else {
$startCommand .= "-drive file=" . Cwd::abs_path($args->{hda})
. ",if=" . $args->{hdaInterface}
. ",werror=report ";
}
}
$startCommand .= "-cdrom $args->{cdrom} "
if defined $args->{cdrom};
$startCommand .= "-device piix3-usb-uhci -drive id=usbdisk,file=$args->{usb},if=none,readonly -device usb-storage,drive=usbdisk "
if defined $args->{usb};
$startCommand .= "-bios $args->{bios} "
if defined $args->{bios};
$startCommand .= $args->{qemuFlags} || "";
}
my $tmpDir = $ENV{'TMPDIR'} || "/tmp";
unless (defined $sharedDir) {
$sharedDir = $tmpDir . "/xchg-shared";
make_path($sharedDir, { mode => 0700, owner => $< });
}
my $allowReboot = 0;
$allowReboot = $args->{allowReboot} if defined $args->{allowReboot};
my $self = {
startCommand => $startCommand,
name => $name,
allowReboot => $allowReboot,
booted => 0,
pid => 0,
connected => 0,
socket => undef,
stateDir => "$tmpDir/vm-state-$name",
monitor => undef,
log => $args->{log},
redirectSerial => $args->{redirectSerial} // 1,
};
mkdir $self->{stateDir}, 0700;
bless $self, $class;
return $self;
}
sub log {
my ($self, $msg) = @_;
$self->{log}->log($msg, { machine => $self->{name} });
}
sub nest {
my ($self, $msg, $coderef, $attrs) = @_;
$self->{log}->nest($msg, $coderef, { %{$attrs || {}}, machine => $self->{name} });
}
sub name {
my ($self) = @_;
return $self->{name};
}
sub stateDir {
my ($self) = @_;
return $self->{stateDir};
}
sub start {
my ($self) = @_;
return if $self->{booted};
$self->log("starting vm");
# Create a socket pair for the serial line input/output of the VM.
my ($serialP, $serialC);
socketpair($serialP, $serialC, PF_UNIX, SOCK_STREAM, 0) or die;
# Create a Unix domain socket to which QEMU's monitor will connect.
my $monitorPath = $self->{stateDir} . "/monitor";
unlink $monitorPath;
my $monitorS;
socket($monitorS, PF_UNIX, SOCK_STREAM, 0) or die;
bind($monitorS, sockaddr_un($monitorPath)) or die "cannot bind monitor socket: $!";
listen($monitorS, 1) or die;
# Create a Unix domain socket to which the root shell in the guest will connect.
my $shellPath = $self->{stateDir} . "/shell";
unlink $shellPath;
my $shellS;
socket($shellS, PF_UNIX, SOCK_STREAM, 0) or die;
bind($shellS, sockaddr_un($shellPath)) or die "cannot bind shell socket: $!";
listen($shellS, 1) or die;
# Start the VM.
my $pid = fork();
die if $pid == -1;
if ($pid == 0) {
close $serialP;
close $monitorS;
close $shellS;
if ($self->{redirectSerial}) {
open NUL, "</dev/null" or die;
dup2(fileno(NUL), fileno(STDIN));
dup2(fileno($serialC), fileno(STDOUT));
dup2(fileno($serialC), fileno(STDERR));
}
$ENV{TMPDIR} = $self->{stateDir};
$ENV{SHARED_DIR} = $sharedDir;
$ENV{USE_TMPDIR} = 1;
$ENV{QEMU_OPTS} =
($self->{allowReboot} ? "" : "-no-reboot ") .
"-monitor unix:./monitor -chardev socket,id=shell,path=./shell " .
"-device virtio-serial -device virtconsole,chardev=shell " .
"-device virtio-rng-pci " .
($showGraphics ? "-serial stdio" : "-nographic") . " " . ($ENV{QEMU_OPTS} || "");
chdir $self->{stateDir} or die;
exec $self->{startCommand};
die "running VM script: $!";
}
# Process serial line output.
close $serialC;
threads->create(\&processSerialOutput, $self, $serialP)->detach;
sub processSerialOutput {
my ($self, $serialP) = @_;
while (<$serialP>) {
chomp;
s/\r$//;
print STDERR $self->{name}, "# $_\n";
$self->{log}->{logQueue}->enqueue({msg => $_, machine => $self->{name}}); # !!!
}
}
eval {
local $SIG{CHLD} = sub { die "QEMU died prematurely\n"; };
# Wait until QEMU connects to the monitor.
accept($self->{monitor}, $monitorS) or die;
# Wait until QEMU connects to the root shell socket. QEMU
# does so immediately; this doesn't mean that the root shell
# has connected yet inside the guest.
accept($self->{socket}, $shellS) or die;
$self->{socket}->autoflush(1);
};
die "$@" if $@;
$self->waitForMonitorPrompt;
$self->log("QEMU running (pid $pid)");
$self->{pid} = $pid;
$self->{booted} = 1;
}
# Send a command to the monitor and wait for it to finish. TODO: QEMU
# also has a JSON-based monitor interface now, but it doesn't support
# all commands yet. We should use it once it does.
sub sendMonitorCommand {
my ($self, $command) = @_;
$self->log("sending monitor command: $command");
syswrite $self->{monitor}, "$command\n";
return $self->waitForMonitorPrompt;
}
# Wait until the monitor sends "(qemu) ".
sub waitForMonitorPrompt {
my ($self) = @_;
my $res = "";
my $s;
while (sysread($self->{monitor}, $s, 1024)) {
$res .= $s;
last if $res =~ s/\(qemu\) $//;
}
return $res;
}
# Call the given code reference repeatedly, with 1 second intervals,
# until it returns 1 or a timeout is reached.
sub retry {
my ($coderef) = @_;
my $n;
for ($n = 899; $n >=0; $n--) {
return if &$coderef($n);
sleep 1;
}
die "action timed out after $n seconds";
}
sub connect {
my ($self) = @_;
return if $self->{connected};
$self->nest("waiting for the VM to finish booting", sub {
$self->start;
my $now = clock_gettime(CLOCK_MONOTONIC);
local $SIG{ALRM} = sub { die "timed out waiting for the VM to connect\n"; };
alarm 600;
readline $self->{socket} or die "the VM quit before connecting\n";
alarm 0;
$self->log("connected to guest root shell");
# We're interested in tracking how close we are to `alarm`.
$self->log(sprintf("(connecting took %.2f seconds)", clock_gettime(CLOCK_MONOTONIC) - $now));
$self->{connected} = 1;
});
}
sub waitForShutdown {
my ($self) = @_;
return unless $self->{booted};
$self->nest("waiting for the VM to power off", sub {
waitpid $self->{pid}, 0;
$self->{pid} = 0;
$self->{booted} = 0;
$self->{connected} = 0;
});
}
sub isUp {
my ($self) = @_;
return $self->{booted} && $self->{connected};
}
sub execute_ {
my ($self, $command) = @_;
$self->connect;
print { $self->{socket} } ("( $command ); echo '|!=EOF' \$?\n");
my $out = "";
while (1) {
my $line = readline($self->{socket});
die "connection to VM lost unexpectedly" unless defined $line;
#$self->log("got line: $line");
if ($line =~ /^(.*)\|\!\=EOF\s+(\d+)$/) {
$out .= $1;
$self->log("exit status $2");
return ($2, $out);
}
$out .= $line;
}
}
sub execute {
my ($self, $command) = @_;
my @res;
$self->nest("running command: $command", sub {
@res = $self->execute_($command);
});
return @res;
}
sub succeed {
my ($self, @commands) = @_;
my $res;
foreach my $command (@commands) {
$self->nest("must succeed: $command", sub {
my ($status, $out) = $self->execute_($command);
if ($status != 0) {
$self->log("output: $out");
die "command `$command' did not succeed (exit code $status)\n";
}
$res .= $out;
});
}
return $res;
}
sub mustSucceed {
succeed @_;
}
sub waitUntilSucceeds {
my ($self, $command) = @_;
$self->nest("waiting for success: $command", sub {
retry sub {
my ($status, $out) = $self->execute($command);
return 1 if $status == 0;
};
});
}
sub waitUntilFails {
my ($self, $command) = @_;
$self->nest("waiting for failure: $command", sub {
retry sub {
my ($status, $out) = $self->execute($command);
return 1 if $status != 0;
};
});
}
sub fail {
my ($self, $command) = @_;
$self->nest("must fail: $command", sub {
my ($status, $out) = $self->execute_($command);
die "command `$command' unexpectedly succeeded"
if $status == 0;
});
}
sub mustFail {
fail @_;
}
sub getUnitInfo {
my ($self, $unit, $user) = @_;
my ($status, $lines) = $self->systemctl("--no-pager show \"$unit\"", $user);
return undef if $status != 0;
my $info = {};
foreach my $line (split '\n', $lines) {
$line =~ /^([^=]+)=(.*)$/ or next;
$info->{$1} = $2;
}
return $info;
}
sub systemctl {
my ($self, $q, $user) = @_;
if ($user) {
$q =~ s/'/\\'/g;
return $self->execute("su -l $user -c \$'XDG_RUNTIME_DIR=/run/user/`id -u` systemctl --user $q'");
}
return $self->execute("systemctl $q");
}
# Fail if the given systemd unit is not in the "active" state.
sub requireActiveUnit {
my ($self, $unit) = @_;
$self->nest("checking if unit $unit has reached state 'active'", sub {
my $info = $self->getUnitInfo($unit);
my $state = $info->{ActiveState};
if ($state ne "active") {
die "Expected unit $unit to to be in state 'active' but it is in state $state\n";
};
});
}
# Wait for a systemd unit to reach the "active" state.
sub waitForUnit {
my ($self, $unit, $user) = @_;
$self->nest("waiting for unit $unit", sub {
retry sub {
my $info = $self->getUnitInfo($unit, $user);
my $state = $info->{ActiveState};
die "unit $unit reached state $state\n" if $state eq "failed";
if ($state eq "inactive") {
# If there are no pending jobs, then assume this unit
# will never reach active state.
my ($status, $jobs) = $self->systemctl("list-jobs --full 2>&1", $user);
if ($jobs =~ /No jobs/) { # FIXME: fragile
# Handle the case where the unit may have started
# between the previous getUnitInfo() and
# list-jobs.
my $info2 = $self->getUnitInfo($unit);
die "unit $unit is inactive and there are no pending jobs\n"
if $info2->{ActiveState} eq $state;
}
}
return 1 if $state eq "active";
};
});
}
sub waitForJob {
my ($self, $jobName) = @_;
return $self->waitForUnit($jobName);
}
# Wait until the specified file exists.
sub waitForFile {
my ($self, $fileName) = @_;
$self->nest("waiting for file $fileName", sub {
retry sub {
my ($status, $out) = $self->execute("test -e $fileName");
return 1 if $status == 0;
}
});
}
sub startJob {
my ($self, $jobName, $user) = @_;
$self->systemctl("start $jobName", $user);
# FIXME: check result
}
sub stopJob {
my ($self, $jobName, $user) = @_;
$self->systemctl("stop $jobName", $user);
}
# Wait until the machine is listening on the given TCP port.
sub waitForOpenPort {
my ($self, $port) = @_;
$self->nest("waiting for TCP port $port", sub {
retry sub {
my ($status, $out) = $self->execute("nc -z localhost $port");
return 1 if $status == 0;
}
});
}
# Wait until the machine is not listening on the given TCP port.
sub waitForClosedPort {
my ($self, $port) = @_;
retry sub {
my ($status, $out) = $self->execute("nc -z localhost $port");
return 1 if $status != 0;
}
}
sub shutdown {
my ($self) = @_;
return unless $self->{booted};
print { $self->{socket} } ("poweroff\n");
$self->waitForShutdown;
}
sub crash {
my ($self) = @_;
return unless $self->{booted};
$self->log("forced crash");
$self->sendMonitorCommand("quit");
$self->waitForShutdown;
}
# Make the machine unreachable by shutting down eth1 (the multicast
# interface used to talk to the other VMs). We keep eth0 up so that
# the test driver can continue to talk to the machine.
sub block {
my ($self) = @_;
$self->sendMonitorCommand("set_link virtio-net-pci.1 off");
}
# Make the machine reachable.
sub unblock {
my ($self) = @_;
$self->sendMonitorCommand("set_link virtio-net-pci.1 on");
}
# Take a screenshot of the X server on :0.0.
sub screenshot {
my ($self, $filename) = @_;
my $dir = $ENV{'out'} || Cwd::abs_path(".");
$filename = "$dir/${filename}.png" if $filename =~ /^\w+$/;
my $tmp = "${filename}.ppm";
my $name = basename($filename);
$self->nest("making screenshot $name", sub {
$self->sendMonitorCommand("screendump $tmp");
system("pnmtopng $tmp > ${filename}") == 0
or die "cannot convert screenshot";
unlink $tmp;
}, { image => $name } );
}
# Get the text of TTY<n>
sub getTTYText {
my ($self, $tty) = @_;
my ($status, $out) = $self->execute("fold -w\$(stty -F /dev/tty${tty} size | awk '{print \$2}') /dev/vcs${tty}");
return $out;
}
# Wait until TTY<n>'s text matches a particular regular expression
sub waitUntilTTYMatches {
my ($self, $tty, $regexp) = @_;
$self->nest("waiting for $regexp to appear on tty $tty", sub {
retry sub {
my ($retries_remaining) = @_;
if ($retries_remaining == 0) {
$self->log("Last chance to match /$regexp/ on TTY$tty, which currently contains:");
$self->log($self->getTTYText($tty));
}
return 1 if $self->getTTYText($tty) =~ /$regexp/;
}
});
}
# Debugging: Dump the contents of the TTY<n>
sub dumpTTYContents {
my ($self, $tty) = @_;
$self->execute("fold -w 80 /dev/vcs${tty} | systemd-cat");
}
# Take a screenshot and return the result as text using optical character
# recognition.
sub getScreenText {
my ($self) = @_;
system("command -v tesseract &> /dev/null") == 0
or die "getScreenText used but enableOCR is false";
my $text;
$self->nest("performing optical character recognition", sub {
my $tmpbase = Cwd::abs_path(".")."/ocr";
my $tmpin = $tmpbase."in.ppm";
$self->sendMonitorCommand("screendump $tmpin");
my $magickArgs = "-filter Catrom -density 72 -resample 300 "
. "-contrast -normalize -despeckle -type grayscale "
. "-sharpen 1 -posterize 3 -negate -gamma 100 "
. "-blur 1x65535";
my $tessArgs = "-c debug_file=/dev/null --psm 11 --oem 2";
$text = `convert $magickArgs $tmpin tiff:- | tesseract - - $tessArgs`;
my $status = $? >> 8;
unlink $tmpin;
die "OCR failed with exit code $status" if $status != 0;
});
return $text;
}
# Wait until a specific regexp matches the textual contents of the screen.
sub waitForText {
my ($self, $regexp) = @_;
$self->nest("waiting for $regexp to appear on the screen", sub {
retry sub {
my ($retries_remaining) = @_;
if ($retries_remaining == 0) {
$self->log("Last chance to match /$regexp/ on the screen, which currently contains:");
$self->log($self->getScreenText);
}
return 1 if $self->getScreenText =~ /$regexp/;
}
});
}
# Wait until it is possible to connect to the X server. Note that
# testing the existence of /tmp/.X11-unix/X0 is insufficient.
sub waitForX {
my ($self, $regexp) = @_;
$self->nest("waiting for the X11 server", sub {
retry sub {
my ($status, $out) = $self->execute("journalctl -b SYSLOG_IDENTIFIER=systemd | grep 'Reached target Current graphical'");
return 0 if $status != 0;
($status, $out) = $self->execute("[ -e /tmp/.X11-unix/X0 ]");
return 1 if $status == 0;
}
});
}
sub getWindowNames {
my ($self) = @_;
my $res = $self->mustSucceed(
q{xwininfo -root -tree | sed 's/.*0x[0-9a-f]* \"\([^\"]*\)\".*/\1/; t; d'});
return split /\n/, $res;
}
sub waitForWindow {
my ($self, $regexp) = @_;
$self->nest("waiting for a window to appear", sub {
retry sub {
my @names = $self->getWindowNames;
my ($retries_remaining) = @_;
if ($retries_remaining == 0) {
$self->log("Last chance to match /$regexp/ on the the window list, which currently contains:");
$self->log(join(", ", @names));
}
foreach my $n (@names) {
return 1 if $n =~ /$regexp/;
}
}
});
}
sub copyFileFromHost {
my ($self, $from, $to) = @_;
my $s = `cat $from` or die;
$s =~ s/'/'\\''/g;
$self->mustSucceed("echo '$s' > $to");
}
my %charToKey = (
'A' => "shift-a", 'N' => "shift-n", '-' => "0x0C", '_' => "shift-0x0C", '!' => "shift-0x02",
'B' => "shift-b", 'O' => "shift-o", '=' => "0x0D", '+' => "shift-0x0D", '@' => "shift-0x03",
'C' => "shift-c", 'P' => "shift-p", '[' => "0x1A", '{' => "shift-0x1A", '#' => "shift-0x04",
'D' => "shift-d", 'Q' => "shift-q", ']' => "0x1B", '}' => "shift-0x1B", '$' => "shift-0x05",
'E' => "shift-e", 'R' => "shift-r", ';' => "0x27", ':' => "shift-0x27", '%' => "shift-0x06",
'F' => "shift-f", 'S' => "shift-s", '\'' => "0x28", '"' => "shift-0x28", '^' => "shift-0x07",
'G' => "shift-g", 'T' => "shift-t", '`' => "0x29", '~' => "shift-0x29", '&' => "shift-0x08",
'H' => "shift-h", 'U' => "shift-u", '\\' => "0x2B", '|' => "shift-0x2B", '*' => "shift-0x09",
'I' => "shift-i", 'V' => "shift-v", ',' => "0x33", '<' => "shift-0x33", '(' => "shift-0x0A",
'J' => "shift-j", 'W' => "shift-w", '.' => "0x34", '>' => "shift-0x34", ')' => "shift-0x0B",
'K' => "shift-k", 'X' => "shift-x", '/' => "0x35", '?' => "shift-0x35",
'L' => "shift-l", 'Y' => "shift-y", ' ' => "spc",
'M' => "shift-m", 'Z' => "shift-z", "\n" => "ret",
);
sub sendKeys {
my ($self, @keys) = @_;
foreach my $key (@keys) {
$key = $charToKey{$key} if exists $charToKey{$key};
$self->sendMonitorCommand("sendkey $key");
}
}
sub sendChars {
my ($self, $chars) = @_;
$self->nest("sending keys $chars", sub {
$self->sendKeys(split //, $chars);
});
}
# Sleep N seconds (in virtual guest time, not real time).
sub sleep {
my ($self, $time) = @_;
$self->succeed("sleep $time");
}
# Forward a TCP port on the host to a TCP port on the guest. Useful
# during interactive testing.
sub forwardPort {
my ($self, $hostPort, $guestPort) = @_;
$hostPort = 8080 unless defined $hostPort;
$guestPort = 80 unless defined $guestPort;
$self->sendMonitorCommand("hostfwd_add tcp::$hostPort-:$guestPort");
}
1;

View file

@ -1,191 +0,0 @@
#! /somewhere/perl -w
use strict;
use Machine;
use Term::ReadLine;
use IO::File;
use IO::Pty;
use Logger;
use Cwd;
use POSIX qw(_exit dup2);
use Time::HiRes qw(clock_gettime CLOCK_MONOTONIC);
$SIG{PIPE} = 'IGNORE'; # because Unix domain sockets may die unexpectedly
STDERR->autoflush(1);
my $log = new Logger;
# Start vde_switch for each network required by the test.
my %vlans;
foreach my $vlan (split / /, $ENV{VLANS} || "") {
next if defined $vlans{$vlan};
# Start vde_switch as a child process. We don't run it in daemon
# mode because we want the child process to be cleaned up when we
# die. Since we have to make sure that the control socket is
# ready, we send a dummy command to vde_switch (via stdin) and
# wait for a reply. Note that vde_switch requires stdin to be a
# TTY, so we create one.
$log->log("starting VDE switch for network $vlan");
my $socket = Cwd::abs_path "./vde$vlan.ctl";
my $pty = new IO::Pty;
my ($stdoutR, $stdoutW); pipe $stdoutR, $stdoutW;
my $pid = fork(); die "cannot fork" unless defined $pid;
if ($pid == 0) {
dup2(fileno($pty->slave), 0);
dup2(fileno($stdoutW), 1);
exec "vde_switch -s $socket --dirmode 0700" or _exit(1);
}
close $stdoutW;
print $pty "version\n";
readline $stdoutR or die "cannot start vde_switch";
$ENV{"QEMU_VDE_SOCKET_$vlan"} = $socket;
$vlans{$vlan} = $pty;
die unless -e "$socket/ctl";
}
my %vms;
my $context = "";
sub createMachine {
my ($args) = @_;
my $vm = Machine->new({%{$args}, log => $log, redirectSerial => ($ENV{USE_SERIAL} // "0") ne "1"});
$vms{$vm->name} = $vm;
$context .= "my \$" . $vm->name . " = \$vms{'" . $vm->name . "'}; ";
return $vm;
}
foreach my $vmScript (@ARGV) {
my $vm = createMachine({startCommand => $vmScript});
}
sub startAll {
$log->nest("starting all VMs", sub {
$_->start foreach values %vms;
});
}
# Wait until all VMs have terminated.
sub joinAll {
$log->nest("waiting for all VMs to finish", sub {
$_->waitForShutdown foreach values %vms;
});
}
# In interactive tests, this allows the non-interactive test script to
# be executed conveniently.
sub testScript {
eval "$context $ENV{testScript};\n";
warn $@ if $@;
}
my $nrTests = 0;
my $nrSucceeded = 0;
sub subtest {
my ($name, $coderef) = @_;
$log->nest("subtest: $name", sub {
$nrTests++;
eval { &$coderef };
if ($@) {
$log->log("error: $@", { error => 1 });
} else {
$nrSucceeded++;
}
});
}
sub runTests {
if (defined $ENV{tests}) {
$log->nest("running the VM test script", sub {
eval "$context $ENV{tests}";
if ($@) {
$log->log("error: $@", { error => 1 });
die $@;
}
}, { expanded => 1 });
} else {
my $term = Term::ReadLine->new('nixos-vm-test');
$term->ReadHistory;
while (defined ($_ = $term->readline("> "))) {
eval "$context $_\n";
warn $@ if $@;
}
$term->WriteHistory;
}
# Copy the kernel coverage data for each machine, if the kernel
# has been compiled with coverage instrumentation.
$log->nest("collecting coverage data", sub {
foreach my $vm (values %vms) {
my $gcovDir = "/sys/kernel/debug/gcov";
next unless $vm->isUp();
my ($status, $out) = $vm->execute("test -e $gcovDir");
next if $status != 0;
# Figure out where to put the *.gcda files so that the
# report generator can find the corresponding kernel
# sources.
my $kernelDir = $vm->mustSucceed("echo \$(dirname \$(readlink -f /run/current-system/kernel))/.build/linux-*");
chomp $kernelDir;
my $coverageDir = "/tmp/xchg/coverage-data/$kernelDir";
# Copy all the *.gcda files.
$vm->execute("for d in $gcovDir/nix/store/*/.build/linux-*; do for i in \$(cd \$d && find -name '*.gcda'); do echo \$i; mkdir -p $coverageDir/\$(dirname \$i); cp -v \$d/\$i $coverageDir/\$i; done; done");
}
});
$log->nest("syncing", sub {
foreach my $vm (values %vms) {
next unless $vm->isUp();
$vm->execute("sync");
}
});
if ($nrTests != 0) {
$log->log("$nrSucceeded out of $nrTests tests succeeded",
($nrSucceeded < $nrTests ? { error => 1 } : { }));
}
}
# Create an empty raw virtual disk with the given name and size (in
# MiB).
sub createDisk {
my ($name, $size) = @_;
system("qemu-img create -f raw $name ${size}M") == 0
or die "cannot create image of size $size";
}
END {
$log->nest("cleaning up", sub {
foreach my $vm (values %vms) {
if ($vm->{pid}) {
$log->log("killing " . $vm->{name} . " (pid " . $vm->{pid} . ")");
kill 9, $vm->{pid};
}
}
});
$log->close();
}
my $now1 = clock_gettime(CLOCK_MONOTONIC);
runTests;
my $now2 = clock_gettime(CLOCK_MONOTONIC);
printf STDERR "test script finished in %.2fs\n", $now2 - $now1;
exit ($nrSucceeded < $nrTests ? 1 : 0);

View file

@ -217,7 +217,7 @@ class Machine:
match = re.search("run-(.+)-vm$", cmd) match = re.search("run-(.+)-vm$", cmd)
if match: if match:
self.name = match.group(1) self.name = match.group(1)
self.logger = args["log"]
self.script = args.get("startCommand", self.create_startcommand(args)) self.script = args.get("startCommand", self.create_startcommand(args))
tmp_dir = os.environ.get("TMPDIR", tempfile.gettempdir()) tmp_dir = os.environ.get("TMPDIR", tempfile.gettempdir())
@ -227,7 +227,10 @@ class Machine:
os.makedirs(path, mode=0o700, exist_ok=True) os.makedirs(path, mode=0o700, exist_ok=True)
return path return path
self.state_dir = create_dir("vm-state-{}".format(self.name)) self.state_dir = os.path.join(tmp_dir, f"vm-state-{self.name}")
if not args.get("keepVmState", False):
self.cleanup_statedir()
os.makedirs(self.state_dir, mode=0o700, exist_ok=True)
self.shared_dir = create_dir("shared-xchg") self.shared_dir = create_dir("shared-xchg")
self.booted = False self.booted = False
@ -235,7 +238,6 @@ class Machine:
self.pid: Optional[int] = None self.pid: Optional[int] = None
self.socket = None self.socket = None
self.monitor: Optional[socket.socket] = None self.monitor: Optional[socket.socket] = None
self.logger: Logger = args["log"]
self.allow_reboot = args.get("allowReboot", False) self.allow_reboot = args.get("allowReboot", False)
@staticmethod @staticmethod
@ -424,15 +426,18 @@ class Machine:
output += out output += out
return output return output
def fail(self, *commands: str) -> None: def fail(self, *commands: str) -> str:
"""Execute each command and check that it fails.""" """Execute each command and check that it fails."""
output = ""
for command in commands: for command in commands:
with self.nested("must fail: {}".format(command)): with self.nested("must fail: {}".format(command)):
status, output = self.execute(command) (status, out) = self.execute(command)
if status == 0: if status == 0:
raise Exception( raise Exception(
"command `{}` unexpectedly succeeded".format(command) "command `{}` unexpectedly succeeded".format(command)
) )
output += out
return output
def wait_until_succeeds(self, command: str) -> str: def wait_until_succeeds(self, command: str) -> str:
"""Wait until a command returns success and return its output. """Wait until a command returns success and return its output.
@ -777,9 +782,10 @@ class Machine:
self.log("QEMU running (pid {})".format(self.pid)) self.log("QEMU running (pid {})".format(self.pid))
def cleanup_statedir(self) -> None: def cleanup_statedir(self) -> None:
self.log("delete the VM state directory") if os.path.isdir(self.state_dir):
if os.path.isfile(self.state_dir):
shutil.rmtree(self.state_dir) shutil.rmtree(self.state_dir)
self.logger.log(f"deleting VM state directory {self.state_dir}")
self.logger.log("if you want to keep the VM state, pass --keep-vm-state")
def shutdown(self) -> None: def shutdown(self) -> None:
if not self.booted: if not self.booted:
@ -837,7 +843,8 @@ class Machine:
retry(window_is_visible) retry(window_is_visible)
def sleep(self, secs: int) -> None: def sleep(self, secs: int) -> None:
time.sleep(secs) # We want to sleep in *guest* time, not *host* time.
self.succeed(f"sleep {secs}")
def forward_port(self, host_port: int = 8080, guest_port: int = 80) -> None: def forward_port(self, host_port: int = 8080, guest_port: int = 80) -> None:
"""Forward a TCP port on the host to a TCP port on the guest. """Forward a TCP port on the host to a TCP port on the guest.
@ -936,10 +943,10 @@ if __name__ == "__main__":
for nr, vde_socket, _, _ in vde_sockets: for nr, vde_socket, _, _ in vde_sockets:
os.environ["QEMU_VDE_SOCKET_{}".format(nr)] = vde_socket os.environ["QEMU_VDE_SOCKET_{}".format(nr)] = vde_socket
machines = [create_machine({"startCommand": s}) for s in vm_scripts] machines = [
for machine in machines: create_machine({"startCommand": s, "keepVmState": cli_args.keep_vm_state})
if not cli_args.keep_vm_state: for s in vm_scripts
machine.cleanup_statedir() ]
machine_eval = [ machine_eval = [
"{0} = machines[{1}]".format(m.name, idx) for idx, m in enumerate(machines) "{0} = machines[{1}]".format(m.name, idx) for idx, m in enumerate(machines)
] ]

View file

@ -4,10 +4,12 @@
, minimal ? false , minimal ? false
# Ignored # Ignored
, config ? {} , config ? {}
# !!! See comment about args in lib/modules.nix
, specialArgs ? {}
# Modules to add to each VM # Modules to add to each VM
, extraConfigurations ? [] }: , extraConfigurations ? [] }:
with import ./build-vms.nix { inherit system pkgs minimal extraConfigurations; }; with import ./build-vms.nix { inherit system pkgs minimal specialArgs extraConfigurations; };
with pkgs; with pkgs;
rec { rec {
@ -63,18 +65,12 @@ rec {
mkdir -p $out mkdir -p $out
LOGFILE=/dev/null tests='exec(os.environ["testScript"])' ${driver}/bin/nixos-test-driver LOGFILE=/dev/null tests='exec(os.environ["testScript"])' ${driver}/bin/nixos-test-driver
for i in */xchg/coverage-data; do
mkdir -p $out/coverage-data
mv $i $out/coverage-data/$(dirname $(dirname $i))
done
''; '';
}; };
makeTest = makeTest =
{ testScript { testScript
, makeCoverageReport ? false
, enableOCR ? false , enableOCR ? false
, name ? "unnamed" , name ? "unnamed"
# Skip linting (mainly intended for faster dev cycles) # Skip linting (mainly intended for faster dev cycles)
@ -153,7 +149,6 @@ rec {
}; };
test = passMeta (runTests driver); test = passMeta (runTests driver);
report = passMeta (releaseTools.gcovReport { coverageRuns = [ test ]; });
nodeNames = builtins.attrNames nodes; nodeNames = builtins.attrNames nodes;
invalidNodeNames = lib.filter invalidNodeNames = lib.filter
@ -169,7 +164,7 @@ rec {
Please stick to alphanumeric chars and underscores as separation. Please stick to alphanumeric chars and underscores as separation.
'' ''
else else
(if makeCoverageReport then report else test) // { test // {
inherit nodes driver test; inherit nodes driver test;
}; };

View file

@ -1,258 +0,0 @@
{ system
, pkgs ? import ../.. { inherit system config; }
# Use a minimal kernel?
, minimal ? false
# Ignored
, config ? {}
# Modules to add to each VM
, extraConfigurations ? [] }:
with import ./build-vms.nix { inherit system pkgs minimal extraConfigurations; };
with pkgs;
rec {
inherit pkgs;
testDriver = lib.warn ''
Perl VM tests are deprecated and will be removed for 20.09.
Please update your tests to use the python test driver.
See https://github.com/NixOS/nixpkgs/pull/71684 for details.
'' stdenv.mkDerivation {
name = "nixos-test-driver";
buildInputs = [ makeWrapper perl ];
dontUnpack = true;
preferLocalBuild = true;
installPhase =
''
mkdir -p $out/bin
cp ${./test-driver/test-driver.pl} $out/bin/nixos-test-driver
chmod u+x $out/bin/nixos-test-driver
libDir=$out/${perl.libPrefix}
mkdir -p $libDir
cp ${./test-driver/Machine.pm} $libDir/Machine.pm
cp ${./test-driver/Logger.pm} $libDir/Logger.pm
wrapProgram $out/bin/nixos-test-driver \
--prefix PATH : "${lib.makeBinPath [ qemu_test vde2 netpbm coreutils ]}" \
--prefix PERL5LIB : "${with perlPackages; makePerlPath [ TermReadLineGnu XMLWriter IOTty FileSlurp ]}:$out/${perl.libPrefix}"
'';
};
# Run an automated test suite in the given virtual network.
# `driver' is the script that runs the network.
runTests = driver:
stdenv.mkDerivation {
name = "vm-test-run-${driver.testName}";
requiredSystemFeatures = [ "kvm" "nixos-test" ];
buildCommand =
''
mkdir -p $out
LOGFILE=/dev/null tests='eval $ENV{testScript}; die $@ if $@;' ${driver}/bin/nixos-test-driver
for i in */xchg/coverage-data; do
mkdir -p $out/coverage-data
mv $i $out/coverage-data/$(dirname $(dirname $i))
done
'';
};
makeTest =
{ testScript
, makeCoverageReport ? false
, enableOCR ? false
, name ? "unnamed"
, ...
} @ t:
let
# A standard store path to the vm monitor is built like this:
# /tmp/nix-build-vm-test-run-$name.drv-0/vm-state-machine/monitor
# The max filename length of a unix domain socket is 108 bytes.
# This means $name can at most be 50 bytes long.
maxTestNameLen = 50;
testNameLen = builtins.stringLength name;
testDriverName = with builtins;
if testNameLen > maxTestNameLen then
abort ("The name of the test '${name}' must not be longer than ${toString maxTestNameLen} " +
"it's currently ${toString testNameLen} characters long.")
else
"nixos-test-driver-${name}";
nodes = buildVirtualNetwork (
t.nodes or (if t ? machine then { machine = t.machine; } else { }));
testScript' =
# Call the test script with the computed nodes.
if lib.isFunction testScript
then testScript { inherit nodes; }
else testScript;
vlans = map (m: m.config.virtualisation.vlans) (lib.attrValues nodes);
vms = map (m: m.config.system.build.vm) (lib.attrValues nodes);
ocrProg = tesseract4.override { enableLanguages = [ "eng" ]; };
imagemagick_tiff = imagemagick_light.override { inherit libtiff; };
# Generate onvenience wrappers for running the test driver
# interactively with the specified network, and for starting the
# VMs from the command line.
driver = runCommand testDriverName
{ buildInputs = [ makeWrapper];
testScript = testScript';
preferLocalBuild = true;
testName = name;
}
''
mkdir -p $out/bin
echo "$testScript" > $out/test-script
ln -s ${testDriver}/bin/nixos-test-driver $out/bin/
vms=($(for i in ${toString vms}; do echo $i/bin/run-*-vm; done))
wrapProgram $out/bin/nixos-test-driver \
--add-flags "''${vms[*]}" \
${lib.optionalString enableOCR
"--prefix PATH : '${ocrProg}/bin:${imagemagick_tiff}/bin'"} \
--run "export testScript=\"\$(cat $out/test-script)\"" \
--set VLANS '${toString vlans}'
ln -s ${testDriver}/bin/nixos-test-driver $out/bin/nixos-run-vms
wrapProgram $out/bin/nixos-run-vms \
--add-flags "''${vms[*]}" \
${lib.optionalString enableOCR "--prefix PATH : '${ocrProg}/bin'"} \
--set tests 'startAll; joinAll;' \
--set VLANS '${toString vlans}' \
${lib.optionalString (builtins.length vms == 1) "--set USE_SERIAL 1"}
''; # "
passMeta = drv: drv // lib.optionalAttrs (t ? meta) {
meta = (drv.meta or {}) // t.meta;
};
test = passMeta (runTests driver);
report = passMeta (releaseTools.gcovReport { coverageRuns = [ test ]; });
nodeNames = builtins.attrNames nodes;
invalidNodeNames = lib.filter
(node: builtins.match "^[A-z_][A-z0-9_]+$" node == null) nodeNames;
in
if lib.length invalidNodeNames > 0 then
throw ''
Cannot create machines out of (${lib.concatStringsSep ", " invalidNodeNames})!
All machines are referenced as perl variables in the testing framework which will break the
script when special characters are used.
Please stick to alphanumeric chars and underscores as separation.
''
else
(if makeCoverageReport then report else test) // {
inherit nodes driver test;
};
runInMachine =
{ drv
, machine
, preBuild ? ""
, postBuild ? ""
, ... # ???
}:
let
vm = buildVM { }
[ machine
{ key = "run-in-machine";
networking.hostName = "client";
nix.readOnlyStore = false;
virtualisation.writableStore = false;
}
];
buildrunner = writeText "vm-build" ''
source $1
${coreutils}/bin/mkdir -p $TMPDIR
cd $TMPDIR
exec $origBuilder $origArgs
'';
testScript = ''
startAll;
$client->waitForUnit("multi-user.target");
${preBuild}
$client->succeed("env -i ${bash}/bin/bash ${buildrunner} /tmp/xchg/saved-env >&2");
${postBuild}
$client->succeed("sync"); # flush all data before pulling the plug
'';
vmRunCommand = writeText "vm-run" ''
xchg=vm-state-client/xchg
${coreutils}/bin/mkdir $out
${coreutils}/bin/mkdir -p $xchg
for i in $passAsFile; do
i2=''${i}Path
_basename=$(${coreutils}/bin/basename ''${!i2})
${coreutils}/bin/cp ''${!i2} $xchg/$_basename
eval $i2=/tmp/xchg/$_basename
${coreutils}/bin/ls -la $xchg
done
unset i i2 _basename
export | ${gnugrep}/bin/grep -v '^xchg=' > $xchg/saved-env
unset xchg
export tests='${testScript}'
${testDriver}/bin/nixos-test-driver ${vm.config.system.build.vm}/bin/run-*-vm
''; # */
in
lib.overrideDerivation drv (attrs: {
requiredSystemFeatures = [ "kvm" ];
builder = "${bash}/bin/sh";
args = ["-e" vmRunCommand];
origArgs = attrs.args;
origBuilder = attrs.builder;
});
runInMachineWithX = { require ? [], ... } @ args:
let
client =
{ ... }:
{
inherit require;
imports = [
../tests/common/auto.nix
];
virtualisation.memorySize = 1024;
services.xserver.enable = true;
test-support.displayManager.auto.enable = true;
services.xserver.displayManager.defaultSession = "none+icewm";
services.xserver.windowManager.icewm.enable = true;
};
in
runInMachine ({
machine = client;
preBuild =
''
$client->waitForX;
'';
} // args);
simpleTest = as: (makeTest as).test;
}

View file

@ -2,6 +2,11 @@ pkgs: with pkgs.lib;
rec { rec {
# Copy configuration files to avoid having the entire sources in the system closure
copyFile = filePath: pkgs.runCommandNoCC (builtins.unsafeDiscardStringContext (builtins.baseNameOf filePath)) {} ''
cp ${filePath} $out
'';
# Check whenever fileSystem is needed for boot. NOTE: Make sure # Check whenever fileSystem is needed for boot. NOTE: Make sure
# pathsNeededForBoot is closed under the parent relationship, i.e. if /a/b/c # pathsNeededForBoot is closed under the parent relationship, i.e. if /a/b/c
# is in the list, put /a and /a/b in as well. # is in the list, put /a and /a/b in as well.

View file

@ -29,7 +29,7 @@ log() {
echo "$@" >&2 echo "$@" >&2
} }
if [ -z "$1" ]; then if [ "$#" -ne 1 ]; then
log "Usage: ./upload-amazon-image.sh IMAGE_OUTPUT" log "Usage: ./upload-amazon-image.sh IMAGE_OUTPUT"
exit 1 exit 1
fi fi

Some files were not shown because too many files have changed in this diff Show more