Project import generated by Copybara.

GitOrigin-RevId: 5181d5945eda382ff6a9ca3e072ed6ea9b547fee
This commit is contained in:
Default email 2022-04-15 03:41:22 +02:00
parent 29ac5c60c3
commit bb584b27e9
2191 changed files with 48659 additions and 29438 deletions

View file

@ -242,9 +242,8 @@
# Docker tools # Docker tools
/pkgs/build-support/docker @roberth /pkgs/build-support/docker @roberth
/nixos/tests/docker-tools-overlay.nix @roberth /nixos/tests/docker-tools* @roberth
/nixos/tests/docker-tools.nix @roberth /doc/builders/images/dockertools.section.md @roberth
/doc/builders/images/dockertools.xml @roberth
# Blockchains # Blockchains
/pkgs/applications/blockchains @mmahut @RaghavSood /pkgs/applications/blockchains @mmahut @RaghavSood

View file

@ -16,7 +16,7 @@ jobs:
# we don't limit this action to only NixOS repo since the checks are cheap and useful developer feedback # we don't limit this action to only NixOS repo since the checks are cheap and useful developer feedback
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: cachix/install-nix-action@v16 - uses: cachix/install-nix-action@v17
- uses: cachix/cachix-action@v10 - uses: cachix/cachix-action@v10
with: with:
# This cache is for the nixpkgs repo checks and should not be trusted or used elsewhere. # This cache is for the nixpkgs repo checks and should not be trusted or used elsewhere.

View file

@ -28,7 +28,7 @@ jobs:
with: with:
# pull_request_target checks out the base branch by default # pull_request_target checks out the base branch by default
ref: refs/pull/${{ github.event.pull_request.number }}/merge ref: refs/pull/${{ github.event.pull_request.number }}/merge
- uses: cachix/install-nix-action@v16 - uses: cachix/install-nix-action@v17
with: with:
# nixpkgs commit is pinned so that it doesn't break # nixpkgs commit is pinned so that it doesn't break
# editorconfig-checker 2.4.0 # editorconfig-checker 2.4.0

View file

@ -18,7 +18,7 @@ jobs:
with: with:
# pull_request_target checks out the base branch by default # pull_request_target checks out the base branch by default
ref: refs/pull/${{ github.event.pull_request.number }}/merge ref: refs/pull/${{ github.event.pull_request.number }}/merge
- uses: cachix/install-nix-action@v16 - uses: cachix/install-nix-action@v17
with: with:
# explicitly enable sandbox # explicitly enable sandbox
extra_nix_config: sandbox = true extra_nix_config: sandbox = true

View file

@ -18,7 +18,7 @@ jobs:
with: with:
# pull_request_target checks out the base branch by default # pull_request_target checks out the base branch by default
ref: refs/pull/${{ github.event.pull_request.number }}/merge ref: refs/pull/${{ github.event.pull_request.number }}/merge
- uses: cachix/install-nix-action@v16 - uses: cachix/install-nix-action@v17
with: with:
# explicitly enable sandbox # explicitly enable sandbox
extra_nix_config: sandbox = true extra_nix_config: sandbox = true

View file

@ -19,7 +19,7 @@ jobs:
with: with:
# pull_request_target checks out the base branch by default # pull_request_target checks out the base branch by default
ref: refs/pull/${{ github.event.pull_request.number }}/merge ref: refs/pull/${{ github.event.pull_request.number }}/merge
- uses: cachix/install-nix-action@v16 - uses: cachix/install-nix-action@v17
- name: Check DocBook files generated from Markdown are consistent - name: Check DocBook files generated from Markdown are consistent
run: | run: |
nixos/doc/manual/md-to-db.sh nixos/doc/manual/md-to-db.sh

View file

@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: cachix/install-nix-action@v16 - uses: cachix/install-nix-action@v17
- name: setup - name: setup
id: setup id: setup
run: | run: |

View file

@ -20,7 +20,7 @@ Below is a short excerpt of some points in there:
``` ```
(pkg-name | nixos/<module>): (from -> to | init at version | refactor | etc) (pkg-name | nixos/<module>): (from -> to | init at version | refactor | etc)
(Motivation for change. Additional information.) (Motivation for change. Link to release notes. Additional information.)
``` ```
For consistency, there should not be a period at the end of the commit message's summary line (the first line of the commit message). For consistency, there should not be a period at the end of the commit message's summary line (the first line of the commit message).
@ -29,6 +29,7 @@ Below is a short excerpt of some points in there:
* nginx: init at 2.0.1 * nginx: init at 2.0.1
* firefox: 54.0.1 -> 55.0 * firefox: 54.0.1 -> 55.0
https://www.mozilla.org/en-US/firefox/55.0/releasenotes/
* nixos/hydra: add bazBaz option * nixos/hydra: add bazBaz option
Dual baz behavior is needed to do foo. Dual baz behavior is needed to do foo.
@ -52,6 +53,46 @@ In addition to writing properly formatted commit messages, it's important to inc
For package version upgrades and such a one-line commit message is usually sufficient. For package version upgrades and such a one-line commit message is usually sufficient.
## Rebasing between branches (i.e. from master to staging)
From time to time, changes between branches must be rebased, for example, if the
number of new rebuilds they would cause is too large for the target branch. When
rebasing, care must be taken to include only the intended changes, otherwise
many CODEOWNERS will be inadvertently requested for review. To achieve this,
rebasing should not be performed directly on the target branch, but on the merge
base between the current and target branch.
In the following example, we see a rebase from `master` onto the merge base
between `master` and `staging`, so that a change can eventually be retargeted to
`staging`. The example uses `upstream` as the remote for `NixOS/nixpkgs.git`
while the `origin` remote is used for the remote you are pushing to.
```console
# Find the common base between two branches
common=$(git merge-base upstream/master upstream/staging)
# Find the common base between your feature branch and master
commits=$(git merge-base $(git branch --show-current) upstream/master)
# Rebase all commits onto the common base
git rebase --onto=$common $commits
# Force push your changes
git push origin $(git branch --show-current) --force-with-lease
```
Then change the base branch in the GitHub PR using the *Edit* button in the upper
right corner, and switch from `master` to `staging`. After the PR has been
retargeted it might be necessary to do a final rebase onto the target branch, to
resolve any outstanding merge conflicts.
```console
# Rebase onto target branch
git rebase upstream/staging
# Review and fixup possible conflicts
git status
# Force push your changes
git push origin $(git branch --show-current) --force-with-lease
```
## Backporting changes ## Backporting changes
Follow these steps to backport a change into a release branch in compliance with the [commit policy](https://nixos.org/nixpkgs/manual/#submitting-changes-stable-release-branches). Follow these steps to backport a change into a release branch in compliance with the [commit policy](https://nixos.org/nixpkgs/manual/#submitting-changes-stable-release-branches).

View file

@ -214,15 +214,15 @@ Most of the time, these are the same. For instance, the package `e2fsprogs` has
There are a few naming guidelines: There are a few naming guidelines:
- The `name` attribute _should_ be identical to the upstream package name. - The `pname` attribute _should_ be identical to the upstream package name.
- The `name` attribute _must not_ contain uppercase letters — e.g., `"mplayer-1.0rc2"` instead of `"MPlayer-1.0rc2"`. - The `pname` and the `version` attribute _must not_ contain uppercase letters — e.g., `"mplayer" instead of `"MPlayer"`.
- The version part of the `name` attribute _must_ start with a digit (following a dash) — e.g., `"hello-0.3.1rc2"`. - The `version` attribute _must_ start with a digit e.g`"0.3.1rc2".
- If a package is not a release but a commit from a repository, then the version part of the name _must_ be the date of that (fetched) commit. The date _must_ be in `"YYYY-MM-DD"` format. Also append `"unstable"` to the name - e.g., `"pkgname-unstable-2014-09-23"`. - If a package is not a release but a commit from a repository, then the `version` attribute _must_ be the date of that (fetched) commit. The date _must_ be in `"unstable-YYYY-MM-DD"` format.
- Dashes in the package name _should_ be preserved in new variable names, rather than converted to underscores or camel cased — e.g., `http-parser` instead of `http_parser` or `httpParser`. The hyphenated style is preferred in all three package names. - Dashes in the package `pname` _should_ be preserved in new variable names, rather than converted to underscores or camel cased — e.g., `http-parser` instead of `http_parser` or `httpParser`. The hyphenated style is preferred in all three package names.
- If there are multiple versions of a package, this _should_ be reflected in the variable names in `all-packages.nix`, e.g. `json-c_0_9` and `json-c_0_11`. If there is an obvious “default” version, make an attribute like `json-c = json-c_0_9;`. See also [](#sec-versioning) - If there are multiple versions of a package, this _should_ be reflected in the variable names in `all-packages.nix`, e.g. `json-c_0_9` and `json-c_0_11`. If there is an obvious “default” version, make an attribute like `json-c = json-c_0_9;`. See also [](#sec-versioning)

View file

@ -0,0 +1,34 @@
# CUDA {#cuda}
CUDA-only packages are stored in the `cudaPackages` packages set. This set
includes the `cudatoolkit`, portions of the toolkit in separate derivations,
`cudnn`, `cutensor` and `nccl`.
A package set is available for each CUDA version, so for example
`cudaPackages_11_6`. Within each set is a matching version of the above listed
packages. Additionally, other versions of the packages that are packaged and
compatible are available as well. For example, there can be a
`cudaPackages.cudnn_8_3_2` package.
To use one or more CUDA packages in an expression, give the expression a `cudaPackages` parameter, and in case CUDA is optional
```nix
cudaSupport ? false
cudaPackages ? {}
```
When using `callPackage`, you can choose to pass in a different variant, e.g.
when a different version of the toolkit suffices
```nix
mypkg = callPackage { cudaPackages = cudaPackages_11_5; }
```
If another version of say `cudnn` or `cutensor` is needed, you can override the
package set to make it the default. This guarantees you get a consistent package
set.
```nix
mypkg = let
cudaPackages = cudaPackages_11_5.overrideScope' (final: prev {
cudnn = prev.cudnn_8_3_2;
}});
in callPackage { inherit cudaPackages; };
```

View file

@ -142,4 +142,8 @@ Removes the pre-existing vendor directory. This should only be used if the depen
### `subPackages` {#var-go-subPackages} ### `subPackages` {#var-go-subPackages}
Limits the builder from building child packages that have not been listed. If `subPackages` is not specified, all child packages will be built. Specified as a string or list of strings. Limits the builder from building child packages that have not been listed. If `subPackages` is not specified, all child packages will be built.
### `excludedPackages` {#var-go-excludedPackages}
Specified as a string or list of strings. Causes the builder to skip building child packages that match any of the provided values. If `excludedPackages` is not specified, all child packages will be built.

View file

@ -11,6 +11,7 @@
<xi:include href="bower.section.xml" /> <xi:include href="bower.section.xml" />
<xi:include href="coq.section.xml" /> <xi:include href="coq.section.xml" />
<xi:include href="crystal.section.xml" /> <xi:include href="crystal.section.xml" />
<xi:include href="cuda.section.xml" />
<xi:include href="dhall.section.xml" /> <xi:include href="dhall.section.xml" />
<xi:include href="dotnet.section.xml" /> <xi:include href="dotnet.section.xml" />
<xi:include href="emscripten.section.xml" /> <xi:include href="emscripten.section.xml" />

View file

@ -1043,7 +1043,7 @@ You can also specify a `runtimeDependencies` variable which lists dependencies t
In certain situations you may want to run the main command (`autoPatchelf`) of the setup hook on a file or a set of directories instead of unconditionally patching all outputs. This can be done by setting the `dontAutoPatchelf` environment variable to a non-empty value. In certain situations you may want to run the main command (`autoPatchelf`) of the setup hook on a file or a set of directories instead of unconditionally patching all outputs. This can be done by setting the `dontAutoPatchelf` environment variable to a non-empty value.
By default `autoPatchelf` will fail as soon as any ELF file requires a dependency which cannot be resolved via the given build inputs. In some situations you might prefer to just leave missing dependencies unpatched and continue to patch the rest. This can be achieved by setting the `autoPatchelfIgnoreMissingDeps` environment variable to a non-empty value. By default `autoPatchelf` will fail as soon as any ELF file requires a dependency which cannot be resolved via the given build inputs. In some situations you might prefer to just leave missing dependencies unpatched and continue to patch the rest. This can be achieved by setting the `autoPatchelfIgnoreMissingDeps` environment variable to a non-empty value. `autoPatchelfIgnoreMissingDeps` can be set to a list like `autoPatchelfIgnoreMissingDeps = [ "libcuda.so.1" "libcudart.so.1" ];` or to simply `[ "*" ]` to ignore all missing dependencies.
The `autoPatchelf` command also recognizes a `--no-recurse` command line flag, which prevents it from recursing into subdirectories. The `autoPatchelf` command also recognizes a `--no-recurse` command line flag, which prevents it from recursing into subdirectories.

View file

@ -10,7 +10,7 @@
* are mostly generators themselves, called with * are mostly generators themselves, called with
* their respective default values; they can be reused. * their respective default values; they can be reused.
* *
* Tests can be found in ./tests.nix * Tests can be found in ./tests/misc.nix
* Documentation in the manual, #sec-generators * Documentation in the manual, #sec-generators
*/ */
{ lib }: { lib }:
@ -108,7 +108,7 @@ rec {
* The mk* configuration attributes can generically change * The mk* configuration attributes can generically change
* the way sections and key-value strings are generated. * the way sections and key-value strings are generated.
* *
* For more examples see the test cases in ./tests.nix. * For more examples see the test cases in ./tests/misc.nix.
*/ */
toINI = { toINI = {
# apply transformations (e.g. escapes) to section names # apply transformations (e.g. escapes) to section names
@ -130,6 +130,51 @@ rec {
# map input to ini sections # map input to ini sections
mapAttrsToStringsSep "\n" mkSection attrsOfAttrs; mapAttrsToStringsSep "\n" mkSection attrsOfAttrs;
/* Generate an INI-style config file from an attrset
* specifying the global section (no header), and an
* attrset of sections to an attrset of key-value pairs.
*
* generators.toINIWithGlobalSection {} {
* globalSection = {
* someGlobalKey = "hi";
* };
* sections = {
* foo = { hi = "${pkgs.hello}"; ciao = "bar"; };
* baz = { "also, integers" = 42; };
* }
*
*> someGlobalKey=hi
*>
*> [baz]
*> also, integers=42
*>
*> [foo]
*> ciao=bar
*> hi=/nix/store/y93qql1p5ggfnaqjjqhxcw0vqw95rlz0-hello-2.10
*
* The mk* configuration attributes can generically change
* the way sections and key-value strings are generated.
*
* For more examples see the test cases in ./tests/misc.nix.
*
* If you dont need a global section, you can also use
* `generators.toINI` directly, which only takes
* the part in `sections`.
*/
toINIWithGlobalSection = {
# apply transformations (e.g. escapes) to section names
mkSectionName ? (name: libStr.escape [ "[" "]" ] name),
# format a setting line from key and value
mkKeyValue ? mkKeyValueDefault {} "=",
# allow lists as values for duplicate keys
listsAsDuplicateKeys ? false
}: { globalSection, sections }:
( if globalSection == {}
then ""
else (toKeyValue { inherit mkKeyValue listsAsDuplicateKeys; } globalSection)
+ "\n")
+ (toINI { inherit mkSectionName mkKeyValue listsAsDuplicateKeys; } sections);
/* Generate a git-config file from an attrset. /* Generate a git-config file from an attrset.
* *
* It has two major differences from the regular INI format: * It has two major differences from the regular INI format:

View file

@ -46,6 +46,7 @@ let
showFiles showFiles
showOption showOption
unknownModule unknownModule
literalExpression
; ;
showDeclPrefix = loc: decl: prefix: showDeclPrefix = loc: decl: prefix:
@ -140,7 +141,7 @@ rec {
# this module is used, to avoid conflicts and allow chaining of # this module is used, to avoid conflicts and allow chaining of
# extendModules. # extendModules.
internalModule = rec { internalModule = rec {
_file = ./modules.nix; _file = "lib/modules.nix";
key = _file; key = _file;
@ -153,8 +154,91 @@ rec {
# a `_module.args.pkgs = import (fetchTarball { ... }) {}` won't # a `_module.args.pkgs = import (fetchTarball { ... }) {}` won't
# start a download when `pkgs` wasn't evaluated. # start a download when `pkgs` wasn't evaluated.
type = types.lazyAttrsOf types.raw; type = types.lazyAttrsOf types.raw;
internal = true; # Only render documentation once at the root of the option tree,
description = "Arguments passed to each module."; # not for all individual submodules.
internal = prefix != [];
# TODO: Change the type of this option to a submodule with a
# freeformType, so that individual arguments can be documented
# separately
description = ''
Additional arguments passed to each module in addition to ones
like <literal>lib</literal>, <literal>config</literal>,
and <literal>pkgs</literal>, <literal>modulesPath</literal>.
</para>
<para>
This option is also available to all submodules. Submodules do not
inherit args from their parent module, nor do they provide args to
their parent module or sibling submodules. The sole exception to
this is the argument <literal>name</literal> which is provided by
parent modules to a submodule and contains the attribute name
the submodule is bound to, or a unique generated name if it is
not bound to an attribute.
</para>
<para>
Some arguments are already passed by default, of which the
following <emphasis>cannot</emphasis> be changed with this option:
<itemizedlist>
<listitem>
<para>
<varname>lib</varname>: The nixpkgs library.
</para>
</listitem>
<listitem>
<para>
<varname>config</varname>: The results of all options after merging the values from all modules together.
</para>
</listitem>
<listitem>
<para>
<varname>options</varname>: The options declared in all modules.
</para>
</listitem>
<listitem>
<para>
<varname>specialArgs</varname>: The <literal>specialArgs</literal> argument passed to <literal>evalModules</literal>.
</para>
</listitem>
<listitem>
<para>
All attributes of <varname>specialArgs</varname>
</para>
<para>
Whereas option values can generally depend on other option values
thanks to laziness, this does not apply to <literal>imports</literal>, which
must be computed statically before anything else.
</para>
<para>
For this reason, callers of the module system can provide <literal>specialArgs</literal>
which are available during import resolution.
</para>
<para>
For NixOS, <literal>specialArgs</literal> includes
<varname>modulesPath</varname>, which allows you to import
extra modules from the nixpkgs package tree without having to
somehow make the module aware of the location of the
<literal>nixpkgs</literal> or NixOS directories.
<programlisting>
{ modulesPath, ... }: {
imports = [
(modulesPath + "/profiles/minimal.nix")
];
}
</programlisting>
</para>
</listitem>
</itemizedlist>
</para>
<para>
For NixOS, the default value for this option includes at least this argument:
<itemizedlist>
<listitem>
<para>
<varname>pkgs</varname>: The nixpkgs package set according to
the <option>nixpkgs.pkgs</option> option.
</para>
</listitem>
</itemizedlist>
'';
}; };
_module.check = mkOption { _module.check = mkOption {

View file

@ -756,7 +756,14 @@ rec {
sanitizeDerivationName pkgs.hello sanitizeDerivationName pkgs.hello
=> "-nix-store-2g75chlbpxlrqn15zlby2dfh8hr9qwbk-hello-2.10" => "-nix-store-2g75chlbpxlrqn15zlby2dfh8hr9qwbk-hello-2.10"
*/ */
sanitizeDerivationName = string: lib.pipe string [ sanitizeDerivationName =
let okRegex = match "[[:alnum:]+_?=-][[:alnum:]+._?=-]*";
in
string:
# First detect the common case of already valid strings, to speed those up
if stringLength string <= 207 && okRegex string != null
then unsafeDiscardStringContext string
else lib.pipe string [
# Get rid of string context. This is safe under the assumption that the # Get rid of string context. This is safe under the assumption that the
# resulting string is only used as a derivation name # resulting string is only used as a derivation name
unsafeDiscardStringContext unsafeDiscardStringContext

View file

@ -471,6 +471,66 @@ runTests {
''; '';
}; };
testToINIWithGlobalSectionEmpty = {
expr = generators.toINIWithGlobalSection {} {
globalSection = {
};
sections = {
};
};
expected = ''
'';
};
testToINIWithGlobalSectionGlobalEmptyIsTheSameAsToINI =
let
sections = {
"section 1" = {
attribute1 = 5;
x = "Me-se JarJar Binx";
};
"foo" = {
"he\\h=he" = "this is okay";
};
};
in {
expr =
generators.toINIWithGlobalSection {} {
globalSection = {};
sections = sections;
};
expected = generators.toINI {} sections;
};
testToINIWithGlobalSectionFull = {
expr = generators.toINIWithGlobalSection {} {
globalSection = {
foo = "bar";
test = false;
};
sections = {
"section 1" = {
attribute1 = 5;
x = "Me-se JarJar Binx";
};
"foo" = {
"he\\h=he" = "this is okay";
};
};
};
expected = ''
foo=bar
test=false
[foo]
he\h\=he=this is okay
[section 1]
attribute1=5
x=Me-se JarJar Binx
'';
};
/* right now only invocation check */ /* right now only invocation check */
testToJSONSimple = testToJSONSimple =
let val = { let val = {
@ -649,6 +709,11 @@ runTests {
expected = "foo"; expected = "foo";
}; };
testSanitizeDerivationNameUnicode = testSanitizeDerivationName {
name = "fö";
expected = "f-";
};
testSanitizeDerivationNameAscii = testSanitizeDerivationName { testSanitizeDerivationNameAscii = testSanitizeDerivationName {
name = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; name = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
expected = "-+--.-0123456789-=-?-ABCDEFGHIJKLMNOPQRSTUVWXYZ-_-abcdefghijklmnopqrstuvwxyz-"; expected = "-+--.-0123456789-=-?-ABCDEFGHIJKLMNOPQRSTUVWXYZ-_-abcdefghijklmnopqrstuvwxyz-";
@ -691,7 +756,7 @@ runTests {
locs = filter (o: ! o.internal) (optionAttrSetToDocList options); locs = filter (o: ! o.internal) (optionAttrSetToDocList options);
in map (o: o.loc) locs; in map (o: o.loc) locs;
expected = [ [ "foo" ] [ "foo" "<name>" "bar" ] [ "foo" "bar" ] ]; expected = [ [ "_module" "args" ] [ "foo" ] [ "foo" "<name>" "bar" ] [ "foo" "bar" ] ];
}; };
testCartesianProductOfEmptySet = { testCartesianProductOfEmptySet = {

View file

@ -4502,6 +4502,12 @@
githubId = 3217744; githubId = 3217744;
name = "Peter Ferenczy"; name = "Peter Ferenczy";
}; };
ghostbuster91 = {
name = "Kasper Kondzielski";
email = "kghost0@gmail.com";
github = "ghostbuster91";
githubId = 5662622;
};
ghuntley = { ghuntley = {
email = "ghuntley@ghuntley.com"; email = "ghuntley@ghuntley.com";
github = "ghuntley"; github = "ghuntley";
@ -4656,6 +4662,12 @@
githubId = 4656860; githubId = 4656860;
name = "Gaute Ravndal"; name = "Gaute Ravndal";
}; };
graysonhead = {
email = "grayson@graysonhead.net";
github = "graysonhead";
githubId = 6179496;
name = "Grayson Head";
};
grburst = { grburst = {
email = "GRBurst@protonmail.com"; email = "GRBurst@protonmail.com";
github = "GRBurst"; github = "GRBurst";
@ -4702,6 +4714,12 @@
githubId = 343415; githubId = 343415;
name = "Greg Roodt"; name = "Greg Roodt";
}; };
grnnja = {
email = "grnnja@gmail.com";
github = "grnnja";
githubId = 31556469;
name = "Prem Netsuwan";
};
gruve-p = { gruve-p = {
email = "groestlcoin@gmail.com"; email = "groestlcoin@gmail.com";
github = "gruve-p"; github = "gruve-p";
@ -5417,6 +5435,12 @@
githubId = 41924494; githubId = 41924494;
name = "Ivar"; name = "Ivar";
}; };
iwanb = {
email = "tracnar@gmail.com";
github = "iwanb";
githubId = 4035835;
name = "Iwan";
};
ixmatus = { ixmatus = {
email = "parnell@digitalmentat.com"; email = "parnell@digitalmentat.com";
github = "ixmatus"; github = "ixmatus";
@ -7288,7 +7312,7 @@
name = "Anthony Lodi"; name = "Anthony Lodi";
}; };
loicreynier = { loicreynier = {
email = "loic@loireynier.fr"; email = "loic@loicreynier.fr";
github = "loicreynier"; github = "loicreynier";
githubId = 88983487; githubId = 88983487;
name = "Loïc Reynier"; name = "Loïc Reynier";
@ -8079,6 +8103,12 @@
githubId = 20536514; githubId = 20536514;
name = "Magdalena Haselsteiner"; name = "Magdalena Haselsteiner";
}; };
mh182 = {
email = "mh182@chello.at";
github = "mh182";
githubId = 9980864;
name = "Max Hofer";
};
mic92 = { mic92 = {
email = "joerg@thalheim.io"; email = "joerg@thalheim.io";
matrix = "@mic92:nixos.dev"; matrix = "@mic92:nixos.dev";
@ -8252,6 +8282,17 @@
githubId = 1776903; githubId = 1776903;
name = "Andrew Abbott"; name = "Andrew Abbott";
}; };
misterio77 = {
email = "eu@misterio.me";
github = "misterio77";
githubId = 5727578;
matrix = "@misterio:matrix.org";
name = "Gabriel Fontes";
keys = [{
longkeyid = "rsa3072/0x245CAB70B4C225E9";
fingerprint = "7088 C742 1873 E0DB 97FF 17C2 245C AB70 B4C2 25E9";
}];
};
mitchmindtree = { mitchmindtree = {
email = "mail@mitchellnordine.com"; email = "mail@mitchellnordine.com";
github = "mitchmindtree"; github = "mitchmindtree";
@ -9910,6 +9951,12 @@
fingerprint = "2CD2 B030 BD22 32EF DF5A 008A 3618 20A4 5DB4 1E9A"; fingerprint = "2CD2 B030 BD22 32EF DF5A 008A 3618 20A4 5DB4 1E9A";
}]; }];
}; };
podocarp = {
email = "xdjiaxd@gmail.com";
github = "podocarp";
githubId = 10473184;
name = "Jia Xiaodong";
};
polendri = { polendri = {
email = "paul@ijj.li"; email = "paul@ijj.li";
github = "polendri"; github = "polendri";
@ -10169,6 +10216,12 @@
githubId = 115877; githubId = 115877;
name = "Kenny Shen"; name = "Kenny Shen";
}; };
quag = {
email = "quaggy@gmail.com";
github = "quag";
githubId = 35086;
name = "Jonathan Wright";
};
queezle = { queezle = {
email = "git@queezle.net"; email = "git@queezle.net";
github = "qzle"; github = "qzle";
@ -11011,6 +11064,16 @@
githubId = 107703; githubId = 107703;
name = "Samuel Rivas"; name = "Samuel Rivas";
}; };
samyak = {
name = "Samyak Sarnayak";
email = "samyak201@gmail.com";
github = "Samyak2";
githubId = 34161949;
keys = [{
longkeyid = "rsa4096/0x365873F2F0C6153B";
fingerprint = "155C F413 0129 C058 9A5F 5524 3658 73F2 F0C6 153B";
}];
};
sander = { sander = {
email = "s.vanderburg@tudelft.nl"; email = "s.vanderburg@tudelft.nl";
github = "svanderburg"; github = "svanderburg";
@ -11117,6 +11180,16 @@
email = "schristopher@konputa.com"; email = "schristopher@konputa.com";
name = "Scott Christopher"; name = "Scott Christopher";
}; };
sciencentistguy = {
email = "jamie@quigley.xyz";
name = "Jamie Quigley";
github = "Sciencentistguy";
githubId = 4983935;
keys = [{
longkeyid = "rsa2048/0x8E8FF66E2AE8D970";
fingerprint = "30BB FF3F AB0B BB3E 0435 F83C 8E8F F66E 2AE8 D970";
}];
};
scode = { scode = {
email = "peter.schuller@infidyne.com"; email = "peter.schuller@infidyne.com";
github = "scode"; github = "scode";
@ -11271,6 +11344,12 @@
githubId = 1151264; githubId = 1151264;
name = "Sebastian Graf"; name = "Sebastian Graf";
}; };
shadaj = {
email = "shadaj@users.noreply.github.com";
github = "shadaj";
githubId = 543055;
name = "Shadaj Laddad";
};
shahrukh330 = { shahrukh330 = {
email = "shahrukh330@gmail.com"; email = "shahrukh330@gmail.com";
github = "shahrukh330"; github = "shahrukh330";
@ -11467,6 +11546,12 @@
githubId = 2770647; githubId = 2770647;
name = "Simon Vandel Sillesen"; name = "Simon Vandel Sillesen";
}; };
sir4ur0n = {
email = "sir4ur0n@users.noreply.github.com";
github = "sir4ur0n";
githubId = 1204125;
name = "sir4ur0n";
};
siraben = { siraben = {
email = "bensiraphob@gmail.com"; email = "bensiraphob@gmail.com";
matrix = "@siraben:matrix.org"; matrix = "@siraben:matrix.org";

View file

@ -9,7 +9,7 @@ tmp=$(mktemp --tmpdir -d nixpkgs-dep-license.XXXXXX)
exitHandler() { exitHandler() {
exitCode=$? exitCode=$?
rm -rf "$tmp" rm -rf "$tmp"
exit $exitCode return $exitCode
} }
trap "exitHandler" EXIT trap "exitHandler" EXIT

View file

@ -99,7 +99,7 @@ This PR is the regular merge of the \`haskell-updates\` branch into \`master\`.
This branch is being continually built and tested by hydra at https://hydra.nixos.org/jobset/nixpkgs/haskell-updates. You may be able to find an up-to-date Hydra build report at [cdepillabout/nix-haskell-updates-status](https://github.com/cdepillabout/nix-haskell-updates-status). This branch is being continually built and tested by hydra at https://hydra.nixos.org/jobset/nixpkgs/haskell-updates. You may be able to find an up-to-date Hydra build report at [cdepillabout/nix-haskell-updates-status](https://github.com/cdepillabout/nix-haskell-updates-status).
We roughly aim to merge these \`haskell-updates\` PRs at least once every two weeks. See the @NixOS/haskell [team calendar](https://cloud.maralorn.de/apps/calendar/p/Mw5WLnzsP7fC4Zky) for who is currently in charge of this branch. We roughly aim to merge these \`haskell-updates\` PRs at least once every two weeks. See the @NixOS/haskell [team calendar](https://cloud.maralorn.de/apps/calendar/p/H6migHmKX7xHoTFa) for who is currently in charge of this branch.
### haskellPackages Workflow Summary ### haskellPackages Workflow Summary

View file

@ -8,6 +8,7 @@
# $ nix run nixpkgs.python3Packages.flake8 -c flake8 --ignore E501,E265 update.py # $ nix run nixpkgs.python3Packages.flake8 -c flake8 --ignore E501,E265 update.py
import argparse import argparse
import csv
import functools import functools
import http import http
import json import json
@ -28,7 +29,7 @@ from pathlib import Path
from typing import Dict, List, Optional, Tuple, Union, Any, Callable from typing import Dict, List, Optional, Tuple, Union, Any, Callable
from urllib.parse import urljoin, urlparse from urllib.parse import urljoin, urlparse
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
from dataclasses import dataclass from dataclasses import dataclass, asdict
import git import git
@ -85,21 +86,30 @@ def make_request(url: str, token=None) -> urllib.request.Request:
headers["Authorization"] = f"token {token}" headers["Authorization"] = f"token {token}"
return urllib.request.Request(url, headers=headers) return urllib.request.Request(url, headers=headers)
Redirects = Dict['Repo', 'Repo']
class Repo: class Repo:
def __init__( def __init__(
self, uri: str, branch: str, alias: Optional[str] self, uri: str, branch: str
) -> None: ) -> None:
self.uri = uri self.uri = uri
'''Url to the repo''' '''Url to the repo'''
self.branch = branch self._branch = branch
self.alias = alias # {old_uri: new_uri}
self.redirect: Dict[str, str] = {} self.redirect: Redirects = {}
self.token = "dummy_token" self.token = "dummy_token"
@property @property
def name(self): def name(self):
return self.uri.split('/')[-1] return self.uri.split('/')[-1]
@property
def branch(self):
return self._branch or "HEAD"
def __str__(self) -> str:
return f"{self.uri}"
def __repr__(self) -> str: def __repr__(self) -> str:
return f"Repo({self.name}, {self.uri})" return f"Repo({self.name}, {self.uri})"
@ -109,6 +119,7 @@ class Repo:
@retry(urllib.error.URLError, tries=4, delay=3, backoff=2) @retry(urllib.error.URLError, tries=4, delay=3, backoff=2)
def latest_commit(self) -> Tuple[str, datetime]: def latest_commit(self) -> Tuple[str, datetime]:
log.debug("Latest commit")
loaded = self._prefetch(None) loaded = self._prefetch(None)
updated = datetime.strptime(loaded['date'], "%Y-%m-%dT%H:%M:%S%z") updated = datetime.strptime(loaded['date'], "%Y-%m-%dT%H:%M:%S%z")
@ -124,6 +135,7 @@ class Repo:
return loaded return loaded
def prefetch(self, ref: Optional[str]) -> str: def prefetch(self, ref: Optional[str]) -> str:
print("Prefetching")
loaded = self._prefetch(ref) loaded = self._prefetch(ref)
return loaded["sha256"] return loaded["sha256"]
@ -137,21 +149,22 @@ class Repo:
class RepoGitHub(Repo): class RepoGitHub(Repo):
def __init__( def __init__(
self, owner: str, repo: str, branch: str, alias: Optional[str] self, owner: str, repo: str, branch: str
) -> None: ) -> None:
self.owner = owner self.owner = owner
self.repo = repo self.repo = repo
self.token = None self.token = None
'''Url to the repo''' '''Url to the repo'''
super().__init__(self.url(""), branch, alias) super().__init__(self.url(""), branch)
log.debug("Instantiating github repo %s/%s", self.owner, self.repo) log.debug("Instantiating github repo owner=%s and repo=%s", self.owner, self.repo)
@property @property
def name(self): def name(self):
return self.repo return self.repo
def url(self, path: str) -> str: def url(self, path: str) -> str:
return urljoin(f"https://github.com/{self.owner}/{self.name}/", path) res = urljoin(f"https://github.com/{self.owner}/{self.repo}/", path)
return res
@retry(urllib.error.URLError, tries=4, delay=3, backoff=2) @retry(urllib.error.URLError, tries=4, delay=3, backoff=2)
def has_submodules(self) -> bool: def has_submodules(self) -> bool:
@ -168,6 +181,7 @@ class RepoGitHub(Repo):
@retry(urllib.error.URLError, tries=4, delay=3, backoff=2) @retry(urllib.error.URLError, tries=4, delay=3, backoff=2)
def latest_commit(self) -> Tuple[str, datetime]: def latest_commit(self) -> Tuple[str, datetime]:
commit_url = self.url(f"commits/{self.branch}.atom") commit_url = self.url(f"commits/{self.branch}.atom")
log.debug("Sending request to %s", commit_url)
commit_req = make_request(commit_url, self.token) commit_req = make_request(commit_url, self.token)
with urllib.request.urlopen(commit_req, timeout=10) as req: with urllib.request.urlopen(commit_req, timeout=10) as req:
self._check_for_redirect(commit_url, req) self._check_for_redirect(commit_url, req)
@ -191,12 +205,9 @@ class RepoGitHub(Repo):
new_owner, new_name = ( new_owner, new_name = (
urllib.parse.urlsplit(response_url).path.strip("/").split("/")[:2] urllib.parse.urlsplit(response_url).path.strip("/").split("/")[:2]
) )
end_line = "\n" if self.alias is None else f" as {self.alias}\n"
plugin_line = "{owner}/{name}" + end_line
old_plugin = plugin_line.format(owner=self.owner, name=self.name) new_repo = RepoGitHub(owner=new_owner, repo=new_name, branch=self.branch)
new_plugin = plugin_line.format(owner=new_owner, name=new_name) self.redirect[self] = new_repo
self.redirect[old_plugin] = new_plugin
def prefetch(self, commit: str) -> str: def prefetch(self, commit: str) -> str:
@ -207,9 +218,9 @@ class RepoGitHub(Repo):
return sha256 return sha256
def prefetch_github(self, ref: str) -> str: def prefetch_github(self, ref: str) -> str:
data = subprocess.check_output( cmd = ["nix-prefetch-url", "--unpack", self.url(f"archive/{ref}.tar.gz")]
["nix-prefetch-url", "--unpack", self.url(f"archive/{ref}.tar.gz")] log.debug("Running %s", cmd)
) data = subprocess.check_output(cmd)
return data.strip().decode("utf-8") return data.strip().decode("utf-8")
def as_nix(self, plugin: "Plugin") -> str: def as_nix(self, plugin: "Plugin") -> str:
@ -239,21 +250,38 @@ class PluginDesc:
else: else:
return self.alias return self.alias
def __lt__(self, other):
return self.repo.name < other.repo.name
@staticmethod
def load_from_csv(config: FetchConfig, row: Dict[str, str]) -> 'PluginDesc':
branch = row["branch"]
repo = make_repo(row['repo'], branch.strip())
repo.token = config.github_token
return PluginDesc(repo, branch.strip(), row["alias"])
@staticmethod
def load_from_string(config: FetchConfig, line: str) -> 'PluginDesc':
branch = "HEAD"
alias = None
uri = line
if " as " in uri:
uri, alias = uri.split(" as ")
alias = alias.strip()
if "@" in uri:
uri, branch = uri.split("@")
repo = make_repo(uri.strip(), branch.strip())
repo.token = config.github_token
return PluginDesc(repo, branch.strip(), alias)
@dataclass
class Plugin: class Plugin:
def __init__( name: str
self, commit: str
name: str, has_submodules: bool
commit: str, sha256: str
has_submodules: bool, date: Optional[datetime] = None
sha256: str,
date: Optional[datetime] = None,
) -> None:
self.name = name
self.commit = commit
self.has_submodules = has_submodules
self.sha256 = sha256
self.date = date
@property @property
def normalized_name(self) -> str: def normalized_name(self) -> str:
@ -270,6 +298,17 @@ class Plugin:
return copy return copy
def load_plugins_from_csv(config: FetchConfig, input_file: Path,) -> List[PluginDesc]:
log.debug("Load plugins from csv %s", input_file)
plugins = []
with open(input_file, newline='') as csvfile:
log.debug("Writing into %s", input_file)
reader = csv.DictReader(csvfile,)
for line in reader:
plugin = PluginDesc.load_from_csv(config, line)
plugins.append(plugin)
return plugins
class Editor: class Editor:
"""The configuration of the update script.""" """The configuration of the update script."""
@ -298,14 +337,8 @@ class Editor:
return get_current_plugins(self) return get_current_plugins(self)
def load_plugin_spec(self, config: FetchConfig, plugin_file) -> List[PluginDesc]: def load_plugin_spec(self, config: FetchConfig, plugin_file) -> List[PluginDesc]:
plugins = [] '''CSV spec'''
with open(plugin_file) as f: return load_plugins_from_csv(config, plugin_file)
for line in f:
if line.startswith("#"):
continue
plugin = parse_plugin_line(config, line)
plugins.append(plugin)
return plugins
def generate_nix(self, plugins, outfile: str): def generate_nix(self, plugins, outfile: str):
'''Returns nothing for now, writes directly to outfile''' '''Returns nothing for now, writes directly to outfile'''
@ -316,11 +349,11 @@ class Editor:
_prefetch = functools.partial(prefetch, cache=cache) _prefetch = functools.partial(prefetch, cache=cache)
def update() -> dict: def update() -> dict:
plugin_names = self.load_plugin_spec(config, input_file) plugins = self.load_plugin_spec(config, input_file)
try: try:
pool = Pool(processes=config.proc) pool = Pool(processes=config.proc)
results = pool.map(_prefetch, plugin_names) results = pool.map(_prefetch, plugins)
finally: finally:
cache.store() cache.store()
@ -423,6 +456,7 @@ def get_current_plugins(editor: Editor) -> List[Plugin]:
data = json.loads(out) data = json.loads(out)
plugins = [] plugins = []
for name, attr in data.items(): for name, attr in data.items():
print("get_current_plugins: name %s" % name)
p = Plugin(name, attr["rev"], attr["submodules"], attr["sha256"]) p = Plugin(name, attr["rev"], attr["submodules"], attr["sha256"])
plugins.append(p) plugins.append(p)
return plugins return plugins
@ -431,7 +465,7 @@ def get_current_plugins(editor: Editor) -> List[Plugin]:
def prefetch_plugin( def prefetch_plugin(
p: PluginDesc, p: PluginDesc,
cache: "Optional[Cache]" = None, cache: "Optional[Cache]" = None,
) -> Tuple[Plugin, Dict[str, str]]: ) -> Tuple[Plugin, Redirects]:
repo, branch, alias = p.repo, p.branch, p.alias repo, branch, alias = p.repo, p.branch, p.alias
name = alias or p.repo.name name = alias or p.repo.name
commit = None commit = None
@ -454,11 +488,6 @@ def prefetch_plugin(
) )
def fetch_plugin_from_pluginline(config: FetchConfig, plugin_line: str) -> Plugin:
plugin, _ = prefetch_plugin(parse_plugin_line(config, plugin_line))
return plugin
def print_download_error(plugin: str, ex: Exception): def print_download_error(plugin: str, ex: Exception):
print(f"{plugin}: {ex}", file=sys.stderr) print(f"{plugin}: {ex}", file=sys.stderr)
ex_traceback = ex.__traceback__ ex_traceback = ex.__traceback__
@ -468,14 +497,14 @@ def print_download_error(plugin: str, ex: Exception):
] ]
print("\n".join(tb_lines)) print("\n".join(tb_lines))
def check_results( def check_results(
results: List[Tuple[PluginDesc, Union[Exception, Plugin], Dict[str, str]]] results: List[Tuple[PluginDesc, Union[Exception, Plugin], Redirects]]
) -> Tuple[List[Tuple[PluginDesc, Plugin]], Dict[str, str]]: ) -> Tuple[List[Tuple[PluginDesc, Plugin]], Redirects]:
''' ''' ''' '''
failures: List[Tuple[str, Exception]] = [] failures: List[Tuple[str, Exception]] = []
plugins = [] plugins = []
redirects: Dict[str, str] = {} # {old: new} plugindesc
redirects: Dict[Repo, Repo] = {}
for (pdesc, result, redirect) in results: for (pdesc, result, redirect) in results:
if isinstance(result, Exception): if isinstance(result, Exception):
failures.append((pdesc.name, result)) failures.append((pdesc.name, result))
@ -495,31 +524,17 @@ def check_results(
sys.exit(1) sys.exit(1)
def make_repo(uri, branch, alias) -> Repo: def make_repo(uri: str, branch) -> Repo:
'''Instantiate a Repo with the correct specialization depending on server (gitub spec)''' '''Instantiate a Repo with the correct specialization depending on server (gitub spec)'''
# dumb check to see if it's of the form owner/repo (=> github) or https://... # dumb check to see if it's of the form owner/repo (=> github) or https://...
res = uri.split('/') res = urlparse(uri)
if len(res) <= 2: if res.netloc in [ "github.com", ""]:
repo = RepoGitHub(res[0], res[1], branch, alias) res = res.path.strip('/').split('/')
repo = RepoGitHub(res[0], res[1], branch)
else: else:
repo = Repo(uri.strip(), branch, alias) repo = Repo(uri.strip(), branch)
return repo return repo
def parse_plugin_line(config: FetchConfig, line: str) -> PluginDesc:
branch = "HEAD"
alias = None
uri = line
if " as " in uri:
uri, alias = uri.split(" as ")
alias = alias.strip()
if "@" in uri:
uri, branch = uri.split("@")
repo = make_repo(uri.strip(), branch.strip(), alias)
repo.token = config.github_token
return PluginDesc(repo, branch.strip(), alias)
def get_cache_path(cache_file_name: str) -> Optional[Path]: def get_cache_path(cache_file_name: str) -> Optional[Path]:
xdg_cache = os.environ.get("XDG_CACHE_HOME", None) xdg_cache = os.environ.get("XDG_CACHE_HOME", None)
@ -585,27 +600,27 @@ def prefetch(
return (pluginDesc, e, {}) return (pluginDesc, e, {})
def rewrite_input( def rewrite_input(
config: FetchConfig, config: FetchConfig,
input_file: Path, input_file: Path,
deprecated: Path, deprecated: Path,
redirects: Dict[str, str] = None, # old pluginDesc and the new
append: Tuple = (), redirects: Dict[PluginDesc, PluginDesc] = {},
append: List[PluginDesc] = [],
): ):
with open(input_file, "r") as f: plugins = load_plugins_from_csv(config, input_file,)
lines = f.readlines()
lines.extend(append) plugins.extend(append)
if redirects: if redirects:
lines = [redirects.get(line, line) for line in lines]
cur_date_iso = datetime.now().strftime("%Y-%m-%d") cur_date_iso = datetime.now().strftime("%Y-%m-%d")
with open(deprecated, "r") as f: with open(deprecated, "r") as f:
deprecations = json.load(f) deprecations = json.load(f)
for old, new in redirects.items(): for old, new in redirects.items():
old_plugin = fetch_plugin_from_pluginline(config, old) old_plugin, _ = prefetch_plugin(old)
new_plugin = fetch_plugin_from_pluginline(config, new) new_plugin, _ = prefetch_plugin(new)
if old_plugin.normalized_name != new_plugin.normalized_name: if old_plugin.normalized_name != new_plugin.normalized_name:
deprecations[old_plugin.normalized_name] = { deprecations[old_plugin.normalized_name] = {
"new": new_plugin.normalized_name, "new": new_plugin.normalized_name,
@ -615,10 +630,14 @@ def rewrite_input(
json.dump(deprecations, f, indent=4, sort_keys=True) json.dump(deprecations, f, indent=4, sort_keys=True)
f.write("\n") f.write("\n")
lines = sorted(lines, key=str.casefold)
with open(input_file, "w") as f: with open(input_file, "w") as f:
f.writelines(lines) log.debug("Writing into %s", input_file)
# fields = dataclasses.fields(PluginDesc)
fieldnames = ['repo', 'branch', 'alias']
writer = csv.DictWriter(f, fieldnames, dialect='unix', quoting=csv.QUOTE_NONE)
writer.writeheader()
for plugin in sorted(plugins):
writer.writerow(asdict(plugin))
def commit(repo: git.Repo, message: str, files: List[Path]) -> None: def commit(repo: git.Repo, message: str, files: List[Path]) -> None:
@ -660,9 +679,11 @@ def update_plugins(editor: Editor, args):
) )
for plugin_line in args.add_plugins: for plugin_line in args.add_plugins:
editor.rewrite_input(fetch_config, args.input_file, editor.deprecated, append=(plugin_line + "\n",)) pdesc = PluginDesc.load_from_string(fetch_config, plugin_line)
append = [ pdesc ]
editor.rewrite_input(fetch_config, args.input_file, editor.deprecated, append=append)
update() update()
plugin = fetch_plugin_from_pluginline(fetch_config, plugin_line) plugin, _ = prefetch_plugin(pdesc, )
if autocommit: if autocommit:
commit( commit(
nixpkgs_repo, nixpkgs_repo,

View file

@ -14,6 +14,10 @@ with pkgs;
let let
lib = pkgs.lib; lib = pkgs.lib;
docbook_xsl_ns = pkgs.docbook-xsl-ns.override {
withManOptDedupPatch = true;
};
# We need to strip references to /nix/store/* from options, # We need to strip references to /nix/store/* from options,
# including any `extraSources` if some modules came from elsewhere, # including any `extraSources` if some modules came from elsewhere,
# or else the build will fail. # or else the build will fail.

View file

@ -866,6 +866,14 @@
package. package.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
The vim/kakoune plugin updater now reads from a CSV file:
check
<literal>pkgs/applications/editors/vim/plugins/vim-plugin-names</literal>
out to see the new format
</para>
</listitem>
</itemizedlist> </itemizedlist>
</section> </section>
</section> </section>

View file

@ -68,6 +68,11 @@
granular distinction between reloads and restarts. granular distinction between reloads and restarts.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
Systemd has been upgraded to the version 250.
</para>
</listitem>
<listitem> <listitem>
<para> <para>
<link xlink:href="https://kops.sigs.k8s.io"><literal>kops</literal></link> <link xlink:href="https://kops.sigs.k8s.io"><literal>kops</literal></link>
@ -125,6 +130,13 @@
<link xlink:href="option.html#opt-services.matrix-conduit.enable">services.matrix-conduit</link>. <link xlink:href="option.html#opt-services.matrix-conduit.enable">services.matrix-conduit</link>.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
<link xlink:href="https://github.com/vvilhonen/nethoscope">nethoscope</link>,
listen to your network traffic. Available as
<link linkend="opt-programs.nethoscope.enable">programs.nethoscope</link>.
</para>
</listitem>
<listitem> <listitem>
<para> <para>
<link xlink:href="https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-overview.html">filebeat</link>, <link xlink:href="https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-overview.html">filebeat</link>,
@ -214,6 +226,15 @@
to be able to access the device. to be able to access the device.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
<link xlink:href="https://github.com/mozilla-mobile/mozilla-vpn-client">mozillavpn</link>,
the client for the
<link xlink:href="https://vpn.mozilla.org/">Mozilla VPN</link>
service. Available as
<link xlink:href="options.html#opt-services.mozillavpn">services.mozillavpn</link>.
</para>
</listitem>
<listitem> <listitem>
<para> <para>
<link xlink:href="https://github.com/mgumz/mtr-exporter">mtr-exporter</link>, <link xlink:href="https://github.com/mgumz/mtr-exporter">mtr-exporter</link>,
@ -360,6 +381,14 @@
cluster resource manager cluster resource manager
</para> </para>
</listitem> </listitem>
<listitem>
<para>
<link xlink:href="https://nifi.apache.org">nifi</link>, an
easy to use, powerful, and reliable system to process and
distribute data. Available as
<link xlink:href="options.html#opt-services.nifi.enable">services.nifi</link>.
</para>
</listitem>
</itemizedlist> </itemizedlist>
</section> </section>
<section xml:id="sec-release-22.05-incompatibilities"> <section xml:id="sec-release-22.05-incompatibilities">
@ -427,6 +456,12 @@
new versions will release. new versions will release.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
<literal>security.klogd</literal> was removed. Logging of
kernel messages is handled by systemd since Linux 3.5.
</para>
</listitem>
<listitem> <listitem>
<para> <para>
<literal>services.kubernetes.addons.dashboard</literal> was <literal>services.kubernetes.addons.dashboard</literal> was
@ -444,6 +479,37 @@
relying on the insecure behaviour before upgrading. relying on the insecure behaviour before upgrading.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
In the PowerDNS Recursor module
(<literal>services.pdns-recursor</literal>), default values of
several IP address-related NixOS options have been updated to
match the default upstream behavior. In particular, Recursor
by default will:
</para>
<itemizedlist spacing="compact">
<listitem>
<para>
listen on (and allows connections from) both IPv4 and IPv6
addresses
(<literal>services.pdns-recursor.dns.address</literal>,
<literal>services.pdns-recursor.dns.allowFrom</literal>);
</para>
</listitem>
<listitem>
<para>
allow only local connections to the REST API server
(<literal>services.pdns-recursor.api.allowFrom</literal>).
</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>
<literal>openssh</literal> has been update to 8.9p1, changing
the FIDO security key middleware interface.
</para>
</listitem>
<listitem> <listitem>
<para> <para>
<literal>services.k3s.enable</literal> no longer implies <literal>services.k3s.enable</literal> no longer implies
@ -476,6 +542,13 @@
} }
</programlisting> </programlisting>
</listitem> </listitem>
<listitem>
<para>
<literal>services.prometheus.alertManagerTimeout</literal> has
been removed as it has been deprecated upstream and has no
effect.
</para>
</listitem>
<listitem> <listitem>
<para> <para>
The DHCP server (<literal>services.dhcpd4</literal>, The DHCP server (<literal>services.dhcpd4</literal>,
@ -509,6 +582,17 @@
work. work.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
<literal>services.paperless-ng</literal> was renamed to
<literal>services.paperless</literal>. Accordingly, the
<literal>paperless-ng-manage</literal> script (located in
<literal>dataDir</literal>) was renamed to
<literal>paperless-manage</literal>.
<literal>services.paperless</literal> now uses
<literal>paperless-ngx</literal>.
</para>
</listitem>
<listitem> <listitem>
<para> <para>
The <literal>matrix-synapse</literal> service The <literal>matrix-synapse</literal> service
@ -1268,6 +1352,33 @@
example. example.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
Existing <literal>resholve*</literal> functions have been
renamed and nested under <literal>pkgs.resholve</literal>.
Update uses to:
</para>
<itemizedlist spacing="compact">
<listitem>
<para>
<literal>resholvePackage</literal> -&gt;
<literal>resholve.mkDerivation</literal>
</para>
</listitem>
<listitem>
<para>
<literal>resholveScript</literal> -&gt;
<literal>resholve.writeScript</literal>
</para>
</listitem>
<listitem>
<para>
<literal>resholveScriptBin</literal> -&gt;
<literal>resholve.writeScriptBin</literal>
</para>
</listitem>
</itemizedlist>
</listitem>
<listitem> <listitem>
<para> <para>
<literal>pkgs.cosmopolitan</literal> no longer provides the <literal>pkgs.cosmopolitan</literal> no longer provides the
@ -1454,6 +1565,15 @@
takes a list of strings instead of a string. takes a list of strings instead of a string.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
The <literal>asterisk</literal> and
<literal>asterisk-stable</literal> packages were switched from
<literal>asterisk_18</literal> to the newly-packaged
<literal>asterisk_19</literal>. Asterisk 13 and 17 have been
removed as they have reached their end of life.
</para>
</listitem>
<listitem> <listitem>
<para> <para>
The <literal>services.unifi.openPorts</literal> option default The <literal>services.unifi.openPorts</literal> option default
@ -1512,9 +1632,11 @@
<para> <para>
<link linkend="opt-programs.ssh.knownHosts">programs.ssh.knownHosts</link> <link linkend="opt-programs.ssh.knownHosts">programs.ssh.knownHosts</link>
has gained an <literal>extraHostNames</literal> option to has gained an <literal>extraHostNames</literal> option to
replace <literal>hostNames</literal>. augment <literal>hostNames</literal>. It is now possible to
<literal>hostNames</literal> is deprecated, but still use the attribute name of a <literal>knownHosts</literal>
available for now. entry as the primary host name and specify secondary host
names using <literal>extraHostNames</literal> without having
to duplicate the primary host name.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
@ -1525,6 +1647,13 @@
configuration. configuration.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
A new module was added for the Envoy reverse proxy, providing
the options <literal>services.envoy.enable</literal> and
<literal>services.envoy.settings</literal>.
</para>
</listitem>
<listitem> <listitem>
<para> <para>
The option <literal>services.duplicati.dataDir</literal> has The option <literal>services.duplicati.dataDir</literal> has
@ -1602,6 +1731,13 @@
<literal>true</literal>. <literal>true</literal>.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
A module for declarative configuration of openconnect VPN
profiles was added under
<literal>networking.openconnect</literal>.
</para>
</listitem>
<listitem> <listitem>
<para> <para>
The <literal>element-desktop</literal> package now has an The <literal>element-desktop</literal> package now has an
@ -1700,6 +1836,15 @@
should now be used instead. should now be used instead.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
<literal>security.pam.ussh</literal> has been added, which
allows authorizing PAM sessions based on SSH
<emphasis>certificates</emphasis> held within an SSH agent,
using
<link xlink:href="https://github.com/uber/pam-ussh">pam-ussh</link>.
</para>
</listitem>
<listitem> <listitem>
<para> <para>
The <literal>zrepl</literal> package has been updated from The <literal>zrepl</literal> package has been updated from
@ -1780,11 +1925,25 @@
desktop environments as needed. desktop environments as needed.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
xfsprogs was update to version 5.15, which enables inobtcount
and bigtime by default on filesystem creation. Support for
these features was added in kernel 5.10 and deemed stable in
kernel 5.15. If you want to be able to mount XFS filesystems
created with this release of xfsprogs on kernel releases older
than 5.10, you need to format them with
<literal>mkfs.xfs -m bigtime=0 -m inobtcount=0</literal>.
</para>
</listitem>
<listitem> <listitem>
<para> <para>
<literal>services.xserver.desktopManager.xfce</literal> now <literal>services.xserver.desktopManager.xfce</literal> now
includes Xfces screen locker, includes Xfces screen locker,
<literal>xfce4-screensaver</literal>. <literal>xfce4-screensaver</literal> that is enabled by
default. You can disable it by setting
<literal>false</literal> to
<link linkend="opt-services.xserver.desktopManager.xfce.enableScreensaver">services.xserver.desktopManager.xfce.enableScreensaver</link>.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>

View file

@ -548,6 +548,14 @@
(<replaceable>user@host</replaceable>). You can also set ssh options by (<replaceable>user@host</replaceable>). You can also set ssh options by
defining the <envar>NIX_SSHOPTS</envar> environment variable. defining the <envar>NIX_SSHOPTS</envar> environment variable.
</para> </para>
<para>
Note that <command>nixos-rebuild</command> honors the
<literal>nixpkgs.crossSystem</literal> setting of the given configuration
but disregards the true architecture of the target host. Hence the
<literal>nixpkgs.crossSystem</literal> setting has to match the target
platform or else activation will fail.
</para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View file

@ -1,5 +1,5 @@
#! /usr/bin/env nix-shell #! /usr/bin/env nix-shell
#! nix-shell -I nixpkgs=channel:nixpkgs-unstable -i bash -p pandoc #! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs/tarball/21.11 -i bash -p pandoc
# This script is temporarily needed while we transition the manual to # This script is temporarily needed while we transition the manual to
# CommonMark. It converts the .md files in the regular manual folder # CommonMark. It converts the .md files in the regular manual folder

View file

@ -282,3 +282,5 @@ When upgrading from a previous release, please be aware of the following incompa
- The NixOS test driver supports user services declared by `systemd.user.services`. The methods `waitForUnit`, `getUnitInfo`, `startJob` and `stopJob` provide an optional `$user` argument for that purpose. - The NixOS test driver supports user services declared by `systemd.user.services`. The methods `waitForUnit`, `getUnitInfo`, `startJob` and `stopJob` provide an optional `$user` argument for that purpose.
- Enabling bash completion on NixOS, `programs.bash.enableCompletion`, will now also enable completion for the Nix command line tools by installing the [nix-bash-completions](https://github.com/hedning/nix-bash-completions) package. - Enabling bash completion on NixOS, `programs.bash.enableCompletion`, will now also enable completion for the Nix command line tools by installing the [nix-bash-completions](https://github.com/hedning/nix-bash-completions) package.
- The vim/kakoune plugin updater now reads from a CSV file: check `pkgs/applications/editors/vim/plugins/vim-plugin-names` out to see the new format

View file

@ -25,6 +25,8 @@ In addition to numerous new and upgraded packages, this release has the followin
- systemd services can now set [systemd.services.\<name\>.reloadTriggers](#opt-systemd.services) instead of `reloadIfChanged` for a more granular distinction between reloads and restarts. - systemd services can now set [systemd.services.\<name\>.reloadTriggers](#opt-systemd.services) instead of `reloadIfChanged` for a more granular distinction between reloads and restarts.
- Systemd has been upgraded to the version 250.
- [`kops`](https://kops.sigs.k8s.io) defaults to 1.22.4, which will enable [Instance Metadata Service Version 2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html) and require tokens on new clusters with Kubernetes 1.22. This will increase security by default, but may break some types of workloads. See the [release notes](https://kops.sigs.k8s.io/releases/1.22-notes/) for details. - [`kops`](https://kops.sigs.k8s.io) defaults to 1.22.4, which will enable [Instance Metadata Service Version 2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html) and require tokens on new clusters with Kubernetes 1.22. This will increase security by default, but may break some types of workloads. See the [release notes](https://kops.sigs.k8s.io/releases/1.22-notes/) for details.
- Module authors can use `mkRenamedOptionModuleWith` to automate the deprecation cycle without annoying out-of-tree module authors and their users. - Module authors can use `mkRenamedOptionModuleWith` to automate the deprecation cycle without annoying out-of-tree module authors and their users.
@ -39,6 +41,8 @@ In addition to numerous new and upgraded packages, this release has the followin
- [matrix-conduit](https://conduit.rs/), a simple, fast and reliable chat server powered by matrix. Available as [services.matrix-conduit](option.html#opt-services.matrix-conduit.enable). - [matrix-conduit](https://conduit.rs/), a simple, fast and reliable chat server powered by matrix. Available as [services.matrix-conduit](option.html#opt-services.matrix-conduit.enable).
- [nethoscope](https://github.com/vvilhonen/nethoscope), listen to your network traffic. Available as [programs.nethoscope](#opt-programs.nethoscope.enable).
- [filebeat](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-overview.html), a lightweight shipper for forwarding and centralizing log data. Available as [services.filebeat](#opt-services.filebeat.enable). - [filebeat](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-overview.html), a lightweight shipper for forwarding and centralizing log data. Available as [services.filebeat](#opt-services.filebeat.enable).
- [apfs](https://github.com/linux-apfs/linux-apfs-rw), a kernel module for mounting the Apple File System (APFS). - [apfs](https://github.com/linux-apfs/linux-apfs-rw), a kernel module for mounting the Apple File System (APFS).
@ -63,6 +67,8 @@ In addition to numerous new and upgraded packages, this release has the followin
- [K40-Whisperer](https://www.scorchworks.com/K40whisperer/k40whisperer.html), a program to control cheap Chinese laser cutters. Available as [programs.k40-whisperer.enable](options.html#opt-programs.k4-whisperer.enable). Users must add themselves to the `k40` group to be able to access the device. - [K40-Whisperer](https://www.scorchworks.com/K40whisperer/k40whisperer.html), a program to control cheap Chinese laser cutters. Available as [programs.k40-whisperer.enable](options.html#opt-programs.k4-whisperer.enable). Users must add themselves to the `k40` group to be able to access the device.
- [mozillavpn](https://github.com/mozilla-mobile/mozilla-vpn-client), the client for the [Mozilla VPN](https://vpn.mozilla.org/) service. Available as [services.mozillavpn](options.html#opt-services.mozillavpn).
- [mtr-exporter](https://github.com/mgumz/mtr-exporter), a Prometheus exporter for mtr metrics. Available as [services.mtr-exporter](options.html#opt-services.mtr-exporter.enable). - [mtr-exporter](https://github.com/mgumz/mtr-exporter), a Prometheus exporter for mtr metrics. Available as [services.mtr-exporter](options.html#opt-services.mtr-exporter.enable).
- [prometheus-pve-exporter](https://github.com/prometheus-pve/prometheus-pve-exporter), a tool that exposes information from the Proxmox VE API for use by Prometheus. Available as [services.prometheus.exporters.pve](options.html#opt-services.prometheus.exporters.pve). - [prometheus-pve-exporter](https://github.com/prometheus-pve/prometheus-pve-exporter), a tool that exposes information from the Proxmox VE API for use by Prometheus. Available as [services.prometheus.exporters.pve](options.html#opt-services.prometheus.exporters.pve).
@ -103,6 +109,8 @@ In addition to numerous new and upgraded packages, this release has the followin
- [pacemaker](https://clusterlabs.org/pacemaker/) cluster resource manager - [pacemaker](https://clusterlabs.org/pacemaker/) cluster resource manager
- [nifi](https://nifi.apache.org), an easy to use, powerful, and reliable system to process and distribute data. Available as [services.nifi](options.html#opt-services.nifi.enable).
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. --> <!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
## Backward Incompatibilities {#sec-release-22.05-incompatibilities} ## Backward Incompatibilities {#sec-release-22.05-incompatibilities}
@ -139,10 +147,21 @@ In addition to numerous new and upgraded packages, this release has the followin
org-contrib, refer to the ones in `pkgs.emacsPackages.elpaPackages` and org-contrib, refer to the ones in `pkgs.emacsPackages.elpaPackages` and
`pkgs.emacsPackages.nongnuPackages` where the new versions will release. `pkgs.emacsPackages.nongnuPackages` where the new versions will release.
- `security.klogd` was removed. Logging of kernel messages is handled
by systemd since Linux 3.5.
- `services.kubernetes.addons.dashboard` was removed due to it being an outdated version. - `services.kubernetes.addons.dashboard` was removed due to it being an outdated version.
- `services.kubernetes.scheduler.{port,address}` now set `--secure-port` and `--bind-address` instead of `--port` and `--address`, since the former have been deprecated and are no longer functional in kubernetes>=1.23. Ensure that you are not relying on the insecure behaviour before upgrading. - `services.kubernetes.scheduler.{port,address}` now set `--secure-port` and `--bind-address` instead of `--port` and `--address`, since the former have been deprecated and are no longer functional in kubernetes>=1.23. Ensure that you are not relying on the insecure behaviour before upgrading.
- In the PowerDNS Recursor module (`services.pdns-recursor`), default values of several IP address-related NixOS options have been updated to match the default upstream behavior.
In particular, Recursor by default will:
- listen on (and allows connections from) both IPv4 and IPv6 addresses
(`services.pdns-recursor.dns.address`, `services.pdns-recursor.dns.allowFrom`);
- allow only local connections to the REST API server (`services.pdns-recursor.api.allowFrom`).
- `openssh` has been update to 8.9p1, changing the FIDO security key middleware interface.
- `services.k3s.enable` no longer implies `systemd.enableUnifiedCgroupHierarchy = false`, and will default to the 'systemd' cgroup driver when using `services.k3s.docker = true`. - `services.k3s.enable` no longer implies `systemd.enableUnifiedCgroupHierarchy = false`, and will default to the 'systemd' cgroup driver when using `services.k3s.docker = true`.
This change may require a reboot to take effect, and k3s may not be able to run if the boot cgroup hierarchy does not match its configuration. This change may require a reboot to take effect, and k3s may not be able to run if the boot cgroup hierarchy does not match its configuration.
The previous behavior may be retained by explicitly setting `systemd.enableUnifiedCgroupHierarchy = false` in your configuration. The previous behavior may be retained by explicitly setting `systemd.enableUnifiedCgroupHierarchy = false` in your configuration.
@ -160,6 +179,8 @@ In addition to numerous new and upgraded packages, this release has the followin
} }
``` ```
- `services.prometheus.alertManagerTimeout` has been removed as it has been deprecated upstream and has no effect.
- The DHCP server (`services.dhcpd4`, `services.dhcpd6`) has been hardened. - The DHCP server (`services.dhcpd4`, `services.dhcpd6`) has been hardened.
The service is now using the systemd's `DynamicUser` mechanism to run as an unprivileged dynamically-allocated user with limited capabilities. The service is now using the systemd's `DynamicUser` mechanism to run as an unprivileged dynamically-allocated user with limited capabilities.
The dhcpd state files are now always stored in `/var/lib/dhcpd{4,6}` and the `services.dhcpd4.stateDir` and `service.dhcpd6.stateDir` options have been removed. The dhcpd state files are now always stored in `/var/lib/dhcpd{4,6}` and the `services.dhcpd4.stateDir` and `service.dhcpd6.stateDir` options have been removed.
@ -169,6 +190,8 @@ In addition to numerous new and upgraded packages, this release has the followin
- `services.ipfs.extraFlags` is now escaped with `utils.escapeSystemdExecArgs`. If you rely on systemd interpolating `extraFlags` in the service `ExecStart`, this will no longer work. - `services.ipfs.extraFlags` is now escaped with `utils.escapeSystemdExecArgs`. If you rely on systemd interpolating `extraFlags` in the service `ExecStart`, this will no longer work.
- `services.paperless-ng` was renamed to `services.paperless`. Accordingly, the `paperless-ng-manage` script (located in `dataDir`) was renamed to `paperless-manage`. `services.paperless` now uses `paperless-ngx`.
- The `matrix-synapse` service (`services.matrix-synapse`) has been converted to use the `settings` option defined in RFC42. - The `matrix-synapse` service (`services.matrix-synapse`) has been converted to use the `settings` option defined in RFC42.
This means that options that are part of your `homeserver.yaml` configuration, and that were specified at the top-level of the This means that options that are part of your `homeserver.yaml` configuration, and that were specified at the top-level of the
module (`services.matrix-synapse`) now need to be moved into `services.matrix-synapse.settings`. And while not all options you module (`services.matrix-synapse`) now need to be moved into `services.matrix-synapse.settings`. And while not all options you
@ -447,6 +470,11 @@ In addition to numerous new and upgraded packages, this release has the followin
See the `vscode` package for a more detailed example. See the `vscode` package for a more detailed example.
- Existing `resholve*` functions have been renamed and nested under `pkgs.resholve`. Update uses to:
- `resholvePackage` -> `resholve.mkDerivation`
- `resholveScript` -> `resholve.writeScript`
- `resholveScriptBin` -> `resholve.writeScriptBin`
- `pkgs.cosmopolitan` no longer provides the `cosmoc` command. It has been moved to `pkgs.cosmoc`. - `pkgs.cosmopolitan` no longer provides the `cosmoc` command. It has been moved to `pkgs.cosmoc`.
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. --> <!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
@ -513,6 +541,8 @@ In addition to numerous new and upgraded packages, this release has the followin
- `programs.zsh.autosuggestions.strategy` now takes a list of strings instead of a string. - `programs.zsh.autosuggestions.strategy` now takes a list of strings instead of a string.
- The `asterisk` and `asterisk-stable` packages were switched from `asterisk_18` to the newly-packaged `asterisk_19`. Asterisk 13 and 17 have been removed as they have reached their end of life.
- The `services.unifi.openPorts` option default value of `true` is now deprecated and will be changed to `false` in 22.11. - The `services.unifi.openPorts` option default value of `true` is now deprecated and will be changed to `false` in 22.11.
Configurations using this default will print a warning when rebuilt. Configurations using this default will print a warning when rebuilt.
@ -537,10 +567,14 @@ In addition to numerous new and upgraded packages, this release has the followin
e.g. Wayland. e.g. Wayland.
- [programs.ssh.knownHosts](#opt-programs.ssh.knownHosts) has gained an `extraHostNames` - [programs.ssh.knownHosts](#opt-programs.ssh.knownHosts) has gained an `extraHostNames`
option to replace `hostNames`. `hostNames` is deprecated, but still available for now. option to augment `hostNames`. It is now possible to use the attribute name of a `knownHosts`
entry as the primary host name and specify secondary host names using `extraHostNames` without
having to duplicate the primary host name.
- The `services.stubby` module was converted to a [settings-style](https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md) configuration. - The `services.stubby` module was converted to a [settings-style](https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md) configuration.
- A new module was added for the Envoy reverse proxy, providing the options `services.envoy.enable` and `services.envoy.settings`.
- The option `services.duplicati.dataDir` has been added to allow changing the location of duplicati's files. - The option `services.duplicati.dataDir` has been added to allow changing the location of duplicati's files.
- The options `boot.extraModprobeConfig` and `boot.blacklistedKernelModules` now also take effect in the initrd by copying the file `/etc/modprobe.d/nixos.conf` into the initrd. - The options `boot.extraModprobeConfig` and `boot.blacklistedKernelModules` now also take effect in the initrd by copying the file `/etc/modprobe.d/nixos.conf` into the initrd.
@ -559,6 +593,8 @@ In addition to numerous new and upgraded packages, this release has the followin
using `fetchgit` or `fetchhg` if the argument `fetchSubmodules` using `fetchgit` or `fetchhg` if the argument `fetchSubmodules`
is set to `true`. is set to `true`.
- A module for declarative configuration of openconnect VPN profiles was added under `networking.openconnect`.
- The `element-desktop` package now has an `useKeytar` option (defaults to `true`), - The `element-desktop` package now has an `useKeytar` option (defaults to `true`),
which allows disabling `keytar` and in turn `libsecret` usage which allows disabling `keytar` and in turn `libsecret` usage
(which binds to native credential managers / keychain libraries). (which binds to native credential managers / keychain libraries).
@ -589,6 +625,8 @@ In addition to numerous new and upgraded packages, this release has the followin
and [services.logrotate.extraConfig](#opt-services.logrotate.extraConfig) will work, but issue deprecation and [services.logrotate.extraConfig](#opt-services.logrotate.extraConfig) will work, but issue deprecation
warnings and [services.logrotate.settings](#opt-services.logrotate.settings) should now be used instead. warnings and [services.logrotate.settings](#opt-services.logrotate.settings) should now be used instead.
- `security.pam.ussh` has been added, which allows authorizing PAM sessions based on SSH _certificates_ held within an SSH agent, using [pam-ussh](https://github.com/uber/pam-ussh).
- The `zrepl` package has been updated from 0.4.0 to 0.5: - The `zrepl` package has been updated from 0.4.0 to 0.5:
- The RPC protocol version was bumped; all zrepl daemons in a setup must be updated and restarted before replication can resume. - The RPC protocol version was bumped; all zrepl daemons in a setup must be updated and restarted before replication can resume.
@ -615,7 +653,10 @@ In addition to numerous new and upgraded packages, this release has the followin
- The polkit service, available at `security.polkit.enable`, is now disabled by default. It will automatically be enabled through services and desktop environments as needed. - The polkit service, available at `security.polkit.enable`, is now disabled by default. It will automatically be enabled through services and desktop environments as needed.
- `services.xserver.desktopManager.xfce` now includes Xfce's screen locker, `xfce4-screensaver`. - xfsprogs was update to version 5.15, which enables inobtcount and bigtime by default on filesystem creation. Support for these features was added in kernel 5.10 and deemed stable in kernel 5.15.
If you want to be able to mount XFS filesystems created with this release of xfsprogs on kernel releases older than 5.10, you need to format them with `mkfs.xfs -m bigtime=0 -m inobtcount=0`.
- `services.xserver.desktopManager.xfce` now includes Xfce's screen locker, `xfce4-screensaver` that is enabled by default. You can disable it by setting `false` to [services.xserver.desktopManager.xfce.enableScreensaver](#opt-services.xserver.desktopManager.xfce.enableScreensaver).
- The `hadoop` package has added support for `aarch64-linux` and `aarch64-darwin` as of 3.3.1 ([#158613](https://github.com/NixOS/nixpkgs/pull/158613)). - The `hadoop` package has added support for `aarch64-linux` and `aarch64-darwin` as of 3.3.1 ([#158613](https://github.com/NixOS/nixpkgs/pull/158613)).

View file

@ -170,6 +170,7 @@ let format' = format; in let
config.system.build.nixos-install config.system.build.nixos-install
config.system.build.nixos-enter config.system.build.nixos-enter
nix nix
systemdMinimal
] ++ stdenv.initialPath); ] ++ stdenv.initialPath);
# I'm preserving the line below because I'm going to search for it across nixpkgs to consolidate # I'm preserving the line below because I'm going to search for it across nixpkgs to consolidate

View file

@ -48,6 +48,8 @@ overrides = pivot(json.load(open(sys.argv[2 + optOffset], 'r')))
# fix up declaration paths in lazy options, since we don't eval them from a full nixpkgs dir # fix up declaration paths in lazy options, since we don't eval them from a full nixpkgs dir
for (k, v) in options.items(): for (k, v) in options.items():
# The _module options are not declared in nixos/modules
if v.value['loc'][0] != "_module":
v.value['declarations'] = list(map(lambda s: f'nixos/modules/{s}', v.value['declarations'])) v.value['declarations'] = list(map(lambda s: f'nixos/modules/{s}', v.value['declarations']))
# merge both descriptions # merge both descriptions

View file

@ -23,8 +23,8 @@ rec {
qemuBinary = qemuPkg: { qemuBinary = qemuPkg: {
x86_64-linux = "${qemuPkg}/bin/qemu-kvm -cpu max"; 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 -machine virt,accel=kvm:tcg -cpu max";
aarch64-linux = "${qemuPkg}/bin/qemu-system-aarch64 -enable-kvm -machine virt,gic-version=host -cpu host"; aarch64-linux = "${qemuPkg}/bin/qemu-system-aarch64 -machine virt,gic-version=max,accel=kvm:tcg -cpu max";
powerpc64le-linux = "${qemuPkg}/bin/qemu-system-ppc64 -machine powernv"; powerpc64le-linux = "${qemuPkg}/bin/qemu-system-ppc64 -machine powernv";
powerpc64-linux = "${qemuPkg}/bin/qemu-system-ppc64 -machine powernv"; powerpc64-linux = "${qemuPkg}/bin/qemu-system-ppc64 -machine powernv";
x86_64-darwin = "${qemuPkg}/bin/qemu-kvm -cpu max"; x86_64-darwin = "${qemuPkg}/bin/qemu-kvm -cpu max";

View file

@ -94,7 +94,8 @@ in rec {
}; };
commonUnitOptions = { options = (sharedOptions // { commonUnitOptions = {
options = sharedOptions // {
description = mkOption { description = mkOption {
default = ""; default = "";
@ -218,7 +219,8 @@ in rec {
''; '';
}; };
}); }; };
};
stage2CommonUnitOptions = { stage2CommonUnitOptions = {
imports = [ imports = [
@ -250,7 +252,8 @@ in rec {
}; };
stage1CommonUnitOptions = commonUnitOptions; stage1CommonUnitOptions = commonUnitOptions;
serviceOptions = { options = { serviceOptions = { name, config, ... }: {
options = {
environment = mkOption { environment = mkOption {
default = {}; default = {};
@ -284,15 +287,6 @@ in rec {
''; '';
}; };
}; };
stage2ServiceOptions = { name, config, ... }: {
imports = [
stage2CommonUnitOptions
serviceOptions
];
options = {
script = mkOption { script = mkOption {
type = types.lines; type = types.lines;
default = ""; default = "";
@ -349,6 +343,51 @@ in rec {
''; '';
}; };
jobScripts = mkOption {
type = with types; coercedTo path singleton (listOf path);
internal = true;
description = "A list of all job script derivations of this unit.";
default = [];
};
};
config = mkMerge [
(mkIf (config.preStart != "") rec {
jobScripts = makeJobScript "${name}-pre-start" config.preStart;
serviceConfig.ExecStartPre = [ jobScripts ];
})
(mkIf (config.script != "") rec {
jobScripts = makeJobScript "${name}-start" config.script;
serviceConfig.ExecStart = jobScripts + " " + config.scriptArgs;
})
(mkIf (config.postStart != "") rec {
jobScripts = (makeJobScript "${name}-post-start" config.postStart);
serviceConfig.ExecStartPost = [ jobScripts ];
})
(mkIf (config.reload != "") rec {
jobScripts = makeJobScript "${name}-reload" config.reload;
serviceConfig.ExecReload = jobScripts;
})
(mkIf (config.preStop != "") rec {
jobScripts = makeJobScript "${name}-pre-stop" config.preStop;
serviceConfig.ExecStop = jobScripts;
})
(mkIf (config.postStop != "") rec {
jobScripts = makeJobScript "${name}-post-stop" config.postStop;
serviceConfig.ExecStopPost = jobScripts;
})
];
};
stage2ServiceOptions = {
imports = [
stage2CommonUnitOptions
serviceOptions
];
options = {
restartIfChanged = mkOption { restartIfChanged = mkOption {
type = types.bool; type = types.bool;
default = true; default = true;
@ -404,33 +443,6 @@ in rec {
apply = v: if isList v then v else [ v ]; apply = v: if isList v then v else [ v ];
}; };
}; };
config = mkMerge
[ (mkIf (config.preStart != "")
{ serviceConfig.ExecStartPre =
[ (makeJobScript "${name}-pre-start" config.preStart) ];
})
(mkIf (config.script != "")
{ serviceConfig.ExecStart =
makeJobScript "${name}-start" config.script + " " + config.scriptArgs;
})
(mkIf (config.postStart != "")
{ serviceConfig.ExecStartPost =
[ (makeJobScript "${name}-post-start" config.postStart) ];
})
(mkIf (config.reload != "")
{ serviceConfig.ExecReload =
makeJobScript "${name}-reload" config.reload;
})
(mkIf (config.preStop != "")
{ serviceConfig.ExecStop =
makeJobScript "${name}-pre-stop" config.preStop;
})
(mkIf (config.postStop != "")
{ serviceConfig.ExecStopPost =
makeJobScript "${name}-post-stop" config.postStop;
})
];
}; };
stage1ServiceOptions = { stage1ServiceOptions = {
@ -441,7 +453,8 @@ in rec {
}; };
socketOptions = { options = { socketOptions = {
options = {
listenStreams = mkOption { listenStreams = mkOption {
default = []; default = [];
@ -474,8 +487,9 @@ in rec {
<manvolnum>5</manvolnum></citerefentry> for details. <manvolnum>5</manvolnum></citerefentry> for details.
''; '';
}; };
};
}; }; };
stage2SocketOptions = { stage2SocketOptions = {
imports = [ imports = [
@ -492,7 +506,8 @@ in rec {
}; };
timerOptions = { options = { timerOptions = {
options = {
timerConfig = mkOption { timerConfig = mkOption {
default = {}; default = {};
@ -508,7 +523,8 @@ in rec {
''; '';
}; };
}; }; };
};
stage2TimerOptions = { stage2TimerOptions = {
imports = [ imports = [
@ -525,7 +541,8 @@ in rec {
}; };
pathOptions = { options = { pathOptions = {
options = {
pathConfig = mkOption { pathConfig = mkOption {
default = {}; default = {};
@ -539,7 +556,8 @@ in rec {
''; '';
}; };
}; }; };
};
stage2PathOptions = { stage2PathOptions = {
imports = [ imports = [
@ -556,7 +574,8 @@ in rec {
}; };
mountOptions = { options = { mountOptions = {
options = {
what = mkOption { what = mkOption {
example = "/dev/sda1"; example = "/dev/sda1";
@ -598,7 +617,9 @@ in rec {
<manvolnum>5</manvolnum></citerefentry> for details. <manvolnum>5</manvolnum></citerefentry> for details.
''; '';
}; };
}; };
};
};
stage2MountOptions = { stage2MountOptions = {
imports = [ imports = [
@ -614,7 +635,8 @@ in rec {
]; ];
}; };
automountOptions = { options = { automountOptions = {
options = {
where = mkOption { where = mkOption {
example = "/mnt"; example = "/mnt";
@ -636,7 +658,9 @@ in rec {
<manvolnum>5</manvolnum></citerefentry> for details. <manvolnum>5</manvolnum></citerefentry> for details.
''; '';
}; };
}; };
};
};
stage2AutomountOptions = { stage2AutomountOptions = {
imports = [ imports = [
@ -652,7 +676,8 @@ in rec {
]; ];
}; };
sliceOptions = { options = { sliceOptions = {
options = {
sliceConfig = mkOption { sliceConfig = mkOption {
default = {}; default = {};
@ -666,7 +691,8 @@ in rec {
''; '';
}; };
}; }; };
};
stage2SliceOptions = { stage2SliceOptions = {
imports = [ imports = [

View file

@ -86,7 +86,7 @@ class Driver:
def subtest(self, name: str) -> Iterator[None]: def subtest(self, name: str) -> Iterator[None]:
"""Group logs under a given test name""" """Group logs under a given test name"""
with rootlog.nested(name): with rootlog.nested("subtest: " + name):
try: try:
yield yield
return True return True

View file

@ -1,4 +1,4 @@
from colorama import Style from colorama import Style, Fore
from contextlib import contextmanager from contextlib import contextmanager
from typing import Any, Dict, Iterator from typing import Any, Dict, Iterator
from queue import Queue, Empty from queue import Queue, Empty
@ -81,7 +81,11 @@ class Logger:
@contextmanager @contextmanager
def nested(self, message: str, attributes: Dict[str, str] = {}) -> Iterator[None]: def nested(self, message: str, attributes: Dict[str, str] = {}) -> Iterator[None]:
self._eprint(self.maybe_prefix(message, attributes)) self._eprint(
self.maybe_prefix(
Style.BRIGHT + Fore.GREEN + message + Style.RESET_ALL, attributes
)
)
self.xml.startElement("nest", attrs={}) self.xml.startElement("nest", attrs={})
self.xml.startElement("head", attributes) self.xml.startElement("head", attributes)

View file

@ -194,6 +194,22 @@ rec {
(( ! $inherit_errexit_enabled )) && shopt -u inherit_errexit (( ! $inherit_errexit_enabled )) && shopt -u inherit_errexit
''; '';
/* Remove packages of packagesToRemove from packages, based on their names.
Relies on package names and has quadratic complexity so use with caution!
Type:
removePackagesByName :: [package] -> [package] -> [package]
Example:
removePackagesByName [ nautilus file-roller ] [ file-roller totem ]
=> [ nautilus ]
*/
removePackagesByName = packages: packagesToRemove:
let
namesToRemove = map lib.getName packagesToRemove;
in
lib.filter (x: !(builtins.elem (lib.getName x) namesToRemove)) packages;
systemdUtils = { systemdUtils = {
lib = import ./systemd-lib.nix { inherit lib config pkgs; }; lib = import ./systemd-lib.nix { inherit lib config pkgs; };
unitOptions = import ./systemd-unit-options.nix { inherit lib systemdUtils; }; unitOptions = import ./systemd-unit-options.nix { inherit lib systemdUtils; };

View file

@ -12,7 +12,7 @@ let
optimizedKeymap = pkgs.runCommand "keymap" { optimizedKeymap = pkgs.runCommand "keymap" {
nativeBuildInputs = [ pkgs.buildPackages.kbd ]; nativeBuildInputs = [ pkgs.buildPackages.kbd ];
LOADKEYS_KEYMAP_PATH = "${consoleEnv}/share/keymaps/**"; LOADKEYS_KEYMAP_PATH = "${consoleEnv pkgs.kbd}/share/keymaps/**";
preferLocalBuild = true; preferLocalBuild = true;
} '' } ''
loadkeys -b ${optionalString isUnicode "-u"} "${cfg.keyMap}" > $out loadkeys -b ${optionalString isUnicode "-u"} "${cfg.keyMap}" > $out
@ -24,9 +24,9 @@ let
FONT=${cfg.font} FONT=${cfg.font}
''; '';
consoleEnv = pkgs.buildEnv { consoleEnv = kbd: pkgs.buildEnv {
name = "console-env"; name = "console-env";
paths = [ pkgs.kbd ] ++ cfg.packages; paths = [ kbd ] ++ cfg.packages;
pathsToLink = [ pathsToLink = [
"/share/consolefonts" "/share/consolefonts"
"/share/consoletrans" "/share/consoletrans"
@ -136,9 +136,9 @@ in
# virtual consoles. # virtual consoles.
environment.etc."vconsole.conf".source = vconsoleConf; environment.etc."vconsole.conf".source = vconsoleConf;
# Provide kbd with additional packages. # Provide kbd with additional packages.
environment.etc.kbd.source = "${consoleEnv}/share"; environment.etc.kbd.source = "${consoleEnv pkgs.kbd}/share";
boot.initrd.preLVMCommands = mkBefore '' boot.initrd.preLVMCommands = mkIf (!config.boot.initrd.systemd.enable) (mkBefore ''
kbd_mode ${if isUnicode then "-u" else "-a"} -C /dev/console kbd_mode ${if isUnicode then "-u" else "-a"} -C /dev/console
printf "\033%%${if isUnicode then "G" else "@"}" >> /dev/console printf "\033%%${if isUnicode then "G" else "@"}" >> /dev/console
loadkmap < ${optimizedKeymap} loadkmap < ${optimizedKeymap}
@ -146,12 +146,23 @@ in
${optionalString cfg.earlySetup '' ${optionalString cfg.earlySetup ''
setfont -C /dev/console $extraUtils/share/consolefonts/font.psf setfont -C /dev/console $extraUtils/share/consolefonts/font.psf
''} ''}
''; '');
boot.initrd.systemd.contents = {
"/etc/kbd".source = "${consoleEnv config.boot.initrd.systemd.package.kbd}/share";
"/etc/vconsole.conf".source = vconsoleConf;
};
boot.initrd.systemd.storePaths = [
"${config.boot.initrd.systemd.package}/lib/systemd/systemd-vconsole-setup"
"${config.boot.initrd.systemd.package.kbd}/bin/setfont"
"${config.boot.initrd.systemd.package.kbd}/bin/loadkeys"
"${config.boot.initrd.systemd.package.kbd.gzip}/bin/gzip" # keyboard layouts are compressed
];
systemd.services.reload-systemd-vconsole-setup = systemd.services.reload-systemd-vconsole-setup =
{ description = "Reset console on configuration changes"; { description = "Reset console on configuration changes";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
restartTriggers = [ vconsoleConf consoleEnv ]; restartTriggers = [ vconsoleConf (consoleEnv pkgs.kbd) ];
reloadIfChanged = true; reloadIfChanged = true;
serviceConfig = serviceConfig =
{ RemainAfterExit = true; { RemainAfterExit = true;
@ -175,7 +186,7 @@ in
${if substring 0 1 cfg.font == "/" then '' ${if substring 0 1 cfg.font == "/" then ''
font="${cfg.font}" font="${cfg.font}"
'' else '' '' else ''
font="$(echo ${consoleEnv}/share/consolefonts/${cfg.font}.*)" font="$(echo ${consoleEnv pkgs.kbd}/share/consolefonts/${cfg.font}.*)"
''} ''}
if [[ $font == *.gz ]]; then if [[ $font == *.gz ]]; then
gzip -cd $font > $out/share/consolefonts/font.psf gzip -cd $font > $out/share/consolefonts/font.psf
@ -183,6 +194,10 @@ in
cp -L $font $out/share/consolefonts/font.psf cp -L $font $out/share/consolefonts/font.psf
fi fi
''; '';
assertions = [{
assertion = !config.boot.initrd.systemd.enable;
message = "console.earlySetup is implied by systemd stage 1";
}];
}) })
])) ]))
]; ];

View file

@ -1,9 +1,33 @@
# This module manages the terminfo database # This module manages the terminfo database
# and its integration in the system. # and its integration in the system.
{ config, ... }: { config, lib, pkgs, ... }:
with lib;
{ {
options.environment.enableAllTerminfo = with lib; mkOption {
default = false;
type = types.bool;
description = ''
Whether to install all terminfo outputs
'';
};
config = { config = {
# can be generated with: filter (drv: (builtins.tryEval (drv ? terminfo)).value) (attrValues pkgs)
environment.systemPackages = mkIf config.environment.enableAllTerminfo (map (x: x.terminfo) (with pkgs; [
alacritty
foot
kitty
mtm
rxvt-unicode-unwrapped
rxvt-unicode-unwrapped-emoji
termite
wezterm
]));
environment.pathsToLink = [ environment.pathsToLink = [
"/share/terminfo" "/share/terminfo"
]; ];

View file

@ -16,11 +16,6 @@ in
config = mkIf cfg.enable { config = mkIf cfg.enable {
assertions = singleton {
assertion = versionAtLeast kernelPackages.kernel.version "3.19";
message = "facetimehd is not supported for kernels older than 3.19";
};
boot.kernelModules = [ "facetimehd" ]; boot.kernelModules = [ "facetimehd" ];
boot.blacklistedKernelModules = [ "bdc_pci" ]; boot.blacklistedKernelModules = [ "bdc_pci" ];

View file

@ -0,0 +1,51 @@
# This module exposes a config.system.build.kexecBoot attribute,
# which returns a directory with kernel, initrd and a shell script
# running the necessary kexec commands.
# It's meant to be scp'ed to a machine with working ssh and kexec binary
# installed.
# This is useful for (cloud) providers where you can't boot a custom image, but
# get some Debian or Ubuntu installation.
{ pkgs
, modulesPath
, config
, ...
}:
{
imports = [
(modulesPath + "/installer/netboot/netboot-minimal.nix")
];
config = {
system.build.kexecBoot =
let
kexecScript = pkgs.writeScript "kexec-boot" ''
#!/usr/bin/env bash
if ! kexec -v >/dev/null 2>&1; then
echo "kexec not found: please install kexec-tools" 2>&1
exit 1
fi
SCRIPT_DIR=$( cd -- "$( dirname -- "''${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
kexec --load ''${SCRIPT_DIR}/bzImage \
--initrd=''${SCRIPT_DIR}/initrd.gz \
--command-line "init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}"
kexec -e
''; in
pkgs.linkFarm "kexec-tree" [
{
name = "initrd.gz";
path = "${config.system.build.netbootRamdisk}/initrd";
}
{
name = "bzImage";
path = "${config.system.build.kernel}/bzImage";
}
{
name = "kexec-boot";
path = kexecScript;
}
];
};
}

View file

@ -64,7 +64,8 @@ let
filter = filter =
builtins.filterSource builtins.filterSource
(n: t: (n: t:
(t == "directory" -> baseNameOf n != "tests") cleanSourceFilter n t
&& (t == "directory" -> baseNameOf n != "tests")
&& (t == "file" -> hasSuffix ".nix" n) && (t == "file" -> hasSuffix ".nix" n)
); );
in in

View file

@ -185,6 +185,7 @@
./programs/nbd.nix ./programs/nbd.nix
./programs/nix-ld.nix ./programs/nix-ld.nix
./programs/neovim.nix ./programs/neovim.nix
./programs/nethoscope.nix
./programs/nm-applet.nix ./programs/nm-applet.nix
./programs/nncp.nix ./programs/nncp.nix
./programs/npm.nix ./programs/npm.nix
@ -596,7 +597,7 @@
./services/misc/osrm.nix ./services/misc/osrm.nix
./services/misc/owncast.nix ./services/misc/owncast.nix
./services/misc/packagekit.nix ./services/misc/packagekit.nix
./services/misc/paperless-ng.nix ./services/misc/paperless.nix
./services/misc/parsoid.nix ./services/misc/parsoid.nix
./services/misc/plex.nix ./services/misc/plex.nix
./services/misc/plikd.nix ./services/misc/plikd.nix
@ -753,6 +754,7 @@
./services/networking/ncdns.nix ./services/networking/ncdns.nix
./services/networking/nomad.nix ./services/networking/nomad.nix
./services/networking/ejabberd.nix ./services/networking/ejabberd.nix
./services/networking/envoy.nix
./services/networking/epmd.nix ./services/networking/epmd.nix
./services/networking/ergo.nix ./services/networking/ergo.nix
./services/networking/ergochat.nix ./services/networking/ergochat.nix
@ -815,6 +817,7 @@
./services/networking/mosquitto.nix ./services/networking/mosquitto.nix
./services/networking/monero.nix ./services/networking/monero.nix
./services/networking/morty.nix ./services/networking/morty.nix
./services/networking/mozillavpn.nix
./services/networking/miredo.nix ./services/networking/miredo.nix
./services/networking/mstpd.nix ./services/networking/mstpd.nix
./services/networking/mtprotoproxy.nix ./services/networking/mtprotoproxy.nix
@ -850,6 +853,7 @@
./services/networking/ofono.nix ./services/networking/ofono.nix
./services/networking/oidentd.nix ./services/networking/oidentd.nix
./services/networking/onedrive.nix ./services/networking/onedrive.nix
./services/networking/openconnect.nix
./services/networking/openvpn.nix ./services/networking/openvpn.nix
./services/networking/ostinato.nix ./services/networking/ostinato.nix
./services/networking/owamp.nix ./services/networking/owamp.nix
@ -1051,6 +1055,7 @@
./services/web-apps/netbox.nix ./services/web-apps/netbox.nix
./services/web-apps/nextcloud.nix ./services/web-apps/nextcloud.nix
./services/web-apps/nexus.nix ./services/web-apps/nexus.nix
./services/web-apps/nifi.nix
./services/web-apps/node-red.nix ./services/web-apps/node-red.nix
./services/web-apps/pict-rs.nix ./services/web-apps/pict-rs.nix
./services/web-apps/peertube.nix ./services/web-apps/peertube.nix
@ -1181,6 +1186,7 @@
./system/boot/systemd/tmpfiles.nix ./system/boot/systemd/tmpfiles.nix
./system/boot/systemd/user.nix ./system/boot/systemd/user.nix
./system/boot/systemd/initrd.nix ./system/boot/systemd/initrd.nix
./system/boot/systemd/initrd-mdraid.nix
./system/boot/timesyncd.nix ./system/boot/timesyncd.nix
./system/boot/tmp.nix ./system/boot/tmp.nix
./system/etc/etc-activation.nix ./system/etc/etc-activation.nix

View file

@ -0,0 +1,30 @@
{ config, lib, pkgs, ... }:
with lib;
let cfg = config.programs.nethoscope;
in
{
meta.maintainers = with maintainers; [ _0x4A6F ];
options = {
programs.nethoscope = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to add nethoscope to the global environment and configure a
setcap wrapper for it.
'';
};
};
};
config = mkIf cfg.enable {
environment.systemPackages = with pkgs; [ nethoscope ];
security.wrappers.nethoscope = {
source = "${pkgs.nethoscope}/bin/nethoscope";
capabilities = "cap_net_raw,cap_net_admin=eip";
};
};
}

View file

@ -157,9 +157,13 @@ in
default = [ name ] ++ config.extraHostNames; default = [ name ] ++ config.extraHostNames;
defaultText = literalExpression "[ ${name} ] ++ config.${options.extraHostNames}"; defaultText = literalExpression "[ ${name} ] ++ config.${options.extraHostNames}";
description = '' description = ''
DEPRECATED, please use <literal>extraHostNames</literal>.
A list of host names and/or IP numbers used for accessing A list of host names and/or IP numbers used for accessing
the host's ssh service. the host's ssh service. This list includes the name of the
containing <literal>knownHosts</literal> attribute by default
for convenience. If you wish to configure multiple host keys
for the same host use multiple <literal>knownHosts</literal>
entries with different attribute names and the same
<literal>hostNames</literal> list.
''; '';
}; };
extraHostNames = mkOption { extraHostNames = mkOption {
@ -167,7 +171,8 @@ in
default = []; default = [];
description = '' description = ''
A list of additional host names and/or IP numbers used for A list of additional host names and/or IP numbers used for
accessing the host's ssh service. accessing the host's ssh service. This list is ignored if
<literal>hostNames</literal> is set explicitly.
''; '';
}; };
publicKey = mkOption { publicKey = mkOption {
@ -198,7 +203,12 @@ in
}; };
})); }));
description = '' description = ''
The set of system-wide known SSH hosts. The set of system-wide known SSH hosts. To make simple setups more
convenient the name of an attribute in this set is used as a host name
for the entry. This behaviour can be disabled by setting
<literal>hostNames</literal> explicitly. You can use
<literal>extraHostNames</literal> to add additional host names without
disabling this default.
''; '';
example = literalExpression '' example = literalExpression ''
{ {
@ -207,6 +217,10 @@ in
publicKeyFile = ./pubkeys/myhost_ssh_host_dsa_key.pub; publicKeyFile = ./pubkeys/myhost_ssh_host_dsa_key.pub;
}; };
"myhost2.net".publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILIRuJ8p1Fi+m6WkHV0KWnRfpM1WxoW8XAS+XvsSKsTK"; "myhost2.net".publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILIRuJ8p1Fi+m6WkHV0KWnRfpM1WxoW8XAS+XvsSKsTK";
"myhost2.net/dsa" = {
hostNames = [ "myhost2.net" ];
publicKeyFile = ./pubkeys/myhost2_ssh_host_dsa_key.pub;
};
} }
''; '';
}; };
@ -279,9 +293,6 @@ in
message = "knownHost ${name} must contain either a publicKey or publicKeyFile"; message = "knownHost ${name} must contain either a publicKey or publicKeyFile";
}); });
warnings = mapAttrsToList (name: _: ''programs.ssh.knownHosts.${name}.hostNames is deprecated, use programs.ssh.knownHosts.${name}.extraHostNames'')
(filterAttrs (name: {hostNames, extraHostNames, ...}: hostNames != [ name ] ++ extraHostNames) cfg.knownHosts);
# SSH configuration. Slight duplication of the sshd_config # SSH configuration. Slight duplication of the sshd_config
# generation in the sshd service. # generation in the sshd service.
environment.etc."ssh/ssh_config".text = environment.etc."ssh/ssh_config".text =

View file

@ -61,6 +61,19 @@ let
''; '';
}; };
usshAuth = mkOption {
default = false;
type = types.bool;
description = ''
If set, users with an SSH certificate containing an authorized principal
in their SSH agent are able to log in. Specific options are controlled
using the <option>security.pam.ussh</option> options.
Note that the <option>security.pam.ussh.enable</option> must also be
set for this option to take effect.
'';
};
yubicoAuth = mkOption { yubicoAuth = mkOption {
default = config.security.pam.yubico.enable; default = config.security.pam.yubico.enable;
defaultText = literalExpression "config.security.pam.yubico.enable"; defaultText = literalExpression "config.security.pam.yubico.enable";
@ -475,6 +488,9 @@ let
optionalString cfg.usbAuth '' optionalString cfg.usbAuth ''
auth sufficient ${pkgs.pam_usb}/lib/security/pam_usb.so auth sufficient ${pkgs.pam_usb}/lib/security/pam_usb.so
'' + '' +
(let ussh = config.security.pam.ussh; in optionalString (config.security.pam.ussh.enable && cfg.usshAuth) ''
auth ${ussh.control} ${pkgs.pam_ussh}/lib/security/pam_ussh.so ${optionalString (ussh.caFile != null) "ca_file=${ussh.caFile}"} ${optionalString (ussh.authorizedPrincipals != null) "authorized_principals=${ussh.authorizedPrincipals}"} ${optionalString (ussh.authorizedPrincipalsFile != null) "authorized_principals_file=${ussh.authorizedPrincipalsFile}"} ${optionalString (ussh.group != null) "group=${ussh.group}"}
'') +
(let oath = config.security.pam.oath; in optionalString cfg.oathAuth '' (let oath = config.security.pam.oath; in optionalString cfg.oathAuth ''
auth requisite ${pkgs.oathToolkit}/lib/security/pam_oath.so window=${toString oath.window} usersfile=${toString oath.usersFile} digits=${toString oath.digits} auth requisite ${pkgs.oathToolkit}/lib/security/pam_oath.so window=${toString oath.window} usersfile=${toString oath.usersFile} digits=${toString oath.digits}
'') + '') +
@ -594,6 +610,7 @@ let
session optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so session optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so
'' + '' +
optionalString cfg.pamMount '' optionalString cfg.pamMount ''
session [success=1 default=ignore] ${pkgs.pam}/lib/security/pam_succeed_if.so service = systemd-user quiet
session optional ${pkgs.pam_mount}/lib/security/pam_mount.so disable_interactive session optional ${pkgs.pam_mount}/lib/security/pam_mount.so disable_interactive
'' + '' +
optionalString use_ldap '' optionalString use_ldap ''
@ -926,6 +943,96 @@ in
}; };
}; };
security.pam.ussh = {
enable = mkOption {
default = false;
type = types.bool;
description = ''
Enables Uber's USSH PAM (<literal>pam-ussh</literal>) module.
This is similar to <literal>pam-ssh-agent</literal>, except that
the presence of a CA-signed SSH key with a valid principal is checked
instead.
Note that this module must both be enabled using this option and on a
per-PAM-service level as well (using <literal>usshAuth</literal>).
More information can be found <link
xlink:href="https://github.com/uber/pam-ussh">here</link>.
'';
};
caFile = mkOption {
default = null;
type = with types; nullOr path;
description = ''
By default <literal>pam-ussh</literal> reads the trusted user CA keys
from <filename>/etc/ssh/trusted_user_ca</filename>.
This should be set the same as your <literal>TrustedUserCAKeys</literal>
option for sshd.
'';
};
authorizedPrincipals = mkOption {
default = null;
type = with types; nullOr commas;
description = ''
Comma-separated list of authorized principals to permit; if the user
presents a certificate with one of these principals, then they will be
authorized.
Note that <literal>pam-ussh</literal> also requires that the certificate
contain a principal matching the user's username. The principals from
this list are in addition to those principals.
Mutually exclusive with <literal>authorizedPrincipalsFile</literal>.
'';
};
authorizedPrincipalsFile = mkOption {
default = null;
type = with types; nullOr path;
description = ''
Path to a list of principals; if the user presents a certificate with
one of these principals, then they will be authorized.
Note that <literal>pam-ussh</literal> also requires that the certificate
contain a principal matching the user's username. The principals from
this file are in addition to those principals.
Mutually exclusive with <literal>authorizedPrincipals</literal>.
'';
};
group = mkOption {
default = null;
type = with types; nullOr str;
description = ''
If set, then the authenticating user must be a member of this group
to use this module.
'';
};
control = mkOption {
default = "sufficient";
type = types.enum [ "required" "requisite" "sufficient" "optional" ];
description = ''
This option sets pam "control".
If you want to have multi factor authentication, use "required".
If you want to use the SSH certificate instead of the regular password,
use "sufficient".
Read
<citerefentry>
<refentrytitle>pam.conf</refentrytitle>
<manvolnum>5</manvolnum>
</citerefentry>
for better understanding of this option.
'';
};
};
security.pam.yubico = { security.pam.yubico = {
enable = mkOption { enable = mkOption {
default = false; default = false;
@ -1110,6 +1217,9 @@ in
optionalString (isEnabled (cfg: cfg.usbAuth)) '' optionalString (isEnabled (cfg: cfg.usbAuth)) ''
mr ${pkgs.pam_usb}/lib/security/pam_usb.so, mr ${pkgs.pam_usb}/lib/security/pam_usb.so,
'' + '' +
optionalString (isEnabled (cfg: cfg.usshAuth)) ''
mr ${pkgs.pam_ussh}/lib/security/pam_ussh.so,
'' +
optionalString (isEnabled (cfg: cfg.oathAuth)) '' optionalString (isEnabled (cfg: cfg.oathAuth)) ''
"mr ${pkgs.oathToolkit}/lib/security/pam_oath.so, "mr ${pkgs.oathToolkit}/lib/security/pam_oath.so,
'' + '' +

View file

@ -5,6 +5,14 @@ with lib;
let let
cfg = config.security.pam.mount; cfg = config.security.pam.mount;
oflRequired = cfg.logoutHup || cfg.logoutTerm || cfg.logoutKill;
fake_ofl = pkgs.writeShellScriptBin "fake_ofl" ''
SIGNAL=$1
MNTPT=$2
${pkgs.lsof}/bin/lsof | ${pkgs.gnugrep}/bin/grep $MNTPT | ${pkgs.gawk}/bin/awk '{print $2}' | ${pkgs.findutils}/bin/xargs ${pkgs.util-linux}/bin/kill -$SIGNAL
'';
anyPamMount = any (attrByPath ["pamMount"] false) (attrValues config.security.pam.services); anyPamMount = any (attrByPath ["pamMount"] false) (attrValues config.security.pam.services);
in in
@ -51,6 +59,71 @@ in
You can define volume-specific options in the volume definitions. You can define volume-specific options in the volume definitions.
''; '';
}; };
debugLevel = mkOption {
type = types.int;
default = 0;
example = 1;
description = ''
Sets the Debug-Level. 0 disables debugging, 1 enables pam_mount tracing,
and 2 additionally enables tracing in mount.crypt. The default is 0.
For more information, visit <link
xlink:href="http://pam-mount.sourceforge.net/pam_mount.conf.5.html" />.
'';
};
logoutWait = mkOption {
type = types.int;
default = 0;
description = ''
Amount of microseconds to wait until killing remaining processes after
final logout.
For more information, visit <link
xlink:href="http://pam-mount.sourceforge.net/pam_mount.conf.5.html" />.
'';
};
logoutHup = mkOption {
type = types.bool;
default = false;
description = ''
Kill remaining processes after logout by sending a SIGHUP.
'';
};
logoutTerm = mkOption {
type = types.bool;
default = false;
description = ''
Kill remaining processes after logout by sending a SIGTERM.
'';
};
logoutKill = mkOption {
type = types.bool;
default = false;
description = ''
Kill remaining processes after logout by sending a SIGKILL.
'';
};
createMountPoints = mkOption {
type = types.bool;
default = true;
description = ''
Create mountpoints for volumes if they do not exist.
'';
};
removeCreatedMountPoints = mkOption {
type = types.bool;
default = true;
description = ''
Remove mountpoints created by pam_mount after logout. This
only affects mountpoints that have been created by pam_mount
in the same session.
'';
};
}; };
}; };
@ -77,21 +150,20 @@ in
<!DOCTYPE pam_mount SYSTEM "pam_mount.conf.xml.dtd"> <!DOCTYPE pam_mount SYSTEM "pam_mount.conf.xml.dtd">
<!-- auto generated from Nixos: modules/config/users-groups.nix --> <!-- auto generated from Nixos: modules/config/users-groups.nix -->
<pam_mount> <pam_mount>
<debug enable="0" /> <debug enable="${toString cfg.debugLevel}" />
<!-- if activated, requires ofl from hxtools to be present --> <!-- if activated, requires ofl from hxtools to be present -->
<logout wait="0" hup="no" term="no" kill="no" /> <logout wait="${toString cfg.logoutWait}" hup="${if cfg.logoutHup then "yes" else "no"}" term="${if cfg.logoutTerm then "yes" else "no"}" kill="${if cfg.logoutKill then "yes" else "no"}" />
<!-- set PATH variable for pam_mount module --> <!-- set PATH variable for pam_mount module -->
<path>${makeBinPath ([ pkgs.util-linux ] ++ cfg.additionalSearchPaths)}</path> <path>${makeBinPath ([ pkgs.util-linux ] ++ cfg.additionalSearchPaths)}</path>
<!-- create mount point if not present --> <!-- create mount point if not present -->
<mkmountpoint enable="1" remove="true" /> <mkmountpoint enable="${if cfg.createMountPoints then "1" else "0"}" remove="${if cfg.removeCreatedMountPoints then "true" else "false"}" />
<!-- specify the binaries to be called --> <!-- specify the binaries to be called -->
<fusemount>${pkgs.fuse}/bin/mount.fuse %(VOLUME) %(MNTPT) -o ${concatStringsSep "," (cfg.fuseMountOptions ++ [ "%(OPTIONS)" ])}</fusemount> <fusemount>${pkgs.fuse}/bin/mount.fuse %(VOLUME) %(MNTPT) -o ${concatStringsSep "," (cfg.fuseMountOptions ++ [ "%(OPTIONS)" ])}</fusemount>
<fuseumount>${pkgs.fuse}/bin/fusermount -u %(MNTPT)</fuseumount>
<cryptmount>${pkgs.pam_mount}/bin/mount.crypt %(VOLUME) %(MNTPT)</cryptmount> <cryptmount>${pkgs.pam_mount}/bin/mount.crypt %(VOLUME) %(MNTPT)</cryptmount>
<cryptumount>${pkgs.pam_mount}/bin/umount.crypt %(MNTPT)</cryptumount> <cryptumount>${pkgs.pam_mount}/bin/umount.crypt %(MNTPT)</cryptumount>
<pmvarrun>${pkgs.pam_mount}/bin/pmvarrun -u %(USER) -o %(OPERATION)</pmvarrun> <pmvarrun>${pkgs.pam_mount}/bin/pmvarrun -u %(USER) -o %(OPERATION)</pmvarrun>
${optionalString oflRequired "<ofl>${fake_ofl}/bin/fake_ofl %(SIGNAL) %(MNTPT)</ofl>"}
${concatStrings (map userVolumeEntry (attrValues extraUserVolumes))} ${concatStrings (map userVolumeEntry (attrValues extraUserVolumes))}
${concatStringsSep "\n" cfg.extraVolumes} ${concatStringsSep "\n" cfg.extraVolumes}
</pam_mount> </pam_mount>

View file

@ -245,7 +245,7 @@ in
environment.systemPackages = [ sudo ]; environment.systemPackages = [ sudo ];
security.pam.services.sudo = { sshAgentAuth = true; }; security.pam.services.sudo = { sshAgentAuth = true; usshAuth = true; };
environment.etc.sudoers = environment.etc.sudoers =
{ source = { source =

View file

@ -1,4 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, utils, ... }:
with lib; with lib;
@ -6,32 +6,30 @@ let
cfg = config.services.cockroachdb; cfg = config.services.cockroachdb;
crdb = cfg.package; crdb = cfg.package;
escape = builtins.replaceStrings ["%"] ["%%"]; startupCommand = utils.escapeSystemdExecArgs
ifNotNull = v: s: optionalString (v != null) s; ([
# Basic startup
startupCommand = lib.concatStringsSep " " "${crdb}/bin/cockroach"
[ # Basic startup "start"
"${crdb}/bin/cockroach start"
"--logtostderr" "--logtostderr"
"--store=/var/lib/cockroachdb" "--store=/var/lib/cockroachdb"
(ifNotNull cfg.locality "--locality='${cfg.locality}'")
# WebUI settings # WebUI settings
"--http-addr='${cfg.http.address}:${toString cfg.http.port}'" "--http-addr=${cfg.http.address}:${toString cfg.http.port}"
# Cluster listen address # Cluster listen address
"--listen-addr='${cfg.listen.address}:${toString cfg.listen.port}'" "--listen-addr=${cfg.listen.address}:${toString cfg.listen.port}"
# Cluster configuration # Cache and memory settings.
(ifNotNull cfg.join "--join=${cfg.join}") "--cache=${cfg.cache}"
"--max-sql-memory=${cfg.maxSqlMemory}"
# Cache and memory settings. Must be escaped.
"--cache='${escape cfg.cache}'"
"--max-sql-memory='${escape cfg.maxSqlMemory}'"
# Certificate/security settings. # Certificate/security settings.
(if cfg.insecure then "--insecure" else "--certs-dir=${cfg.certsDir}") (if cfg.insecure then "--insecure" else "--certs-dir=${cfg.certsDir}")
]; ]
++ lib.optional (cfg.join != null) "--join=${cfg.join}"
++ lib.optional (cfg.locality != null) "--locality=${cfg.locality}"
++ cfg.extraArgs);
addressOption = descr: defaultPort: { addressOption = descr: defaultPort: {
address = mkOption { address = mkOption {
@ -159,6 +157,16 @@ in
only contain open source features and open source code). only contain open source features and open source code).
''; '';
}; };
extraArgs = mkOption {
type = types.listOf types.str;
default = [];
example = [ "--advertise-addr" "[fe80::f6f2:::]" ];
description = ''
Extra CLI arguments passed to <command>cockroach start</command>.
For the full list of supported argumemnts, check <link xlink:href="https://www.cockroachlabs.com/docs/stable/cockroach-start.html#flags"/>
'';
};
}; };
}; };

View file

@ -23,17 +23,16 @@ let
nixosRules = '' nixosRules = ''
# Miscellaneous devices. # Miscellaneous devices.
KERNEL=="kvm", MODE="0666" KERNEL=="kvm", MODE="0666"
KERNEL=="kqemu", MODE="0666"
# Needed for gpm. # Needed for gpm.
SUBSYSTEM=="input", KERNEL=="mice", TAG+="systemd" SUBSYSTEM=="input", KERNEL=="mice", TAG+="systemd"
''; '';
# Perform substitutions in all udev rules files. # Perform substitutions in all udev rules files.
udevRules = pkgs.runCommand "udev-rules" udevRulesFor = { name, udevPackages, udevPath, udev, systemd, binPackages, initrdBin ? null }: pkgs.runCommand name
{ preferLocalBuild = true; { preferLocalBuild = true;
allowSubstitutes = false; allowSubstitutes = false;
packages = unique (map toString cfg.packages); packages = unique (map toString udevPackages);
} }
'' ''
mkdir -p $out mkdir -p $out
@ -61,6 +60,9 @@ let
--replace \"/bin/mount \"${pkgs.util-linux}/bin/mount \ --replace \"/bin/mount \"${pkgs.util-linux}/bin/mount \
--replace /usr/bin/readlink ${pkgs.coreutils}/bin/readlink \ --replace /usr/bin/readlink ${pkgs.coreutils}/bin/readlink \
--replace /usr/bin/basename ${pkgs.coreutils}/bin/basename --replace /usr/bin/basename ${pkgs.coreutils}/bin/basename
${optionalString (initrdBin != null) ''
substituteInPlace $i --replace '/run/current-system/systemd' "${removeSuffix "/bin" initrdBin}"
''}
done done
echo -n "Checking that all programs called by relative paths in udev rules exist in ${udev}/lib/udev... " echo -n "Checking that all programs called by relative paths in udev rules exist in ${udev}/lib/udev... "
@ -85,8 +87,9 @@ let
for i in $import_progs $run_progs; do for i in $import_progs $run_progs; do
# if the path refers to /run/current-system/systemd, replace with config.systemd.package # if the path refers to /run/current-system/systemd, replace with config.systemd.package
if [[ $i == /run/current-system/systemd* ]]; then if [[ $i == /run/current-system/systemd* ]]; then
i="${config.systemd.package}/''${i#/run/current-system/systemd/}" i="${systemd}/''${i#/run/current-system/systemd/}"
fi fi
if [[ ! -x $i ]]; then if [[ ! -x $i ]]; then
echo "FAIL" echo "FAIL"
echo "$i is called in udev rules but is not executable or does not exist" echo "$i is called in udev rules but is not executable or does not exist"
@ -103,7 +106,7 @@ let
echo "Consider fixing the following udev rules:" echo "Consider fixing the following udev rules:"
echo "$filesToFixup" | while read localFile; do echo "$filesToFixup" | while read localFile; do
remoteFile="origin unknown" remoteFile="origin unknown"
for i in ${toString cfg.packages}; do for i in ${toString binPackages}; do
for j in "$i"/*/udev/rules.d/*; do for j in "$i"/*/udev/rules.d/*; do
[ -e "$out/$(basename "$j")" ] || continue [ -e "$out/$(basename "$j")" ] || continue
[ "$(basename "$j")" = "$(basename "$localFile")" ] || continue [ "$(basename "$j")" = "$(basename "$localFile")" ] || continue
@ -126,7 +129,7 @@ let
${optionalString (!config.boot.hardwareScan) '' ${optionalString (!config.boot.hardwareScan) ''
ln -s /dev/null $out/80-drivers.rules ln -s /dev/null $out/80-drivers.rules
''} ''}
''; # */ '';
hwdbBin = pkgs.runCommand "hwdb.bin" hwdbBin = pkgs.runCommand "hwdb.bin"
{ preferLocalBuild = true; { preferLocalBuild = true;
@ -202,20 +205,6 @@ in
''; '';
}; };
initrdRules = mkOption {
default = "";
example = ''
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:1D:60:B9:6D:4F", KERNEL=="eth*", NAME="my_fast_network_card"
'';
type = types.lines;
description = ''
<command>udev</command> rules to include in the initrd
<emphasis>only</emphasis>. They'll be written into file
<filename>99-local.rules</filename>. Thus they are read and applied
after the essential initrd rules.
'';
};
extraRules = mkOption { extraRules = mkOption {
default = ""; default = "";
example = '' example = ''
@ -283,6 +272,52 @@ in
''; '';
}; };
boot.initrd.services.udev = {
packages = mkOption {
type = types.listOf types.path;
default = [];
visible = false;
description = ''
<emphasis>This will only be used when systemd is used in stage 1.</emphasis>
List of packages containing <command>udev</command> rules that will be copied to stage 1.
All files found in
<filename><replaceable>pkg</replaceable>/etc/udev/rules.d</filename> and
<filename><replaceable>pkg</replaceable>/lib/udev/rules.d</filename>
will be included.
'';
};
binPackages = mkOption {
type = types.listOf types.path;
default = [];
visible = false;
description = ''
<emphasis>This will only be used when systemd is used in stage 1.</emphasis>
Packages to search for binaries that are referenced by the udev rules in stage 1.
This list always contains /bin of the initrd.
'';
apply = map getBin;
};
rules = mkOption {
default = "";
example = ''
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:1D:60:B9:6D:4F", KERNEL=="eth*", NAME="my_fast_network_card"
'';
type = types.lines;
description = ''
<command>udev</command> rules to include in the initrd
<emphasis>only</emphasis>. They'll be written into file
<filename>99-local.rules</filename>. Thus they are read and applied
after the essential initrd rules.
'';
};
};
}; };
@ -298,16 +333,54 @@ in
boot.kernelParams = mkIf (!config.networking.usePredictableInterfaceNames) [ "net.ifnames=0" ]; boot.kernelParams = mkIf (!config.networking.usePredictableInterfaceNames) [ "net.ifnames=0" ];
boot.initrd.extraUdevRulesCommands = optionalString (cfg.initrdRules != "") boot.initrd.extraUdevRulesCommands = optionalString (!config.boot.initrd.systemd.enable && config.boot.initrd.services.udev.rules != "")
'' ''
cat <<'EOF' > $out/99-local.rules cat <<'EOF' > $out/99-local.rules
${cfg.initrdRules} ${config.boot.initrd.services.udev.rules}
EOF EOF
''; '';
boot.initrd.systemd.additionalUpstreamUnits = [
# TODO: "initrd-udevadm-cleanup-db.service" is commented out because of https://github.com/systemd/systemd/issues/12953
"systemd-udevd-control.socket"
"systemd-udevd-kernel.socket"
"systemd-udevd.service"
"systemd-udev-settle.service"
"systemd-udev-trigger.service"
];
boot.initrd.systemd.storePaths = [
"${config.boot.initrd.systemd.package}/lib/systemd/systemd-udevd"
"${config.boot.initrd.systemd.package}/lib/udev"
] ++ map (x: "${x}/bin") config.boot.initrd.services.udev.binPackages;
# Generate the udev rules for the initrd
boot.initrd.systemd.contents = {
"/etc/udev/rules.d".source = udevRulesFor {
name = "initrd-udev-rules";
initrdBin = config.boot.initrd.systemd.contents."/bin".source;
udevPackages = config.boot.initrd.services.udev.packages;
udevPath = config.boot.initrd.systemd.contents."/bin".source;
udev = config.boot.initrd.systemd.package;
systemd = config.boot.initrd.systemd.package;
binPackages = config.boot.initrd.services.udev.binPackages ++ [ config.boot.initrd.systemd.contents."/bin".source ];
};
};
# Insert custom rules
boot.initrd.services.udev.packages = mkIf (config.boot.initrd.services.udev.rules != "") (pkgs.writeTextFile {
name = "initrd-udev-rules";
destination = "/etc/udev/rules.d/99-local.rules";
text = config.boot.initrd.services.udev.rules;
});
environment.etc = environment.etc =
{ {
"udev/rules.d".source = udevRules; "udev/rules.d".source = udevRulesFor {
name = "udev-rules";
udevPackages = cfg.packages;
systemd = config.systemd.package;
binPackages = cfg.packages;
inherit udevPath udev;
};
"udev/hwdb.bin".source = hwdbBin; "udev/hwdb.bin".source = hwdbBin;
}; };
@ -338,4 +411,8 @@ in
}; };
}; };
imports = [
(mkRenamedOptionModule [ "services" "udev" "initrdRules" ] [ "boot" "initrd" "services" "udev" "rules" ])
];
} }

View file

@ -4,6 +4,13 @@
with lib; with lib;
let
settingsFormat = pkgs.formats.ini {
listToValue = concatMapStringsSep "," (generators.mkValueStringDefault {});
};
configFiles = mapAttrs (name: value: (settingsFormat.generate name value)) (mapAttrs' (name: value: nameValuePair name value ) config.services.udisks2.settings);
in
{ {
###### interface ###### interface
@ -21,6 +28,36 @@ with lib;
''; '';
}; };
settings = mkOption rec {
type = types.attrsOf settingsFormat.type;
apply = recursiveUpdate default;
default = {
"udisks2.conf" = {
udisks2 = {
modules = [ "*" ];
modules_load_preference = "ondemand";
};
defaults = {
encryption = "luks2";
};
};
};
example = literalExpression ''
{
"WDC-WD10EZEX-60M2NA0-WD-WCC3F3SJ0698.conf" = {
ATA = {
StandbyTimeout = 50;
};
};
};
'';
description = ''
Options passed to udisksd.
See <link xlink:href="http://manpages.ubuntu.com/manpages/latest/en/man5/udisks2.conf.5.html">here</link> and
drive configuration in <link xlink:href="http://manpages.ubuntu.com/manpages/latest/en/man8/udisks.8.html">here</link> for supported options.
'';
};
}; };
}; };
@ -32,6 +69,8 @@ with lib;
environment.systemPackages = [ pkgs.udisks2 ]; environment.systemPackages = [ pkgs.udisks2 ];
environment.etc = mapAttrs' (name: value: nameValuePair "udisks2/${name}" { source = value; } ) configFiles;
security.polkit.enable = true; security.polkit.enable = true;
services.dbus.packages = [ pkgs.udisks2 ]; services.dbus.packages = [ pkgs.udisks2 ];

View file

@ -1,38 +1,9 @@
{ config, lib, pkgs, ... }: { lib, ... }:
with lib;
{ {
###### interface imports = [
(lib.mkRemovedOptionModule [ "security" "klogd" "enable" ] ''
options = { Logging of kernel messages is now handled by systemd.
'')
services.klogd.enable = mkOption { ];
type = types.bool;
default = versionOlder (getVersion config.boot.kernelPackages.kernel) "3.5";
defaultText = literalExpression ''versionOlder (getVersion config.boot.kernelPackages.kernel) "3.5"'';
description = ''
Whether to enable klogd, the kernel log message processing
daemon. Since systemd handles logging of kernel messages on
Linux 3.5 and later, this is only useful if you're running an
older kernel.
'';
};
};
###### implementation
config = mkIf config.services.klogd.enable {
systemd.services.klogd = {
description = "Kernel Log Daemon";
wantedBy = [ "multi-user.target" ];
path = [ pkgs.sysklogd ];
unitConfig.ConditionVirtualization = "!systemd-nspawn";
script =
"klogd -c 1 -2 -n " +
"-k $(dirname $(readlink -f /run/booted-system/kernel))/System.map";
};
};
} }

View file

@ -192,7 +192,6 @@ in {
log_dir = "/var/log/mailman"; log_dir = "/var/log/mailman";
lock_dir = "$var_dir/lock"; lock_dir = "$var_dir/lock";
etc_dir = "/etc"; etc_dir = "/etc";
ext_dir = "$etc_dir/mailman.d";
pid_file = "/run/mailman/master.pid"; pid_file = "/run/mailman/master.pid";
}; };
@ -225,7 +224,14 @@ in {
See <https://mailman.readthedocs.io/en/latest/src/mailman/docs/mta.html>. See <https://mailman.readthedocs.io/en/latest/src/mailman/docs/mta.html>.
''; '';
}; };
in (lib.optionals cfg.enablePostfix [ in [
{ assertion = cfg.webHosts != [];
message = ''
services.mailman.serve.enable requires there to be at least one entry
in services.mailman.webHosts.
'';
}
] ++ (lib.optionals cfg.enablePostfix [
{ assertion = postfix.enable; { assertion = postfix.enable;
message = '' message = ''
Mailman's default NixOS configuration requires Postfix to be enabled. Mailman's default NixOS configuration requires Postfix to be enabled.
@ -275,15 +281,14 @@ in {
globals().update(json.load(f)) globals().update(json.load(f))
''; '';
services.nginx = mkIf cfg.serve.enable { services.nginx = mkIf (cfg.serve.enable && cfg.webHosts != []) {
enable = mkDefault true; enable = mkDefault true;
virtualHosts."${lib.head cfg.webHosts}" = { virtualHosts = lib.genAttrs cfg.webHosts (webHost: {
serverAliases = cfg.webHosts;
locations = { locations = {
"/".extraConfig = "uwsgi_pass unix:/run/mailman-web.socket;"; "/".extraConfig = "uwsgi_pass unix:/run/mailman-web.socket;";
"/static/".alias = webSettings.STATIC_ROOT + "/"; "/static/".alias = webSettings.STATIC_ROOT + "/";
}; };
}; });
}; };
environment.systemPackages = [ (pkgs.buildEnv { environment.systemPackages = [ (pkgs.buildEnv {

View file

@ -22,7 +22,7 @@ in
}; };
recheckInterval = mkOption { recheckInterval = mkOption {
type = types.int; type = types.ints.unsigned;
default = 2000; default = 2000;
description = "Interval in milliseconds between farm rechecks."; description = "Interval in milliseconds between farm rechecks.";
}; };
@ -70,7 +70,7 @@ in
}; };
maxPower = mkOption { maxPower = mkOption {
type = types.int; type = types.ints.unsigned;
default = 113; default = 113;
description = "Miner max watt usage."; description = "Miner max watt usage.";
}; };
@ -85,7 +85,7 @@ in
config = mkIf cfg.enable { config = mkIf cfg.enable {
systemd.services.ethminer = { systemd.services.ethminer = {
path = [ pkgs.cudatoolkit ]; path = optional (cfg.toolkit == "cuda") [ pkgs.cudaPackages.cudatoolkit ];
description = "ethminer ethereum mining service"; description = "ethminer ethereum mining service";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
after = [ "network.target" ]; after = [ "network.target" ];
@ -97,7 +97,7 @@ in
Restart = "always"; Restart = "always";
}; };
environment = { environment = mkIf (cfg.toolkit == "cuda") {
LD_LIBRARY_PATH = "${config.boot.kernelPackages.nvidia_x11}/lib"; LD_LIBRARY_PATH = "${config.boot.kernelPackages.nvidia_x11}/lib";
}; };

View file

@ -10,7 +10,7 @@ let
toYesNo = b: if b then "yes" else "no"; toYesNo = b: if b then "yes" else "no";
gititShared = with cfg.haskellPackages; gitit + "/share/" + pkgs.stdenv.hostPlatform.system + "-" + ghc.name + "/" + gitit.pname + "-" + gitit.version; gititShared = with cfg.haskellPackages; gitit + "/share/" + ghc.targetPrefix + ghc.haskellCompilerName + "/" + gitit.pname + "-" + gitit.version;
gititWithPkgs = hsPkgs: extras: hsPkgs.ghcWithPackages (self: with self; [ gitit ] ++ (extras self)); gititWithPkgs = hsPkgs: extras: hsPkgs.ghcWithPackages (self: with self; [ gitit ] ++ (extras self));

View file

@ -708,6 +708,14 @@ in
systemd.packages = [ nixPackage ]; systemd.packages = [ nixPackage ];
# Will only work once https://github.com/NixOS/nix/pull/6285 is merged
# systemd.tmpfiles.packages = [ nixPackage ];
# Can be dropped for Nix > https://github.com/NixOS/nix/pull/6285
systemd.tmpfiles.rules = [
"d /nix/var/nix/daemon-socket 0755 root root - -"
];
systemd.sockets.nix-daemon.wantedBy = [ "sockets.target" ]; systemd.sockets.nix-daemon.wantedBy = [ "sockets.target" ];
systemd.services.nix-daemon = systemd.services.nix-daemon =

View file

@ -2,11 +2,13 @@
with lib; with lib;
let let
cfg = config.services.paperless-ng; cfg = config.services.paperless;
defaultUser = "paperless"; defaultUser = "paperless";
hasCustomRedis = hasAttr "PAPERLESS_REDIS" cfg.extraConfig; # Don't start a redis instance if the user sets a custom redis connection
enableRedis = !hasAttr "PAPERLESS_REDIS" cfg.extraConfig;
redisServer = config.services.redis.servers.paperless;
env = { env = {
PAPERLESS_DATA_DIR = cfg.dataDir; PAPERLESS_DATA_DIR = cfg.dataDir;
@ -15,15 +17,15 @@ let
GUNICORN_CMD_ARGS = "--bind=${cfg.address}:${toString cfg.port}"; GUNICORN_CMD_ARGS = "--bind=${cfg.address}:${toString cfg.port}";
} // ( } // (
lib.mapAttrs (_: toString) cfg.extraConfig lib.mapAttrs (_: toString) cfg.extraConfig
) // (optionalAttrs (!hasCustomRedis) { ) // (optionalAttrs enableRedis {
PAPERLESS_REDIS = "unix://${config.services.redis.servers.paperless-ng.unixSocket}"; PAPERLESS_REDIS = "unix://${redisServer.unixSocket}";
}); });
manage = let manage = let
setupEnv = lib.concatStringsSep "\n" (mapAttrsToList (name: val: "export ${name}=\"${val}\"") env); setupEnv = lib.concatStringsSep "\n" (mapAttrsToList (name: val: "export ${name}=\"${val}\"") env);
in pkgs.writeShellScript "manage" '' in pkgs.writeShellScript "manage" ''
${setupEnv} ${setupEnv}
exec ${cfg.package}/bin/paperless-ng "$@" exec ${cfg.package}/bin/paperless-ngx "$@"
''; '';
# Secure the services # Secure the services
@ -36,7 +38,7 @@ let
"-/etc/hosts" "-/etc/hosts"
"-/etc/localtime" "-/etc/localtime"
"-/run/postgresql" "-/run/postgresql"
] ++ (optional (!hasCustomRedis) config.services.redis.servers.paperless-ng.unixSocket); ] ++ (optional enableRedis redisServer.unixSocket);
BindPaths = [ BindPaths = [
cfg.consumptionDir cfg.consumptionDir
cfg.dataDir cfg.dataDir
@ -65,11 +67,15 @@ let
ProtectKernelModules = true; ProtectKernelModules = true;
ProtectKernelTunables = true; ProtectKernelTunables = true;
ProtectProc = "invisible"; ProtectProc = "invisible";
# Don't restrict ProcSubset because django-q requires read access to /proc/stat
# to query CPU and memory information.
# Note that /proc only contains processes of user `paperless`, so this is safe.
# ProcSubset = "pid";
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ]; RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
RestrictNamespaces = true; RestrictNamespaces = true;
RestrictRealtime = true; RestrictRealtime = true;
RestrictSUIDSGID = true; RestrictSUIDSGID = true;
SupplementaryGroups = optional (!hasCustomRedis) config.services.redis.servers.paperless-ng.user; SupplementaryGroups = optional enableRedis redisServer.user;
SystemCallArchitectures = "native"; SystemCallArchitectures = "native";
SystemCallFilter = [ "@system-service" "~@privileged @resources @setuid @keyring" ]; SystemCallFilter = [ "@system-service" "~@privileged @resources @setuid @keyring" ];
# Does not work well with the temporary root # Does not work well with the temporary root
@ -80,26 +86,22 @@ in
meta.maintainers = with maintainers; [ earvstedt Flakebi ]; meta.maintainers = with maintainers; [ earvstedt Flakebi ];
imports = [ imports = [
(mkRemovedOptionModule [ "services" "paperless"] '' (mkRenamedOptionModule [ "services" "paperless-ng" ] [ "services" "paperless" ])
The paperless module has been removed as the upstream project died.
Users should migrate to the paperless-ng module (services.paperless-ng).
More information can be found in the NixOS 21.11 release notes.
'')
]; ];
options.services.paperless-ng = { options.services.paperless = {
enable = mkOption { enable = mkOption {
type = lib.types.bool; type = lib.types.bool;
default = false; default = false;
description = '' description = ''
Enable Paperless-ng. Enable Paperless.
When started, the Paperless database is automatically created if it doesn't When started, the Paperless database is automatically created if it doesn't
exist and updated if the Paperless package has changed. exist and updated if the Paperless package has changed.
Both tasks are achieved by running a Django migration. Both tasks are achieved by running a Django migration.
A script to manage the Paperless instance (by wrapping Django's manage.py) is linked to A script to manage the Paperless instance (by wrapping Django's manage.py) is linked to
<literal>''${dataDir}/paperless-ng-manage</literal>. <literal>''${dataDir}/paperless-manage</literal>.
''; '';
}; };
@ -132,13 +134,13 @@ in
passwordFile = mkOption { passwordFile = mkOption {
type = types.nullOr types.path; type = types.nullOr types.path;
default = null; default = null;
example = "/run/keys/paperless-ng-password"; example = "/run/keys/paperless-password";
description = '' description = ''
A file containing the superuser password. A file containing the superuser password.
A superuser is required to access the web interface. A superuser is required to access the web interface.
If unset, you can create a superuser manually by running If unset, you can create a superuser manually by running
<literal>''${dataDir}/paperless-ng-manage createsuperuser</literal>. <literal>''${dataDir}/paperless-manage createsuperuser</literal>.
The default superuser name is <literal>admin</literal>. To change it, set The default superuser name is <literal>admin</literal>. To change it, set
option <option>extraConfig.PAPERLESS_ADMIN_USER</option>. option <option>extraConfig.PAPERLESS_ADMIN_USER</option>.
@ -167,9 +169,9 @@ in
type = types.attrs; type = types.attrs;
default = {}; default = {};
description = '' description = ''
Extra paperless-ng config options. Extra paperless config options.
See <link xlink:href="https://paperless-ng.readthedocs.io/en/latest/configuration.html">the documentation</link> See <link xlink:href="https://paperless-ngx.readthedocs.io/en/latest/configuration.html">the documentation</link>
for available options. for available options.
''; '';
example = literalExpression '' example = literalExpression ''
@ -187,15 +189,14 @@ in
package = mkOption { package = mkOption {
type = types.package; type = types.package;
default = pkgs.paperless-ng; default = pkgs.paperless-ngx;
defaultText = literalExpression "pkgs.paperless-ng"; defaultText = literalExpression "pkgs.paperless-ngx";
description = "The Paperless package to use."; description = "The Paperless package to use.";
}; };
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
# Enable redis if no special url is set services.redis.servers.paperless.enable = mkIf enableRedis true;
services.redis.servers.paperless-ng.enable = mkIf (!hasCustomRedis) true;
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules = [
"d '${cfg.dataDir}' - ${cfg.user} ${config.users.users.${cfg.user}.group} - -" "d '${cfg.dataDir}' - ${cfg.user} ${config.users.users.${cfg.user}.group} - -"
@ -207,11 +208,11 @@ in
) )
]; ];
systemd.services.paperless-ng-server = { systemd.services.paperless-scheduler = {
description = "Paperless document server"; description = "Paperless scheduler";
serviceConfig = defaultServiceConfig // { serviceConfig = defaultServiceConfig // {
User = cfg.user; User = cfg.user;
ExecStart = "${cfg.package}/bin/paperless-ng qcluster"; ExecStart = "${cfg.package}/bin/paperless-ngx qcluster";
Restart = "on-failure"; Restart = "on-failure";
# The `mbind` syscall is needed for running the classifier. # The `mbind` syscall is needed for running the classifier.
SystemCallFilter = defaultServiceConfig.SystemCallFilter ++ [ "mbind" ]; SystemCallFilter = defaultServiceConfig.SystemCallFilter ++ [ "mbind" ];
@ -220,15 +221,15 @@ in
}; };
environment = env; environment = env;
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
wants = [ "paperless-ng-consumer.service" "paperless-ng-web.service" ]; wants = [ "paperless-consumer.service" "paperless-web.service" ];
preStart = '' preStart = ''
ln -sf ${manage} ${cfg.dataDir}/paperless-ng-manage ln -sf ${manage} ${cfg.dataDir}/paperless-manage
# Auto-migrate on first run or if the package has changed # Auto-migrate on first run or if the package has changed
versionFile="${cfg.dataDir}/src-version" versionFile="${cfg.dataDir}/src-version"
if [[ $(cat "$versionFile" 2>/dev/null) != ${cfg.package} ]]; then if [[ $(cat "$versionFile" 2>/dev/null) != ${cfg.package} ]]; then
${cfg.package}/bin/paperless-ng migrate ${cfg.package}/bin/paperless-ngx migrate
echo ${cfg.package} > "$versionFile" echo ${cfg.package} > "$versionFile"
fi fi
'' ''
@ -239,20 +240,18 @@ in
superuserStateFile="${cfg.dataDir}/superuser-state" superuserStateFile="${cfg.dataDir}/superuser-state"
if [[ $(cat "$superuserStateFile" 2>/dev/null) != $superuserState ]]; then if [[ $(cat "$superuserStateFile" 2>/dev/null) != $superuserState ]]; then
${cfg.package}/bin/paperless-ng manage_superuser ${cfg.package}/bin/paperless-ngx manage_superuser
echo "$superuserState" > "$superuserStateFile" echo "$superuserState" > "$superuserStateFile"
fi fi
''; '';
} // optionalAttrs (!hasCustomRedis) { } // optionalAttrs enableRedis {
after = [ "redis-paperless-ng.service" ]; after = [ "redis-paperless.service" ];
}; };
# Password copying can't be implemented as a privileged preStart script # Reading the user-provided password file requires root access
# in 'paperless-ng-server' because 'defaultServiceConfig' limits the filesystem systemd.services.paperless-copy-password = mkIf (cfg.passwordFile != null) {
# paths accessible by the service. requiredBy = [ "paperless-scheduler.service" ];
systemd.services.paperless-ng-copy-password = mkIf (cfg.passwordFile != null) { before = [ "paperless-scheduler.service" ];
requiredBy = [ "paperless-ng-server.service" ];
before = [ "paperless-ng-server.service" ];
serviceConfig = { serviceConfig = {
ExecStart = '' ExecStart = ''
${pkgs.coreutils}/bin/install --mode 600 --owner '${cfg.user}' --compare \ ${pkgs.coreutils}/bin/install --mode 600 --owner '${cfg.user}' --compare \
@ -262,27 +261,27 @@ in
}; };
}; };
systemd.services.paperless-ng-consumer = { systemd.services.paperless-consumer = {
description = "Paperless document consumer"; description = "Paperless document consumer";
serviceConfig = defaultServiceConfig // { serviceConfig = defaultServiceConfig // {
User = cfg.user; User = cfg.user;
ExecStart = "${cfg.package}/bin/paperless-ng document_consumer"; ExecStart = "${cfg.package}/bin/paperless-ngx document_consumer";
Restart = "on-failure"; Restart = "on-failure";
}; };
environment = env; environment = env;
# Bind to `paperless-ng-server` so that the consumer never runs # Bind to `paperless-scheduler` so that the consumer never runs
# during migrations # during migrations
bindsTo = [ "paperless-ng-server.service" ]; bindsTo = [ "paperless-scheduler.service" ];
after = [ "paperless-ng-server.service" ]; after = [ "paperless-scheduler.service" ];
}; };
systemd.services.paperless-ng-web = { systemd.services.paperless-web = {
description = "Paperless web server"; description = "Paperless web server";
serviceConfig = defaultServiceConfig // { serviceConfig = defaultServiceConfig // {
User = cfg.user; User = cfg.user;
ExecStart = '' ExecStart = ''
${pkgs.python3Packages.gunicorn}/bin/gunicorn \ ${pkgs.python3Packages.gunicorn}/bin/gunicorn \
-c ${cfg.package}/lib/paperless-ng/gunicorn.conf.py paperless.asgi:application -c ${cfg.package}/lib/paperless-ngx/gunicorn.conf.py paperless.asgi:application
''; '';
Restart = "on-failure"; Restart = "on-failure";
@ -295,15 +294,15 @@ in
}; };
environment = env // { environment = env // {
PATH = mkForce cfg.package.path; PATH = mkForce cfg.package.path;
PYTHONPATH = "${cfg.package.pythonPath}:${cfg.package}/lib/paperless-ng/src"; PYTHONPATH = "${cfg.package.pythonPath}:${cfg.package}/lib/paperless-ngx/src";
}; };
# Allow the web interface to access the private /tmp directory of the server. # Allow the web interface to access the private /tmp directory of the server.
# This is required to support uploading files via the web interface. # This is required to support uploading files via the web interface.
unitConfig.JoinsNamespaceOf = "paperless-ng-server.service"; unitConfig.JoinsNamespaceOf = "paperless-scheduler.service";
# Bind to `paperless-ng-server` so that the web server never runs # Bind to `paperless-scheduler` so that the web server never runs
# during migrations # during migrations
bindsTo = [ "paperless-ng-server.service" ]; bindsTo = [ "paperless-scheduler.service" ];
after = [ "paperless-ng-server.service" ]; after = [ "paperless-scheduler.service" ];
}; };
users = optionalAttrs (cfg.user == defaultUser) { users = optionalAttrs (cfg.user == defaultUser) {

View file

@ -74,7 +74,6 @@ let
}" }"
"--web.listen-address=${cfg.listenAddress}:${builtins.toString cfg.port}" "--web.listen-address=${cfg.listenAddress}:${builtins.toString cfg.port}"
"--alertmanager.notification-queue-capacity=${toString cfg.alertmanagerNotificationQueueCapacity}" "--alertmanager.notification-queue-capacity=${toString cfg.alertmanagerNotificationQueueCapacity}"
"--alertmanager.timeout=${toString cfg.alertmanagerTimeout}s"
] ++ optional (cfg.webExternalUrl != null) "--web.external-url=${cfg.webExternalUrl}" ] ++ optional (cfg.webExternalUrl != null) "--web.external-url=${cfg.webExternalUrl}"
++ optional (cfg.retentionTime != null) "--storage.tsdb.retention.time=${cfg.retentionTime}"; ++ optional (cfg.retentionTime != null) "--storage.tsdb.retention.time=${cfg.retentionTime}";
@ -1563,6 +1562,8 @@ in
(mkRenamedOptionModule [ "services" "prometheus2" ] [ "services" "prometheus" ]) (mkRenamedOptionModule [ "services" "prometheus2" ] [ "services" "prometheus" ])
(mkRemovedOptionModule [ "services" "prometheus" "environmentFile" ] (mkRemovedOptionModule [ "services" "prometheus" "environmentFile" ]
"It has been removed since it was causing issues (https://github.com/NixOS/nixpkgs/issues/126083) and Prometheus now has native support for secret files, i.e. `basic_auth.password_file` and `authorization.credentials_file`.") "It has been removed since it was causing issues (https://github.com/NixOS/nixpkgs/issues/126083) and Prometheus now has native support for secret files, i.e. `basic_auth.password_file` and `authorization.credentials_file`.")
(mkRemovedOptionModule [ "services" "prometheus" "alertmanagerTimeout" ]
"Deprecated upstream and no longer had any effect")
]; ];
options.services.prometheus = { options.services.prometheus = {
@ -1719,14 +1720,6 @@ in
''; '';
}; };
alertmanagerTimeout = mkOption {
type = types.int;
default = 10;
description = ''
Alert manager HTTP API timeout (in seconds).
'';
};
webExternalUrl = mkOption { webExternalUrl = mkOption {
type = types.nullOr types.str; type = types.nullOr types.str;
default = null; default = null;

View file

@ -267,11 +267,15 @@ in
'' + '' '' + ''
ipfs --offline config show \ ipfs --offline config show \
| ${pkgs.jq}/bin/jq '. * $extraConfig' --argjson extraConfig ${ | ${pkgs.jq}/bin/jq '. * $extraConfig' --argjson extraConfig ${
escapeShellArg (builtins.toJSON ({ escapeShellArg (builtins.toJSON (
recursiveUpdate
{
Addresses.API = cfg.apiAddress; Addresses.API = cfg.apiAddress;
Addresses.Gateway = cfg.gatewayAddress; Addresses.Gateway = cfg.gatewayAddress;
Addresses.Swarm = cfg.swarmAddress; Addresses.Swarm = cfg.swarmAddress;
} // cfg.extraConfig)) }
cfg.extraConfig
))
} \ } \
| ipfs --offline config replace - | ipfs --offline config replace -
''; '';

View file

@ -0,0 +1,84 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.envoy;
format = pkgs.formats.json { };
conf = format.generate "envoy.json" cfg.settings;
validateConfig = file:
pkgs.runCommand "validate-envoy-conf" { } ''
${pkgs.envoy}/bin/envoy --log-level error --mode validate -c "${file}"
cp "${file}" "$out"
'';
in
{
options.services.envoy = {
enable = mkEnableOption "Envoy reverse proxy";
settings = mkOption {
type = format.type;
default = { };
example = literalExpression ''
{
admin = {
access_log_path = "/dev/null";
address = {
socket_address = {
protocol = "TCP";
address = "127.0.0.1";
port_value = 9901;
};
};
};
static_resources = {
listeners = [];
clusters = [];
};
}
'';
description = ''
Specify the configuration for Envoy in Nix.
'';
};
};
config = mkIf cfg.enable {
environment.systemPackages = [ pkgs.envoy ];
systemd.services.envoy = {
description = "Envoy reverse proxy";
after = [ "network-online.target" ];
requires = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${pkgs.envoy}/bin/envoy -c ${validateConfig conf}";
DynamicUser = true;
Restart = "no";
CacheDirectory = "envoy";
LogsDirectory = "envoy";
AmbientCapabilities = "CAP_NET_BIND_SERVICE";
CapabilityBoundingSet = "CAP_NET_BIND_SERVICE";
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK AF_XDP";
SystemCallArchitectures = "native";
LockPersonality = true;
RestrictNamespaces = true;
RestrictRealtime = true;
PrivateUsers = false; # breaks CAP_NET_BIND_SERVICE
PrivateDevices = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "ptraceable";
ProtectHostname = true;
ProtectSystem = "strict";
UMask = "0066";
SystemCallFilter = "~@clock @module @mount @reboot @swap @obsolete @cpu-emulation";
};
};
};
}

View file

@ -0,0 +1,19 @@
{ config, lib, pkgs, ... }:
{
options.services.mozillavpn.enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Enable the Mozilla VPN daemon.
'';
};
config = lib.mkIf config.services.mozillavpn.enable {
environment.systemPackages = [ pkgs.mozillavpn ];
services.dbus.packages = [ pkgs.mozillavpn ];
systemd.packages = [ pkgs.mozillavpn ];
};
meta.maintainers = with lib.maintainers; [ andersk ];
}

View file

@ -5,18 +5,6 @@ with lib;
let let
cfg = config.networking.networkmanager; cfg = config.networking.networkmanager;
basePackages = with pkgs; [
modemmanager
networkmanager
networkmanager-fortisslvpn
networkmanager-iodine
networkmanager-l2tp
networkmanager-openconnect
networkmanager-openvpn
networkmanager-vpnc
networkmanager-sstp
] ++ optional (!delegateWireless && !enableIwd) wpa_supplicant;
delegateWireless = config.networking.wireless.enable == true && cfg.unmanaged != []; delegateWireless = config.networking.wireless.enable == true && cfg.unmanaged != [];
enableIwd = cfg.wifi.backend == "iwd"; enableIwd = cfg.wifi.backend == "iwd";
@ -145,6 +133,15 @@ let
''; '';
}; };
packages = [
pkgs.modemmanager
pkgs.networkmanager
]
++ cfg.plugins
++ lib.optionals (!delegateWireless && !enableIwd) [
pkgs.wpa_supplicant
];
in { in {
meta = { meta = {
@ -227,17 +224,33 @@ in {
''; '';
}; };
packages = mkOption { plugins = mkOption {
type = types.listOf types.package; type =
let
networkManagerPluginPackage = types.package // {
description = "NetworkManager plug-in";
check =
p:
lib.assertMsg
(types.package.check p
&& p ? networkManagerPlugin
&& lib.isString p.networkManagerPlugin)
''
Package ${p.name}, is not a NetworkManager plug-in.
Those need to have a networkManagerPlugin attribute.
'';
};
in
types.listOf networkManagerPluginPackage;
default = [ ]; default = [ ];
description = '' description = ''
Extra packages that provide NetworkManager plugins. List of NetworkManager plug-ins to enable.
Some plug-ins are enabled by the NetworkManager module by default.
''; '';
apply = list: basePackages ++ list;
}; };
dhcp = mkOption { dhcp = mkOption {
type = types.enum [ "dhclient" "dhcpcd" "internal" ]; type = types.enum [ "dhcpcd" "internal" ];
default = "internal"; default = "internal";
description = '' description = ''
Which program (or internal library) should be used for DHCP. Which program (or internal library) should be used for DHCP.
@ -380,7 +393,7 @@ in {
</para><para> </para><para>
If you enable this option the If you enable this option the
<literal>networkmanager_strongswan</literal> plugin will be added to <literal>networkmanager_strongswan</literal> plugin will be added to
the <option>networking.networkmanager.packages</option> option the <option>networking.networkmanager.plugins</option> option
so you don't need to to that yourself. so you don't need to to that yourself.
''; '';
}; };
@ -399,6 +412,9 @@ in {
}; };
imports = [ imports = [
(mkRenamedOptionModule
[ "networking" "networkmanager" "packages" ]
[ "networking" "networkmanager" "plugins" ])
(mkRenamedOptionModule [ "networking" "networkmanager" "useDnsmasq" ] [ "networking" "networkmanager" "dns" ]) (mkRenamedOptionModule [ "networking" "networkmanager" "useDnsmasq" ] [ "networking" "networkmanager" "dns" ])
(mkRemovedOptionModule ["networking" "networkmanager" "dynamicHosts"] '' (mkRemovedOptionModule ["networking" "networkmanager" "dynamicHosts"] ''
This option was removed because allowing (multiple) regular users to This option was removed because allowing (multiple) regular users to
@ -426,31 +442,12 @@ in {
hardware.wirelessRegulatoryDatabase = true; hardware.wirelessRegulatoryDatabase = true;
environment.etc = with pkgs; { environment.etc = {
"NetworkManager/NetworkManager.conf".source = configFile; "NetworkManager/NetworkManager.conf".source = configFile;
"NetworkManager/VPN/nm-openvpn-service.name".source =
"${networkmanager-openvpn}/lib/NetworkManager/VPN/nm-openvpn-service.name";
"NetworkManager/VPN/nm-vpnc-service.name".source =
"${networkmanager-vpnc}/lib/NetworkManager/VPN/nm-vpnc-service.name";
"NetworkManager/VPN/nm-openconnect-service.name".source =
"${networkmanager-openconnect}/lib/NetworkManager/VPN/nm-openconnect-service.name";
"NetworkManager/VPN/nm-fortisslvpn-service.name".source =
"${networkmanager-fortisslvpn}/lib/NetworkManager/VPN/nm-fortisslvpn-service.name";
"NetworkManager/VPN/nm-l2tp-service.name".source =
"${networkmanager-l2tp}/lib/NetworkManager/VPN/nm-l2tp-service.name";
"NetworkManager/VPN/nm-iodine-service.name".source =
"${networkmanager-iodine}/lib/NetworkManager/VPN/nm-iodine-service.name";
"NetworkManager/VPN/nm-sstp-service.name".source =
"${networkmanager-sstp}/lib/NetworkManager/VPN/nm-sstp-service.name";
} }
// builtins.listToAttrs (map (pkg: nameValuePair "NetworkManager/${pkg.networkManagerPlugin}" {
source = "${pkg}/lib/NetworkManager/${pkg.networkManagerPlugin}";
}) cfg.plugins)
// optionalAttrs cfg.enableFccUnlock // optionalAttrs cfg.enableFccUnlock
{ {
"ModemManager/fcc-unlock.d".source = "ModemManager/fcc-unlock.d".source =
@ -460,18 +457,13 @@ in {
{ {
"NetworkManager/dispatcher.d/02overridedns".source = overrideNameserversScript; "NetworkManager/dispatcher.d/02overridedns".source = overrideNameserversScript;
} }
// optionalAttrs cfg.enableStrongSwan
{
"NetworkManager/VPN/nm-strongswan-service.name".source =
"${pkgs.networkmanager_strongswan}/lib/NetworkManager/VPN/nm-strongswan-service.name";
}
// listToAttrs (lib.imap1 (i: s: // listToAttrs (lib.imap1 (i: s:
{ {
name = "NetworkManager/dispatcher.d/${dispatcherTypesSubdirMap.${s.type}}03userscript${lib.fixedWidthNumber 4 i}"; name = "NetworkManager/dispatcher.d/${dispatcherTypesSubdirMap.${s.type}}03userscript${lib.fixedWidthNumber 4 i}";
value = { mode = "0544"; inherit (s) source; }; value = { mode = "0544"; inherit (s) source; };
}) cfg.dispatcherScripts); }) cfg.dispatcherScripts);
environment.systemPackages = cfg.packages; environment.systemPackages = packages;
users.groups = { users.groups = {
networkmanager.gid = config.ids.gids.networkmanager; networkmanager.gid = config.ids.gids.networkmanager;
@ -490,14 +482,13 @@ in {
}; };
}; };
systemd.packages = cfg.packages; systemd.packages = packages;
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules = [
"d /etc/NetworkManager/system-connections 0700 root root -" "d /etc/NetworkManager/system-connections 0700 root root -"
"d /etc/ipsec.d 0700 root root -" "d /etc/ipsec.d 0700 root root -"
"d /var/lib/NetworkManager-fortisslvpn 0700 root root -" "d /var/lib/NetworkManager-fortisslvpn 0700 root root -"
"d /var/lib/dhclient 0755 root root -"
"d /var/lib/misc 0755 root root -" # for dnsmasq.leases "d /var/lib/misc 0755 root root -" # for dnsmasq.leases
]; ];
@ -534,8 +525,20 @@ in {
useDHCP = false; useDHCP = false;
}) })
{
networkmanager.plugins = with pkgs; [
networkmanager-fortisslvpn
networkmanager-iodine
networkmanager-l2tp
networkmanager-openconnect
networkmanager-openvpn
networkmanager-vpnc
networkmanager-sstp
];
}
(mkIf cfg.enableStrongSwan { (mkIf cfg.enableStrongSwan {
networkmanager.packages = [ pkgs.networkmanager_strongswan ]; networkmanager.plugins = [ pkgs.networkmanager_strongswan ];
}) })
(mkIf enableIwd { (mkIf enableIwd {
@ -559,10 +562,10 @@ in {
security.polkit.enable = true; security.polkit.enable = true;
security.polkit.extraConfig = polkitConf; security.polkit.extraConfig = polkitConf;
services.dbus.packages = cfg.packages services.dbus.packages = packages
++ optional cfg.enableStrongSwan pkgs.strongswanNM ++ optional cfg.enableStrongSwan pkgs.strongswanNM
++ optional (cfg.dns == "dnsmasq") pkgs.dnsmasq; ++ optional (cfg.dns == "dnsmasq") pkgs.dnsmasq;
services.udev.packages = cfg.packages; services.udev.packages = packages;
}; };
} }

View file

@ -0,0 +1,137 @@
{ config, lib, options, pkgs, ... }:
with lib;
let
cfg = config.networking.openconnect;
openconnect = cfg.package;
pkcs11 = types.strMatching "pkcs11:.+" // {
name = "pkcs11";
description = "PKCS#11 URI";
};
interfaceOptions = {
options = {
gateway = mkOption {
description = "Gateway server to connect to.";
example = "gateway.example.com";
type = types.str;
};
protocol = mkOption {
description = "Protocol to use.";
example = "anyconnect";
type =
types.enum [ "anyconnect" "array" "nc" "pulse" "gp" "f5" "fortinet" ];
};
user = mkOption {
description = "Username to authenticate with.";
example = "example-user";
type = types.nullOr types.str;
};
# Note: It does not make sense to provide a way to declaratively
# set an authentication cookie, because they have to be requested
# for every new connection and would only work once.
passwordFile = mkOption {
description = ''
File containing the password to authenticate with. This
is passed to <code>openconnect</code> via the
<code>--passwd-on-stdin</code> option.
'';
default = null;
example = "/var/lib/secrets/openconnect-passwd";
type = types.nullOr types.path;
};
certificate = mkOption {
description = "Certificate to authenticate with.";
default = null;
example = "/var/lib/secrets/openconnect_certificate.pem";
type = with types; nullOr (either path pkcs11);
};
privateKey = mkOption {
description = "Private key to authenticate with.";
example = "/var/lib/secrets/openconnect_private_key.pem";
default = null;
type = with types; nullOr (either path pkcs11);
};
extraOptions = mkOption {
description = ''
Extra config to be appended to the interface config. It should
contain long-format options as would be accepted on the command
line by <code>openconnect</code>
(see https://www.infradead.org/openconnect/manual.html).
Non-key-value options like <code>deflate</code> can be used by
declaring them as booleans, i. e. <code>deflate = true;</code>.
'';
default = { };
example = {
compression = "stateless";
no-http-keepalive = true;
no-dtls = true;
};
type = with types; attrsOf (either str bool);
};
};
};
generateExtraConfig = extra_cfg:
strings.concatStringsSep "\n" (attrsets.mapAttrsToList
(name: value: if (value == true) then name else "${name}=${value}")
(attrsets.filterAttrs (_: value: value != false) extra_cfg));
generateConfig = name: icfg:
pkgs.writeText "config" ''
interface=${name}
${optionalString (icfg.user != null) "user=${icfg.user}"}
${optionalString (icfg.passwordFile != null) "passwd-on-stdin"}
${optionalString (icfg.certificate != null)
"certificate=${icfg.certificate}"}
${optionalString (icfg.privateKey != null) "sslkey=${icfg.privateKey}"}
${generateExtraConfig icfg.extraOptions}
'';
generateUnit = name: icfg: {
description = "OpenConnect Interface - ${name}";
requires = [ "network-online.target" ];
after = [ "network.target" "network-online.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
ExecStart = "${openconnect}/bin/openconnect --config=${
generateConfig name icfg
} ${icfg.gateway}";
StandardInput = "file:${icfg.passwordFile}";
ProtectHome = true;
};
};
in {
options.networking.openconnect = {
package = mkPackageOption pkgs "openconnect" { };
interfaces = mkOption {
description = "OpenConnect interfaces.";
default = { };
example = {
openconnect0 = {
gateway = "gateway.example.com";
protocol = "anyconnect";
user = "example-user";
passwordFile = "/var/lib/secrets/openconnect-passwd";
};
};
type = with types; attrsOf (submodule interfaceOptions);
};
};
config = {
systemd.services = mapAttrs' (name: value: {
name = "openconnect-${name}";
value = generateUnit name value;
}) cfg.interfaces;
};
meta.maintainers = with maintainers; [ alyaeanyx ];
}

View file

@ -30,10 +30,10 @@ in {
enable = mkEnableOption "PowerDNS Recursor, a recursive DNS server"; enable = mkEnableOption "PowerDNS Recursor, a recursive DNS server";
dns.address = mkOption { dns.address = mkOption {
type = types.str; type = oneOrMore types.str;
default = "0.0.0.0"; default = [ "::" "0.0.0.0" ];
description = '' description = ''
IP address Recursor DNS server will bind to. IP addresses Recursor DNS server will bind to.
''; '';
}; };
@ -47,8 +47,12 @@ in {
dns.allowFrom = mkOption { dns.allowFrom = mkOption {
type = types.listOf types.str; type = types.listOf types.str;
default = [ "10.0.0.0/8" "172.16.0.0/12" "192.168.0.0/16" ]; default = [
example = [ "0.0.0.0/0" ]; "127.0.0.0/8" "10.0.0.0/8" "100.64.0.0/10"
"169.254.0.0/16" "192.168.0.0/16" "172.16.0.0/12"
"::1/128" "fc00::/7" "fe80::/10"
];
example = [ "0.0.0.0/0" "::/0" ];
description = '' description = ''
IP address ranges of clients allowed to make DNS queries. IP address ranges of clients allowed to make DNS queries.
''; '';
@ -72,7 +76,8 @@ in {
api.allowFrom = mkOption { api.allowFrom = mkOption {
type = types.listOf types.str; type = types.listOf types.str;
default = [ "0.0.0.0/0" ]; default = [ "127.0.0.1" "::1" ];
example = [ "0.0.0.0/0" "::/0" ];
description = '' description = ''
IP address ranges of clients allowed to make API requests. IP address ranges of clients allowed to make API requests.
''; '';
@ -96,7 +101,7 @@ in {
forwardZonesRecurse = mkOption { forwardZonesRecurse = mkOption {
type = types.attrs; type = types.attrs;
example = { eth = "127.0.0.1:5353"; }; example = { eth = "[::1]:5353"; };
default = {}; default = {};
description = '' description = ''
DNS zones to be forwarded to other recursive servers. DNS zones to be forwarded to other recursive servers.

View file

@ -1,31 +1,37 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib; with lib;
let let
cfg = config.services.shellhub-agent; cfg = config.services.shellhub-agent;
in { in
{
###### interface ###### interface
options = { options = {
services.shellhub-agent = { services.shellhub-agent = {
enable = mkOption { enable = mkEnableOption "ShellHub Agent daemon";
type = types.bool;
default = false; package = mkPackageOption pkgs "shellhub-agent" { };
preferredHostname = mkOption {
type = types.str;
default = "";
description = '' description = ''
Whether to enable the ShellHub Agent daemon, which allows Set the device preferred hostname. This provides a hint to
secure remote logins. the server to use this as hostname if it is available.
''; '';
}; };
package = mkOption { keepAliveInterval = mkOption {
type = types.package; type = types.int;
default = pkgs.shellhub-agent; default = 30;
defaultText = literalExpression "pkgs.shellhub-agent";
description = '' description = ''
Which ShellHub Agent package to use. Determine the interval to send the keep alive message to
the server. This has a direct impact of the bandwidth
used by the device.
''; '';
}; };
@ -74,9 +80,13 @@ in {
"time-sync.target" "time-sync.target"
]; ];
environment.SERVER_ADDRESS = cfg.server; environment = {
environment.PRIVATE_KEY = cfg.privateKey; SHELLHUB_SERVER_ADDRESS = cfg.server;
environment.TENANT_ID = cfg.tenantId; SHELLHUB_PRIVATE_KEY = cfg.privateKey;
SHELLHUB_TENANT_ID = cfg.tenantId;
SHELLHUB_KEEPALIVE_INTERVAL = toString cfg.keepAliveInterval;
SHELLHUB_PREFERRED_HOSTNAME = cfg.preferredHostname;
};
serviceConfig = { serviceConfig = {
# The service starts sessions for different users. # The service starts sessions for different users.
@ -85,7 +95,6 @@ in {
ExecStart = "${cfg.package}/bin/agent"; ExecStart = "${cfg.package}/bin/agent";
}; };
}; };
environment.systemPackages = [ cfg.package ];
}; };
} }

View file

@ -609,6 +609,7 @@ in
connection_reaper_interval = 30; connection_reaper_interval = 30;
relative_url_root = null; relative_url_root = null;
message_bus_max_backlog_size = 100; message_bus_max_backlog_size = 100;
message_bus_clear_every = 50;
secret_key_base = cfg.secretKeyBaseFile; secret_key_base = cfg.secretKeyBaseFile;
fallback_assets_path = null; fallback_assets_path = null;
@ -655,7 +656,12 @@ in
long_polling_interval = null; long_polling_interval = null;
}; };
services.redis.enable = lib.mkDefault (cfg.redis.host == "localhost"); services.redis.servers.discourse =
lib.mkIf (lib.elem cfg.redis.host [ "localhost" "127.0.0.1" ]) {
enable = true;
bind = cfg.redis.host;
port = cfg.backendSettings.redis_port;
};
services.postgresql = lib.mkIf databaseActuallyCreateLocally { services.postgresql = lib.mkIf databaseActuallyCreateLocally {
enable = true; enable = true;
@ -696,12 +702,12 @@ in
systemd.services.discourse = { systemd.services.discourse = {
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
after = [ after = [
"redis.service" "redis-discourse.service"
"postgresql.service" "postgresql.service"
"discourse-postgresql.service" "discourse-postgresql.service"
]; ];
bindsTo = [ bindsTo = [
"redis.service" "redis-discourse.service"
] ++ lib.optionals (cfg.database.host == null) [ ] ++ lib.optionals (cfg.database.host == null) [
"postgresql.service" "postgresql.service"
"discourse-postgresql.service" "discourse-postgresql.service"

View file

@ -0,0 +1,318 @@
{ lib, pkgs, config, options, ... }:
let
cfg = config.services.nifi;
opt = options.services.nifi;
env = {
NIFI_OVERRIDE_NIFIENV = "true";
NIFI_HOME = "/var/lib/nifi";
NIFI_PID_DIR = "/run/nifi";
NIFI_LOG_DIR = "/var/log/nifi";
};
envFile = pkgs.writeText "nifi.env" (lib.concatMapStrings (s: s + "\n") (
(lib.concatLists (lib.mapAttrsToList (name: value:
if value != null then [
"${name}=\"${toString value}\""
] else []
) env))));
nifiEnv = pkgs.writeShellScriptBin "nifi-env" ''
set -a
source "${envFile}"
eval -- "\$@"
'';
in {
options = {
services.nifi = {
enable = lib.mkEnableOption "Apache NiFi";
package = lib.mkOption {
type = lib.types.package;
default = pkgs.nifi;
defaultText = lib.literalExpression "pkgs.nifi";
description = "Apache NiFi package to use.";
};
user = lib.mkOption {
type = lib.types.str;
default = "nifi";
description = "User account where Apache NiFi runs.";
};
group = lib.mkOption {
type = lib.types.str;
default = "nifi";
description = "Group account where Apache NiFi runs.";
};
enableHTTPS = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Enable HTTPS protocol. Don`t use in production.";
};
listenHost = lib.mkOption {
type = lib.types.str;
default = if cfg.enableHTTPS then "0.0.0.0" else "127.0.0.1";
defaultText = lib.literalExpression ''
if config.${opt.enableHTTPS}
then "0.0.0.0"
else "127.0.0.1"
'';
description = "Bind to an ip for Apache NiFi web-ui.";
};
listenPort = lib.mkOption {
type = lib.types.int;
default = if cfg.enableHTTPS then 8443 else 8080;
defaultText = lib.literalExpression ''
if config.${opt.enableHTTPS}
then "8443"
else "8000"
'';
description = "Bind to a port for Apache NiFi web-ui.";
};
proxyHost = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = if cfg.enableHTTPS then "0.0.0.0" else null;
defaultText = lib.literalExpression ''
if config.${opt.enableHTTPS}
then "0.0.0.0"
else null
'';
description = "Allow requests from a specific host.";
};
proxyPort = lib.mkOption {
type = lib.types.nullOr lib.types.int;
default = if cfg.enableHTTPS then 8443 else null;
defaultText = lib.literalExpression ''
if config.${opt.enableHTTPS}
then "8443"
else null
'';
description = "Allow requests from a specific port.";
};
initUser = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "Initial user account for Apache NiFi. Username must be at least 4 characters.";
};
initPasswordFile = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
example = "/run/keys/nifi/password-nifi";
description = "nitial password for Apache NiFi. Password must be at least 12 characters.";
};
initJavaHeapSize = lib.mkOption {
type = lib.types.nullOr lib.types.int;
default = null;
example = 1024;
description = "Set the initial heap size for the JVM in MB.";
};
maxJavaHeapSize = lib.mkOption {
type = lib.types.nullOr lib.types.int;
default = null;
example = 2048;
description = "Set the initial heap size for the JVM in MB.";
};
};
};
config = lib.mkIf cfg.enable {
assertions = [
{ assertion = cfg.initUser!=null || cfg.initPasswordFile==null;
message = ''
<option>services.nifi.initUser</option> needs to be set if <option>services.nifi.initPasswordFile</option> enabled.
'';
}
{ assertion = cfg.initUser==null || cfg.initPasswordFile!=null;
message = ''
<option>services.nifi.initPasswordFile</option> needs to be set if <option>services.nifi.initUser</option> enabled.
'';
}
{ assertion = cfg.proxyHost==null || cfg.proxyPort!=null;
message = ''
<option>services.nifi.proxyPort</option> needs to be set if <option>services.nifi.proxyHost</option> value specified.
'';
}
{ assertion = cfg.proxyHost!=null || cfg.proxyPort==null;
message = ''
<option>services.nifi.proxyHost</option> needs to be set if <option>services.nifi.proxyPort</option> value specified.
'';
}
{ assertion = cfg.initJavaHeapSize==null || cfg.maxJavaHeapSize!=null;
message = ''
<option>services.nifi.maxJavaHeapSize</option> needs to be set if <option>services.nifi.initJavaHeapSize</option> value specified.
'';
}
{ assertion = cfg.initJavaHeapSize!=null || cfg.maxJavaHeapSize==null;
message = ''
<option>services.nifi.initJavaHeapSize</option> needs to be set if <option>services.nifi.maxJavaHeapSize</option> value specified.
'';
}
];
warnings = lib.optional (cfg.enableHTTPS==false) ''
Please do not disable HTTPS mode in production. In this mode, access to the nifi is opened without authentication.
'';
systemd.tmpfiles.rules = [
"d '/var/lib/nifi/conf' 0750 ${cfg.user} ${cfg.group}"
"L+ '/var/lib/nifi/lib' - - - - ${cfg.package}/lib"
];
systemd.services.nifi = {
description = "Apache NiFi";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
environment = env;
path = [ pkgs.gawk ];
serviceConfig = {
Type = "forking";
PIDFile = "/run/nifi/nifi.pid";
ExecStartPre = pkgs.writeScript "nifi-pre-start.sh" ''
#!/bin/sh
umask 077
test -f '/var/lib/nifi/conf/authorizers.xml' || (cp '${cfg.package}/share/nifi/conf/authorizers.xml' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/authorizers.xml')
test -f '/var/lib/nifi/conf/bootstrap.conf' || (cp '${cfg.package}/share/nifi/conf/bootstrap.conf' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/bootstrap.conf')
test -f '/var/lib/nifi/conf/bootstrap-hashicorp-vault.conf' || (cp '${cfg.package}/share/nifi/conf/bootstrap-hashicorp-vault.conf' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/bootstrap-hashicorp-vault.conf')
test -f '/var/lib/nifi/conf/bootstrap-notification-services.xml' || (cp '${cfg.package}/share/nifi/conf/bootstrap-notification-services.xml' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/bootstrap-notification-services.xml')
test -f '/var/lib/nifi/conf/logback.xml' || (cp '${cfg.package}/share/nifi/conf/logback.xml' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/logback.xml')
test -f '/var/lib/nifi/conf/login-identity-providers.xml' || (cp '${cfg.package}/share/nifi/conf/login-identity-providers.xml' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/login-identity-providers.xml')
test -f '/var/lib/nifi/conf/nifi.properties' || (cp '${cfg.package}/share/nifi/conf/nifi.properties' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/nifi.properties')
test -f '/var/lib/nifi/conf/stateless-logback.xml' || (cp '${cfg.package}/share/nifi/conf/stateless-logback.xml' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/stateless-logback.xml')
test -f '/var/lib/nifi/conf/stateless.properties' || (cp '${cfg.package}/share/nifi/conf/stateless.properties' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/stateless.properties')
test -f '/var/lib/nifi/conf/state-management.xml' || (cp '${cfg.package}/share/nifi/conf/state-management.xml' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/state-management.xml')
test -f '/var/lib/nifi/conf/zookeeper.properties' || (cp '${cfg.package}/share/nifi/conf/zookeeper.properties' '/var/lib/nifi/conf/' && chmod 0640 '/var/lib/nifi/conf/zookeeper.properties')
test -d '/var/lib/nifi/docs/html' || (mkdir -p /var/lib/nifi/docs && cp -r '${cfg.package}/share/nifi/docs/html' '/var/lib/nifi/docs/html')
${lib.optionalString ((cfg.initUser != null) && (cfg.initPasswordFile != null)) ''
awk -F'[<|>]' '/property name="Username"/ {if ($3!="") f=1} END{exit !f}' /var/lib/nifi/conf/login-identity-providers.xml || ${cfg.package}/bin/nifi.sh set-single-user-credentials ${cfg.initUser} $(cat ${cfg.initPasswordFile})
''}
${lib.optionalString (cfg.enableHTTPS == false) ''
sed -i /var/lib/nifi/conf/nifi.properties \
-e 's|nifi.remote.input.secure=.*|nifi.remote.input.secure=false|g' \
-e 's|nifi.web.http.host=.*|nifi.web.http.host=${cfg.listenHost}|g' \
-e 's|nifi.web.http.port=.*|nifi.web.http.port=${(toString cfg.listenPort)}|g' \
-e 's|nifi.web.https.host=.*|nifi.web.https.host=|g' \
-e 's|nifi.web.https.port=.*|nifi.web.https.port=|g' \
-e 's|nifi.security.keystore=.*|nifi.security.keystore=|g' \
-e 's|nifi.security.keystoreType=.*|nifi.security.keystoreType=|g' \
-e 's|nifi.security.truststore=.*|nifi.security.truststore=|g' \
-e 's|nifi.security.truststoreType=.*|nifi.security.truststoreType=|g' \
-e '/nifi.security.keystorePasswd/s|^|#|' \
-e '/nifi.security.keyPasswd/s|^|#|' \
-e '/nifi.security.truststorePasswd/s|^|#|'
''}
${lib.optionalString (cfg.enableHTTPS == true) ''
sed -i /var/lib/nifi/conf/nifi.properties \
-e 's|nifi.remote.input.secure=.*|nifi.remote.input.secure=true|g' \
-e 's|nifi.web.http.host=.*|nifi.web.http.host=|g' \
-e 's|nifi.web.http.port=.*|nifi.web.http.port=|g' \
-e 's|nifi.web.https.host=.*|nifi.web.https.host=${cfg.listenHost}|g' \
-e 's|nifi.web.https.port=.*|nifi.web.https.port=${(toString cfg.listenPort)}|g' \
-e 's|nifi.security.keystore=.*|nifi.security.keystore=./conf/keystore.p12|g' \
-e 's|nifi.security.keystoreType=.*|nifi.security.keystoreType=PKCS12|g' \
-e 's|nifi.security.truststore=.*|nifi.security.truststore=./conf/truststore.p12|g' \
-e 's|nifi.security.truststoreType=.*|nifi.security.truststoreType=PKCS12|g' \
-e '/nifi.security.keystorePasswd/s|^#\+||' \
-e '/nifi.security.keyPasswd/s|^#\+||' \
-e '/nifi.security.truststorePasswd/s|^#\+||'
''}
${lib.optionalString ((cfg.enableHTTPS == true) && (cfg.proxyHost != null) && (cfg.proxyPort != null)) ''
sed -i /var/lib/nifi/conf/nifi.properties \
-e 's|nifi.web.proxy.host=.*|nifi.web.proxy.host=${cfg.proxyHost}:${(toString cfg.proxyPort)}|g'
''}
${lib.optionalString ((cfg.enableHTTPS == false) || (cfg.proxyHost == null) && (cfg.proxyPort == null)) ''
sed -i /var/lib/nifi/conf/nifi.properties \
-e 's|nifi.web.proxy.host=.*|nifi.web.proxy.host=|g'
''}
${lib.optionalString ((cfg.initJavaHeapSize != null) && (cfg.maxJavaHeapSize != null))''
sed -i /var/lib/nifi/conf/bootstrap.conf \
-e 's|java.arg.2=.*|java.arg.2=-Xms${(toString cfg.initJavaHeapSize)}m|g' \
-e 's|java.arg.3=.*|java.arg.3=-Xmx${(toString cfg.maxJavaHeapSize)}m|g'
''}
${lib.optionalString ((cfg.initJavaHeapSize == null) && (cfg.maxJavaHeapSize == null))''
sed -i /var/lib/nifi/conf/bootstrap.conf \
-e 's|java.arg.2=.*|java.arg.2=-Xms512m|g' \
-e 's|java.arg.3=.*|java.arg.3=-Xmx512m|g'
''}
'';
ExecStart = "${cfg.package}/bin/nifi.sh start";
ExecStop = "${cfg.package}/bin/nifi.sh stop";
# User and group
User = cfg.user;
Group = cfg.group;
# Runtime directory and mode
RuntimeDirectory = "nifi";
RuntimeDirectoryMode = "0750";
# State directory and mode
StateDirectory = "nifi";
StateDirectoryMode = "0750";
# Logs directory and mode
LogsDirectory = "nifi";
LogsDirectoryMode = "0750";
# Proc filesystem
ProcSubset = "pid";
ProtectProc = "invisible";
# Access write directories
ReadWritePaths = [ cfg.initPasswordFile ];
UMask = "0027";
# Capabilities
CapabilityBoundingSet = "";
# Security
NoNewPrivileges = true;
# Sandboxing
ProtectSystem = "strict";
ProtectHome = true;
PrivateTmp = true;
PrivateDevices = true;
PrivateIPC = true;
PrivateUsers = true;
ProtectHostname = true;
ProtectClock = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
ProtectControlGroups = true;
RestrictAddressFamilies = [ "AF_INET AF_INET6" ];
RestrictNamespaces = true;
LockPersonality = true;
MemoryDenyWriteExecute = false;
RestrictRealtime = true;
RestrictSUIDSGID = true;
RemoveIPC = true;
PrivateMounts = true;
# System Call Filtering
SystemCallArchitectures = "native";
SystemCallFilter = [ "~@cpu-emulation @debug @keyring @memlock @mount @obsolete @resources @privileged @setuid" "@chown" ];
};
};
users.users = lib.mkMerge [
(lib.mkIf (cfg.user == "nifi") {
nifi = {
group = cfg.group;
isSystemUser = true;
home = cfg.package;
};
})
(lib.attrsets.setAttrByPath [ cfg.user "packages" ] [ cfg.package nifiEnv ])
];
users.groups = lib.optionalAttrs (cfg.group == "nifi") {
nifi = { };
};
};
}

View file

@ -255,20 +255,22 @@ let
else defaultListen; else defaultListen;
listenString = { addr, port, ssl, extraParameters ? [], ... }: listenString = { addr, port, ssl, extraParameters ? [], ... }:
"listen ${addr}:${toString port} " (if ssl && vhost.http3 then "
+ optionalString ssl "ssl "
+ optionalString (ssl && vhost.http2) "http2 "
+ optionalString vhost.default "default_server "
+ optionalString (extraParameters != []) (concatStringsSep " " extraParameters)
+ ";"
+ (if ssl && vhost.http3 then ''
# UDP listener for **QUIC+HTTP/3 # UDP listener for **QUIC+HTTP/3
listen ${addr}:${toString port} http3 reuseport; listen ${addr}:${toString port} http3 "
# Advertise that HTTP/3 is available + optionalString vhost.default "default_server "
add_header Alt-Svc 'h3=":443"'; + optionalString vhost.reuseport "reuseport "
# Sent when QUIC was used + optionalString (extraParameters != []) (concatStringsSep " " extraParameters)
add_header QUIC-Status $quic; + ";" else "")
'' else ""); + "
listen ${addr}:${toString port} "
+ optionalString (ssl && vhost.http2) "http2 "
+ optionalString ssl "ssl "
+ optionalString vhost.default "default_server "
+ optionalString vhost.reuseport "reuseport "
+ optionalString (extraParameters != []) (concatStringsSep " " extraParameters)
+ ";";
redirectListen = filter (x: !x.ssl) defaultListen; redirectListen = filter (x: !x.ssl) defaultListen;
@ -321,6 +323,11 @@ let
ssl_conf_command Options KTLS; ssl_conf_command Options KTLS;
''} ''}
${optionalString (hasSSL && vhost.http3) ''
# Advertise that HTTP/3 is available
add_header Alt-Svc 'h3=":443"; ma=86400' always;
''}
${mkBasicAuth vhostName vhost} ${mkBasicAuth vhostName vhost}
${mkLocations vhost.locations} ${mkLocations vhost.locations}

View file

@ -20,7 +20,7 @@ with lib;
serverAliases = mkOption { serverAliases = mkOption {
type = types.listOf types.str; type = types.listOf types.str;
default = []; default = [];
example = ["www.example.org" "example.org"]; example = [ "www.example.org" "example.org" ];
description = '' description = ''
Additional names of virtual hosts served by this virtual host configuration. Additional names of virtual hosts served by this virtual host configuration.
''; '';
@ -31,11 +31,11 @@ with lib;
addr = mkOption { type = str; description = "IP address."; }; addr = mkOption { type = str; description = "IP address."; };
port = mkOption { type = int; description = "Port number."; default = 80; }; port = mkOption { type = int; description = "Port number."; default = 80; };
ssl = mkOption { type = bool; description = "Enable SSL."; default = false; }; ssl = mkOption { type = bool; description = "Enable SSL."; default = false; };
extraParameters = mkOption { type = listOf str; description = "Extra parameters of this listen directive."; default = []; example = [ "reuseport" "deferred" ]; }; extraParameters = mkOption { type = listOf str; description = "Extra parameters of this listen directive."; default = []; example = [ "backlog=1024" "deferred" ]; };
}; }); }; });
default = []; default = [];
example = [ example = [
{ addr = "195.154.1.1"; port = 443; ssl = true;} { addr = "195.154.1.1"; port = 443; ssl = true; }
{ addr = "192.154.1.1"; port = 80; } { addr = "192.154.1.1"; port = 80; }
]; ];
description = '' description = ''
@ -207,6 +207,15 @@ with lib;
''; '';
}; };
reuseport = mkOption {
type = types.bool;
default = false;
description = ''
Create an individual listening socket .
It is required to specify only once on one of the hosts.
'';
};
root = mkOption { root = mkOption {
type = types.nullOr types.path; type = types.nullOr types.path;
default = null; default = null;

View file

@ -1,4 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, utils, ... }:
with lib; with lib;
@ -196,7 +196,7 @@ in
programs.evince.enable = mkDefault true; programs.evince.enable = mkDefault true;
programs.file-roller.enable = mkDefault true; programs.file-roller.enable = mkDefault true;
environment.systemPackages = (with pkgs // pkgs.gnome // pkgs.cinnamon; pkgs.gnome.removePackagesByName [ environment.systemPackages = with pkgs // pkgs.gnome // pkgs.cinnamon; utils.removePackagesByName [
# cinnamon team apps # cinnamon team apps
bulky bulky
blueberry blueberry
@ -212,7 +212,7 @@ in
# external apps shipped with linux-mint # external apps shipped with linux-mint
hexchat hexchat
gnome-calculator gnome-calculator
] config.environment.cinnamon.excludePackages); ] config.environment.cinnamon.excludePackages;
}) })
]; ];
} }

View file

@ -1,4 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, utils, ... }:
with lib; with lib;
@ -42,7 +42,8 @@ let
chmod -R a+w $out/share/gsettings-schemas/nixos-gsettings-overrides chmod -R a+w $out/share/gsettings-schemas/nixos-gsettings-overrides
cat - > $out/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas/nixos-defaults.gschema.override <<- EOF cat - > $out/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas/nixos-defaults.gschema.override <<- EOF
[org.gnome.desktop.background] [org.gnome.desktop.background]
picture-uri='file://${pkgs.nixos-artwork.wallpapers.simple-dark-gray.gnomeFilePath}' picture-uri='file://${pkgs.nixos-artwork.wallpapers.simple-blue.gnomeFilePath}'
picture-uri-dark='file://${pkgs.nixos-artwork.wallpapers.simple-dark-gray.gnomeFilePath}'
[org.gnome.desktop.screensaver] [org.gnome.desktop.screensaver]
picture-uri='file://${pkgs.nixos-artwork.wallpapers.simple-dark-gray-bottom.gnomeFilePath}' picture-uri='file://${pkgs.nixos-artwork.wallpapers.simple-dark-gray-bottom.gnomeFilePath}'
@ -455,7 +456,7 @@ in
(mkIf serviceCfg.core-utilities.enable { (mkIf serviceCfg.core-utilities.enable {
environment.systemPackages = environment.systemPackages =
with pkgs.gnome; with pkgs.gnome;
removePackagesByName utils.removePackagesByName
([ ([
baobab baobab
cheese cheese
@ -515,7 +516,7 @@ in
}) })
(mkIf serviceCfg.games.enable { (mkIf serviceCfg.games.enable {
environment.systemPackages = (with pkgs.gnome; removePackagesByName [ environment.systemPackages = with pkgs.gnome; utils.removePackagesByName [
aisleriot aisleriot
atomix atomix
five-or-more five-or-more
@ -536,12 +537,12 @@ in
quadrapassel quadrapassel
swell-foop swell-foop
tali tali
] config.environment.gnome.excludePackages); ] config.environment.gnome.excludePackages;
}) })
# Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/-/blob/3.38.0/elements/core/meta-gnome-core-developer-tools.bst # Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/-/blob/3.38.0/elements/core/meta-gnome-core-developer-tools.bst
(mkIf serviceCfg.core-developer-tools.enable { (mkIf serviceCfg.core-developer-tools.enable {
environment.systemPackages = (with pkgs.gnome; removePackagesByName [ environment.systemPackages = with pkgs.gnome; utils.removePackagesByName [
dconf-editor dconf-editor
devhelp devhelp
pkgs.gnome-builder pkgs.gnome-builder
@ -550,7 +551,7 @@ in
# in default configurations. # in default configurations.
# https://github.com/NixOS/nixpkgs/issues/60908 # https://github.com/NixOS/nixpkgs/issues/60908
/* gnome-boxes */ /* gnome-boxes */
] config.environment.gnome.excludePackages); ] config.environment.gnome.excludePackages;
services.sysprof.enable = notExcluded pkgs.sysprof; services.sysprof.enable = notExcluded pkgs.sysprof;
}) })

View file

@ -1,4 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, utils, ... }:
with lib; with lib;
@ -51,7 +51,7 @@ in
environment.systemPackages = environment.systemPackages =
pkgs.lxqt.preRequisitePackages ++ pkgs.lxqt.preRequisitePackages ++
pkgs.lxqt.corePackages ++ pkgs.lxqt.corePackages ++
(pkgs.gnome.removePackagesByName (utils.removePackagesByName
pkgs.lxqt.optionalPackages pkgs.lxqt.optionalPackages
config.environment.lxqt.excludePackages); config.environment.lxqt.excludePackages);

View file

@ -1,20 +1,9 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, utils, ... }:
with lib; with lib;
let let
addToXDGDirs = p: ''
if [ -d "${p}/share/gsettings-schemas/${p.name}" ]; then
export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${p}/share/gsettings-schemas/${p.name}
fi
if [ -d "${p}/lib/girepository-1.0" ]; then
export GI_TYPELIB_PATH=$GI_TYPELIB_PATH''${GI_TYPELIB_PATH:+:}${p}/lib/girepository-1.0
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH''${LD_LIBRARY_PATH:+:}${p}/lib
fi
'';
xcfg = config.services.xserver; xcfg = config.services.xserver;
cfg = xcfg.desktopManager.mate; cfg = xcfg.desktopManager.mate;
@ -48,24 +37,8 @@ in
pkgs.mate.mate-session-manager pkgs.mate.mate-session-manager
]; ];
services.xserver.displayManager.sessionCommands = ''
if test "$XDG_CURRENT_DESKTOP" = "MATE"; then
export XDG_MENU_PREFIX=mate-
# Let caja find extensions # Let caja find extensions
export CAJA_EXTENSION_DIRS=$CAJA_EXTENSION_DIRS''${CAJA_EXTENSION_DIRS:+:}${config.system.path}/lib/caja/extensions-2.0 environment.sessionVariables.CAJA_EXTENSION_DIRS = [ "${config.system.path}/lib/caja/extensions-2.0" ];
# Let caja extensions find gsettings schemas
${concatMapStrings (p: ''
if [ -d "${p}/lib/caja/extensions-2.0" ]; then
${addToXDGDirs p}
fi
'') config.environment.systemPackages}
# Add mate-control-center paths to some XDG variables because its schemas are needed by mate-settings-daemon, and mate-settings-daemon is a dependency for mate-control-center (that is, they are mutually recursive)
${addToXDGDirs pkgs.mate.mate-control-center}
fi
'';
# Let mate-panel find applets # Let mate-panel find applets
environment.sessionVariables."MATE_PANEL_APPLETS_DIR" = "${config.system.path}/share/mate-panel/applets"; environment.sessionVariables."MATE_PANEL_APPLETS_DIR" = "${config.system.path}/share/mate-panel/applets";
@ -74,7 +47,7 @@ in
# Debugging # Debugging
environment.sessionVariables.MATE_SESSION_DEBUG = mkIf cfg.debug "1"; environment.sessionVariables.MATE_SESSION_DEBUG = mkIf cfg.debug "1";
environment.systemPackages = pkgs.gnome.removePackagesByName environment.systemPackages = utils.removePackagesByName
(pkgs.mate.basePackages ++ (pkgs.mate.basePackages ++
pkgs.mate.extraPackages ++ pkgs.mate.extraPackages ++
[ [
@ -83,7 +56,6 @@ in
pkgs.gtk3.out pkgs.gtk3.out
pkgs.shared-mime-info pkgs.shared-mime-info
pkgs.xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/ pkgs.xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/
pkgs.mate.mate-settings-daemon
pkgs.yelp # for 'Contents' in 'Help' menus pkgs.yelp # for 'Contents' in 'Help' menus
]) ])
config.environment.mate.excludePackages; config.environment.mate.excludePackages;

View file

@ -1,4 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, utils, pkgs, ... }:
with lib; with lib;
@ -214,7 +214,7 @@ in
elementary-settings-daemon elementary-settings-daemon
pantheon-agent-geoclue2 pantheon-agent-geoclue2
pantheon-agent-polkit pantheon-agent-polkit
]) ++ (gnome.removePackagesByName [ ]) ++ (utils.removePackagesByName [
gnome.gnome-font-viewer gnome.gnome-font-viewer
gnome.gnome-settings-daemon338 gnome.gnome-settings-daemon338
] config.environment.pantheon.excludePackages); ] config.environment.pantheon.excludePackages);
@ -272,7 +272,7 @@ in
}) })
(mkIf serviceCfg.apps.enable { (mkIf serviceCfg.apps.enable {
environment.systemPackages = with pkgs.pantheon; pkgs.gnome.removePackagesByName ([ environment.systemPackages = with pkgs.pantheon; utils.removePackagesByName ([
elementary-calculator elementary-calculator
elementary-calendar elementary-calendar
elementary-camera elementary-camera

View file

@ -66,6 +66,12 @@ in
default = true; default = true;
description = "Enable the XFWM (default) window manager."; description = "Enable the XFWM (default) window manager.";
}; };
enableScreensaver = mkOption {
type = types.bool;
default = true;
description = "Enable the XFCE screensaver.";
};
}; };
}; };
@ -99,7 +105,6 @@ in
ristretto ristretto
xfce4-appfinder xfce4-appfinder
xfce4-notifyd xfce4-notifyd
xfce4-screensaver
xfce4-screenshooter xfce4-screenshooter
xfce4-session xfce4-session
xfce4-settings xfce4-settings
@ -123,7 +128,7 @@ in
] ++ optionals (!cfg.noDesktop) [ ] ++ optionals (!cfg.noDesktop) [
xfce4-panel xfce4-panel
xfdesktop xfdesktop
]; ] ++ optional cfg.enableScreensaver xfce4-screensaver;
environment.pathsToLink = [ environment.pathsToLink = [
"/share/xfce4" "/share/xfce4"
@ -169,6 +174,6 @@ in
xfce4-notifyd xfce4-notifyd
]; ];
security.pam.services.xfce4-screensaver.unixAuth = true; security.pam.services.xfce4-screensaver.unixAuth = cfg.enableScreensaver;
}; };
} }

View file

@ -7,19 +7,26 @@ let
in in
{ {
options = { options.services.xserver.windowManager.qtile = {
services.xserver.windowManager.qtile.enable = mkEnableOption "qtile"; enable = mkEnableOption "qtile";
package = mkPackageOption pkgs "qtile" { };
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
services.xserver.windowManager.session = [{ services.xserver.windowManager.session = [{
name = "qtile"; name = "qtile";
start = '' start = ''
${pkgs.qtile}/bin/qtile start & ${cfg.package}/bin/qtile start &
waitPID=$! waitPID=$!
''; '';
}]; }];
environment.systemPackages = [ pkgs.qtile ]; environment.systemPackages = [
# pkgs.qtile is currently a buildenv of qtile and its dependencies.
# For userland commands, we want the underlying package so that
# packages such as python don't bleed into userland and overwrite intended behavior.
(cfg.package.unwrapped or cfg.package)
];
}; };
} }

View file

@ -1,4 +1,4 @@
{ config, lib, pkgs, ... }: { config, lib, utils, pkgs, ... }:
with lib; with lib;
@ -181,6 +181,13 @@ in
''; '';
}; };
excludePackages = mkOption {
default = [];
example = literalExpression "[ pkgs.xterm ]";
type = types.listOf types.package;
description = "Which X11 packages to exclude from the default environment";
};
exportConfiguration = mkOption { exportConfiguration = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
@ -655,7 +662,7 @@ in
${cfgPath}.source = xorg.xf86inputevdev.out + "/share" + cfgPath; ${cfgPath}.source = xorg.xf86inputevdev.out + "/share" + cfgPath;
}); });
environment.systemPackages = environment.systemPackages = utils.removePackagesByName
[ xorg.xorgserver.out [ xorg.xorgserver.out
xorg.xrandr xorg.xrandr
xorg.xrdb xorg.xrdb
@ -671,7 +678,7 @@ in
pkgs.xdg-utils pkgs.xdg-utils
xorg.xf86inputevdev.out # get evdev.4 man page xorg.xf86inputevdev.out # get evdev.4 man page
pkgs.nixos-icons # needed for gnome and pantheon about dialog, nixos-manual and maybe more pkgs.nixos-icons # needed for gnome and pantheon about dialog, nixos-manual and maybe more
] ] config.services.xserver.excludePackages
++ optional (elem "virtualbox" cfg.videoDrivers) xorg.xrefresh; ++ optional (elem "virtualbox" cfg.videoDrivers) xorg.xrefresh;
environment.pathsToLink = [ "/share/X11" ]; environment.pathsToLink = [ "/share/X11" ];

View file

@ -1,5 +1,17 @@
#! @perl@/bin/perl #! @perl@/bin/perl
# Issue #166838 uncovered a situation in which a configuration not suitable
# for the target architecture caused a cryptic error message instead of
# a clean failure. Due to this mismatch, the perl interpreter in the shebang
# line wasn't able to be executed, causing this script to be misinterpreted
# as a shell script.
#
# Let's detect this situation to give a more meaningful error
# message. The following two lines are carefully written to be both valid Perl
# and Bash.
printf "Perl script erroneously interpreted as shell script,\ndoes target platform match nixpkgs.crossSystem platform?\n" && exit 1
if 0;
use strict; use strict;
use warnings; use warnings;
use Config::IniFiles; use Config::IniFiles;

View file

@ -55,11 +55,18 @@ let
substituteInPlace $out/dry-activate --subst-var out substituteInPlace $out/dry-activate --subst-var out
chmod u+x $out/activate $out/dry-activate chmod u+x $out/activate $out/dry-activate
unset activationScript dryActivationScript unset activationScript dryActivationScript
${pkgs.stdenv.shellDryRun} $out/activate
${pkgs.stdenv.shellDryRun} $out/dry-activate
${if config.boot.initrd.systemd.enable then ''
cp ${config.system.build.bootStage2} $out/prepare-root
substituteInPlace $out/prepare-root --subst-var-by systemConfig $out
# This must not be a symlink or the abs_path of the grub builder for the tests
# will resolve the symlink and we end up with a path that doesn't point to a
# system closure.
cp "$systemd/lib/systemd/systemd" $out/init
'' else ''
cp ${config.system.build.bootStage2} $out/init cp ${config.system.build.bootStage2} $out/init
substituteInPlace $out/init --subst-var-by systemConfig $out substituteInPlace $out/init --subst-var-by systemConfig $out
''}
ln -s ${config.system.build.etc}/etc $out/etc ln -s ${config.system.build.etc}/etc $out/etc
ln -s ${config.system.path} $out/sw ln -s ${config.system.path} $out/sw

View file

@ -44,6 +44,8 @@ let
{ splashImage = f cfg.splashImage; { splashImage = f cfg.splashImage;
splashMode = f cfg.splashMode; splashMode = f cfg.splashMode;
backgroundColor = f cfg.backgroundColor; backgroundColor = f cfg.backgroundColor;
entryOptions = f cfg.entryOptions;
subEntryOptions = f cfg.subEntryOptions;
grub = f grub; grub = f grub;
grubTarget = f (grub.grubTarget or ""); grubTarget = f (grub.grubTarget or "");
shell = "${pkgs.runtimeShell}"; shell = "${pkgs.runtimeShell}";
@ -448,6 +450,30 @@ in
''; '';
}; };
entryOptions = mkOption {
default = "--class nixos --unrestricted";
type = types.nullOr types.str;
description = ''
Options applied to the primary NixOS menu entry.
<note><para>
This options has no effect for GRUB 1.
</para></note>
'';
};
subEntryOptions = mkOption {
default = "--class nixos";
type = types.nullOr types.str;
description = ''
Options applied to the secondary NixOS submenu entry.
<note><para>
This options has no effect for GRUB 1.
</para></note>
'';
};
theme = mkOption { theme = mkOption {
type = types.nullOr types.path; type = types.nullOr types.path;
example = literalExpression "pkgs.nixos-grub2-theme"; example = literalExpression "pkgs.nixos-grub2-theme";

View file

@ -64,6 +64,8 @@ my $extraEntries = get("extraEntries");
my $extraEntriesBeforeNixOS = get("extraEntriesBeforeNixOS") eq "true"; my $extraEntriesBeforeNixOS = get("extraEntriesBeforeNixOS") eq "true";
my $splashImage = get("splashImage"); my $splashImage = get("splashImage");
my $splashMode = get("splashMode"); my $splashMode = get("splashMode");
my $entryOptions = get("entryOptions");
my $subEntryOptions = get("subEntryOptions");
my $backgroundColor = get("backgroundColor"); my $backgroundColor = get("backgroundColor");
my $configurationLimit = int(get("configurationLimit")); my $configurationLimit = int(get("configurationLimit"));
my $copyKernels = get("copyKernels") eq "true"; my $copyKernels = get("copyKernels") eq "true";
@ -509,7 +511,7 @@ sub addEntry {
# Add default entries. # Add default entries.
$conf .= "$extraEntries\n" if $extraEntriesBeforeNixOS; $conf .= "$extraEntries\n" if $extraEntriesBeforeNixOS;
addEntry("NixOS - Default", $defaultConfig, "--unrestricted"); addEntry("NixOS - Default", $defaultConfig, $entryOptions);
$conf .= "$extraEntries\n" unless $extraEntriesBeforeNixOS; $conf .= "$extraEntries\n" unless $extraEntriesBeforeNixOS;
@ -546,7 +548,7 @@ sub addProfile {
my ($profile, $description) = @_; my ($profile, $description) = @_;
# Add entries for all generations of this profile. # Add entries for all generations of this profile.
$conf .= "submenu \"$description\" {\n" if $grubVersion == 2; $conf .= "submenu \"$description\" --class submenu {\n" if $grubVersion == 2;
sub nrFromGen { my ($x) = @_; $x =~ /\/\w+-(\d+)-link/; return $1; } sub nrFromGen { my ($x) = @_; $x =~ /\/\w+-(\d+)-link/; return $1; }
@ -566,7 +568,7 @@ sub addProfile {
-e "$link/nixos-version" -e "$link/nixos-version"
? readFile("$link/nixos-version") ? readFile("$link/nixos-version")
: basename((glob(dirname(Cwd::abs_path("$link/kernel")) . "/lib/modules/*"))[0]); : basename((glob(dirname(Cwd::abs_path("$link/kernel")) . "/lib/modules/*"))[0]);
addEntry("NixOS - Configuration " . nrFromGen($link) . " ($date - $version)", $link); addEntry("NixOS - Configuration " . nrFromGen($link) . " ($date - $version)", $link, $subEntryOptions);
} }
$conf .= "}\n" if $grubVersion == 2; $conf .= "}\n" if $grubVersion == 2;

View file

@ -1704,8 +1704,8 @@ let
renderConfig = def: renderConfig = def:
{ text = '' { text = ''
[Network] [Network]
${attrsToSection def.networkConfig}
'' ''
+ attrsToSection def.networkConfig
+ optionalString (def.dhcpV4Config != { }) '' + optionalString (def.dhcpV4Config != { }) ''
[DHCPv4] [DHCPv4]
${attrsToSection def.dhcpV4Config} ${attrsToSection def.dhcpV4Config}
@ -1815,8 +1815,7 @@ let
unitFiles = listToAttrs (map (name: { unitFiles = listToAttrs (map (name: {
name = "systemd/network/${name}"; name = "systemd/network/${name}";
value.source = "${cfg.units.${name}.unit}/${name}"; value.source = "${cfg.units.${name}.unit}/${name}";
}) (attrNames cfg.units)) // { }) (attrNames cfg.units));
};
in in
{ {

View file

@ -232,7 +232,8 @@ done
mkdir -p /lib mkdir -p /lib
ln -s @modulesClosure@/lib/modules /lib/modules ln -s @modulesClosure@/lib/modules /lib/modules
ln -s @modulesClosure@/lib/firmware /lib/firmware ln -s @modulesClosure@/lib/firmware /lib/firmware
echo @extraUtils@/bin/modprobe > /proc/sys/kernel/modprobe # see comment in stage-1.nix for explanation
echo @extraUtils@/bin/modprobe-kernel > /proc/sys/kernel/modprobe
for i in @kernelModules@; do for i in @kernelModules@; do
info "loading module $(basename $i)..." info "loading module $(basename $i)..."
modprobe $i modprobe $i

View file

@ -131,6 +131,26 @@ let
copy_bin_and_libs ${pkgs.kmod}/bin/kmod copy_bin_and_libs ${pkgs.kmod}/bin/kmod
ln -sf kmod $out/bin/modprobe ln -sf kmod $out/bin/modprobe
# Dirty hack to make sure the kernel properly loads modules
# such as ext4 on demand (e.g. on a `mount(2)` syscall). This is necessary
# because `kmod` isn't linked against `libpthread.so.0` anymore (since
# it was merged into `libc.so.6` since version `2.34`), but still needs
# to access it for some reason. This is not an issue in stage-1 itself
# because of the `LD_LIBRARY_PATH`-variable and anytime later because the rpath of
# kmod/modprobe points to glibc's `$out/lib` where `libpthread.so.6` exists.
# However, this is a problem when the kernel calls `modprobe` inside
# the initial ramdisk because it doesn't know about the
# `LD_LIBRARY_PATH` and the rpath was nuked.
#
# Also, we can't use `makeWrapper` here because `kmod` only does
# `modprobe` functionality if `argv[0] == "modprobe"`.
cat >$out/bin/modprobe-kernel <<EOF
#!$out/bin/ash
export LD_LIBRARY_PATH=$out/lib
exec $out/bin/modprobe "\$@"
EOF
chmod +x $out/bin/modprobe-kernel
# Copy resize2fs if any ext* filesystems are to be resized # Copy resize2fs if any ext* filesystems are to be resized
${optionalString (any (fs: fs.autoResize && (lib.hasPrefix "ext" fs.fsType)) fileSystems) '' ${optionalString (any (fs: fs.autoResize && (lib.hasPrefix "ext" fs.fsType)) fileSystems) ''
# We need mke2fs in the initrd. # We need mke2fs in the initrd.
@ -335,7 +355,7 @@ let
[ { object = bootStage1; [ { object = bootStage1;
symlink = "/init"; symlink = "/init";
} }
{ object = pkgs.writeText "mdadm.conf" config.boot.initrd.mdadmConf; { object = pkgs.writeText "mdadm.conf" config.boot.initrd.services.mdraid.mdadmConf;
symlink = "/etc/mdadm.conf"; symlink = "/etc/mdadm.conf";
} }
{ object = pkgs.runCommand "initrd-kmod-blacklist-ubuntu" { { object = pkgs.runCommand "initrd-kmod-blacklist-ubuntu" {
@ -485,14 +505,6 @@ in
''; '';
}; };
boot.initrd.mdadmConf = mkOption {
default = "";
type = types.lines;
description = ''
Contents of <filename>/etc/mdadm.conf</filename> in stage 1.
'';
};
boot.initrd.preLVMCommands = mkOption { boot.initrd.preLVMCommands = mkOption {
default = ""; default = "";
type = types.lines; type = types.lines;
@ -716,6 +728,9 @@ in
]; ];
boot.initrd.supportedFilesystems = map (fs: fs.fsType) fileSystems; boot.initrd.supportedFilesystems = map (fs: fs.fsType) fileSystems;
}; };
imports = [
(mkRenamedOptionModule [ "boot" "initrd" "mdadmConf" ] [ "boot" "initrd" "services" "mdraid" "mdadmConf" ])
];
} }

View file

@ -5,28 +5,30 @@ systemConfig=@systemConfig@
export HOME=/root PATH="@path@" export HOME=/root PATH="@path@"
# Process the kernel command line. if [ "${IN_NIXOS_SYSTEMD_STAGE1:-}" != true ]; then
for o in $(</proc/cmdline); do # Process the kernel command line.
for o in $(</proc/cmdline); do
case $o in case $o in
boot.debugtrace) boot.debugtrace)
# Show each command. # Show each command.
set -x set -x
;; ;;
esac esac
done done
# Print a greeting. # Print a greeting.
echo echo
echo -e "\e[1;32m<<< NixOS Stage 2 >>>\e[0m" echo -e "\e[1;32m<<< NixOS Stage 2 >>>\e[0m"
echo echo
# Normally, stage 1 mounts the root filesystem read/writable. # Normally, stage 1 mounts the root filesystem read/writable.
# However, in some environments, stage 2 is executed directly, and the # However, in some environments, stage 2 is executed directly, and the
# root is read-only. So make it writable here. # root is read-only. So make it writable here.
if [ -z "$container" ]; then if [ -z "$container" ]; then
mount -n -o remount,rw none / mount -n -o remount,rw none /
fi
fi fi
@ -39,6 +41,12 @@ if [ ! -e /proc/1 ]; then
local options="$3" local options="$3"
local fsType="$4" local fsType="$4"
# We must not overwrite this mount because it's bind-mounted
# from stage 1's /run
if [ "${IN_NIXOS_SYSTEMD_STAGE1:-}" = true ] && [ "${mountPoint}" = /run ]; then
return
fi
install -m 0755 -d "$mountPoint" install -m 0755 -d "$mountPoint"
mount -n -t "$fsType" -o "$options" "$device" "$mountPoint" mount -n -t "$fsType" -o "$options" "$device" "$mountPoint"
} }
@ -46,7 +54,11 @@ if [ ! -e /proc/1 ]; then
fi fi
echo "booting system configuration $systemConfig" > /dev/kmsg if [ "${IN_NIXOS_SYSTEMD_STAGE1:-}" = true ]; then
echo "booting system configuration ${systemConfig}"
else
echo "booting system configuration $systemConfig" > /dev/kmsg
fi
# Make /nix/store a read-only bind mount to enforce immutability of # Make /nix/store a read-only bind mount to enforce immutability of
@ -68,24 +80,26 @@ if [ -n "@readOnlyStore@" ]; then
fi fi
# Use /etc/resolv.conf supplied by systemd-nspawn, if applicable. if [ "${IN_NIXOS_SYSTEMD_STAGE1:-}" != true ]; then
if [ -n "@useHostResolvConf@" ] && [ -e /etc/resolv.conf ]; then # Use /etc/resolv.conf supplied by systemd-nspawn, if applicable.
if [ -n "@useHostResolvConf@" ] && [ -e /etc/resolv.conf ]; then
resolvconf -m 1000 -a host </etc/resolv.conf resolvconf -m 1000 -a host </etc/resolv.conf
fi fi
# Log the script output to /dev/kmsg or /run/log/stage-2-init.log. # Log the script output to /dev/kmsg or /run/log/stage-2-init.log.
# Only at this point are all the necessary prerequisites ready for these commands. # Only at this point are all the necessary prerequisites ready for these commands.
exec {logOutFd}>&1 {logErrFd}>&2 exec {logOutFd}>&1 {logErrFd}>&2
if test -w /dev/kmsg; then if test -w /dev/kmsg; then
exec > >(tee -i /proc/self/fd/"$logOutFd" | while read -r line; do exec > >(tee -i /proc/self/fd/"$logOutFd" | while read -r line; do
if test -n "$line"; then if test -n "$line"; then
echo "<7>stage-2-init: $line" > /dev/kmsg echo "<7>stage-2-init: $line" > /dev/kmsg
fi fi
done) 2>&1 done) 2>&1
else else
mkdir -p /run/log mkdir -p /run/log
exec > >(tee -i /run/log/stage-2-init.log) 2>&1 exec > >(tee -i /run/log/stage-2-init.log) 2>&1
fi
fi fi
@ -116,11 +130,15 @@ ln -sfn "$systemConfig" /run/booted-system
: >> /etc/machine-id : >> /etc/machine-id
# Reset the logging file descriptors. # No need to restore the stdout/stderr streams we never redirected and
exec 1>&$logOutFd 2>&$logErrFd # especially no need to start systemd
exec {logOutFd}>&- {logErrFd}>&- if [ "${IN_NIXOS_SYSTEMD_STAGE1:-}" != true ]; then
# Reset the logging file descriptors.
exec 1>&$logOutFd 2>&$logErrFd
exec {logOutFd}>&- {logErrFd}>&-
# Start systemd in a clean environment. # Start systemd in a clean environment.
echo "starting systemd..." echo "starting systemd..."
exec @systemdExecutable@ "$@" exec @systemdExecutable@ "$@"
fi

View file

@ -573,14 +573,6 @@ in
}) })
(filterAttrs (name: service: service.enable && service.startAt != []) cfg.services); (filterAttrs (name: service: service.enable && service.startAt != []) cfg.services);
# Generate timer units for all services that have a startAt value.
systemd.user.timers =
mapAttrs (name: service:
{ wantedBy = [ "timers.target" ];
timerConfig.OnCalendar = service.startAt;
})
(filterAttrs (name: service: service.startAt != []) cfg.user.services);
# Some overrides to upstream units. # Some overrides to upstream units.
systemd.services."systemd-backlight@".restartIfChanged = false; systemd.services."systemd-backlight@".restartIfChanged = false;
systemd.services."systemd-fsck@".restartIfChanged = false; systemd.services."systemd-fsck@".restartIfChanged = false;

View file

@ -0,0 +1,32 @@
{ config, pkgs, lib, ... }: let
cfg = config.boot.initrd.services.mdraid;
in {
options.boot.initrd.services.mdraid = {
enable = (lib.mkEnableOption "mdraid support in initrd") // {
visible = false;
};
mdadmConf = lib.mkOption {
description = "Contents of <filename>/etc/mdadm.conf</filename> in initrd.";
type = lib.types.lines;
default = "";
};
};
config = lib.mkIf (config.boot.initrd.systemd.enable && cfg.enable) {
boot.initrd.systemd = {
contents."/etc/mdadm.conf" = lib.mkIf (cfg.mdadmConf != "") {
text = cfg.mdadmConf;
};
initrdBin = [ pkgs.mdadm ];
};
boot.initrd.services.udev.packages = [ pkgs.mdadm ];
boot.initrd.systemd.packages = [ pkgs.mdadm ];
boot.kernelModules = [ "dm-raid" ];
};
}

View file

@ -34,7 +34,6 @@ let
"initrd-switch-root.service" "initrd-switch-root.service"
"initrd-switch-root.target" "initrd-switch-root.target"
"initrd.target" "initrd.target"
"initrd-udevadm-cleanup-db.service"
"kexec.target" "kexec.target"
"kmod-static-nodes.service" "kmod-static-nodes.service"
"local-fs-pre.target" "local-fs-pre.target"
@ -71,12 +70,6 @@ let
"systemd-sysctl.service" "systemd-sysctl.service"
"systemd-tmpfiles-setup-dev.service" "systemd-tmpfiles-setup-dev.service"
"systemd-tmpfiles-setup.service" "systemd-tmpfiles-setup.service"
"systemd-udevd-control.socket"
"systemd-udevd-kernel.socket"
"systemd-udevd.service"
"systemd-udev-settle.service"
"systemd-udev-trigger.service"
"systemd-vconsole-setup.service"
"timers.target" "timers.target"
"umount.target" "umount.target"
@ -96,6 +89,7 @@ let
enabledUpstreamUnits = filter (n: ! elem n cfg.suppressedUnits) upstreamUnits; enabledUpstreamUnits = filter (n: ! elem n cfg.suppressedUnits) upstreamUnits;
enabledUnits = filterAttrs (n: v: ! elem n cfg.suppressedUnits) cfg.units; enabledUnits = filterAttrs (n: v: ! elem n cfg.suppressedUnits) cfg.units;
jobScripts = concatLists (mapAttrsToList (_: unit: unit.jobScripts or []) (filterAttrs (_: v: v.enable) cfg.services));
stage1Units = generateUnits { stage1Units = generateUnits {
type = "initrd"; type = "initrd";
@ -107,7 +101,7 @@ let
fileSystems = filter utils.fsNeededForBoot config.system.build.fileSystems; fileSystems = filter utils.fsNeededForBoot config.system.build.fileSystems;
fstab = pkgs.writeText "fstab" (lib.concatMapStringsSep "\n" fstab = pkgs.writeText "initrd-fstab" (lib.concatMapStringsSep "\n"
({ fsType, mountPoint, device, options, autoFormat, autoResize, ... }@fs: let ({ fsType, mountPoint, device, options, autoFormat, autoResize, ... }@fs: let
opts = options ++ optional autoFormat "x-systemd.makefs" ++ optional autoResize "x-systemd.growfs"; opts = options ++ optional autoFormat "x-systemd.makefs" ++ optional autoResize "x-systemd.growfs";
in "${device} /sysroot${mountPoint} ${fsType} ${lib.concatStringsSep "," opts}") fileSystems); in "${device} /sysroot${mountPoint} ${fsType} ${lib.concatStringsSep "," opts}") fileSystems);
@ -124,14 +118,10 @@ let
}; };
initrdBinEnv = pkgs.buildEnv { initrdBinEnv = pkgs.buildEnv {
name = "initrd-emergency-env"; name = "initrd-bin-env";
paths = map getBin cfg.initrdBin; paths = map getBin cfg.initrdBin;
pathsToLink = ["/bin" "/sbin"]; pathsToLink = ["/bin" "/sbin"];
# Make recovery easier postBuild = concatStringsSep "\n" (mapAttrsToList (n: v: "ln -s '${v}' $out/bin/'${n}'") cfg.extraBin);
postBuild = ''
ln -s ${cfg.package.util-linux}/bin/mount $out/bin/
ln -s ${cfg.package.util-linux}/bin/umount $out/bin/
'';
}; };
initialRamdisk = pkgs.makeInitrdNG { initialRamdisk = pkgs.makeInitrdNG {
@ -149,7 +139,7 @@ in {
''; '';
package = (mkPackageOption pkgs "systemd" { package = (mkPackageOption pkgs "systemd" {
default = "systemdMinimal"; default = "systemdStage1";
}) // { }) // {
visible = false; visible = false;
}; };
@ -204,6 +194,19 @@ in {
default = []; default = [];
}; };
extraBin = mkOption {
description = ''
Tools to add to /bin
'';
example = literalExpression ''
{
umount = ''${pkgs.util-linux}/bin/umount;
}
'';
type = types.attrsOf types.path;
default = {};
};
suppressedStorePaths = mkOption { suppressedStorePaths = mkOption {
description = '' description = ''
Store paths specified in the storePaths option that Store paths specified in the storePaths option that
@ -341,8 +344,16 @@ in {
config = mkIf (config.boot.initrd.enable && cfg.enable) { config = mkIf (config.boot.initrd.enable && cfg.enable) {
system.build = { inherit initialRamdisk; }; system.build = { inherit initialRamdisk; };
boot.initrd.availableKernelModules = [ "autofs4" ]; # systemd needs this for some features
boot.initrd.systemd = { boot.initrd.systemd = {
initrdBin = [pkgs.bash pkgs.coreutils pkgs.kmod cfg.package] ++ config.system.fsPackages; initrdBin = [pkgs.bash pkgs.coreutils cfg.package.kmod cfg.package] ++ config.system.fsPackages;
extraBin = {
less = "${pkgs.less}/bin/less";
mount = "${cfg.package.util-linux}/bin/mount";
umount = "${cfg.package.util-linux}/bin/umount";
};
contents = { contents = {
"/init".source = "${cfg.package}/lib/systemd/systemd"; "/init".source = "${cfg.package}/lib/systemd/systemd";
@ -350,7 +361,7 @@ in {
"/etc/systemd/system.conf".text = '' "/etc/systemd/system.conf".text = ''
[Manager] [Manager]
DefaultEnvironment=PATH=/bin:/sbin DefaultEnvironment=PATH=/bin:/sbin ${optionalString (isBool cfg.emergencyAccess && cfg.emergencyAccess) "SYSTEMD_SULOGIN_FORCE=1"}
''; '';
"/etc/fstab".source = fstab; "/etc/fstab".source = fstab;
@ -366,19 +377,39 @@ in {
"/sbin".source = "${initrdBinEnv}/sbin"; "/sbin".source = "${initrdBinEnv}/sbin";
"/etc/sysctl.d/nixos.conf".text = "kernel.modprobe = /sbin/modprobe"; "/etc/sysctl.d/nixos.conf".text = "kernel.modprobe = /sbin/modprobe";
"/etc/modprobe.d/systemd.conf".source = "${cfg.package}/lib/modprobe.d/systemd.conf";
"/etc/modprobe.d/ubuntu.conf".source = pkgs.runCommand "initrd-kmod-blacklist-ubuntu" { } ''
${pkgs.buildPackages.perl}/bin/perl -0pe 's/## file: iwlwifi.conf(.+?)##/##/s;' $src > $out
'';
"/etc/modprobe.d/debian.conf".source = pkgs.kmod-debian-aliases;
}; };
storePaths = [ storePaths = [
# TODO: Limit this to the bare necessities # systemd tooling
"${cfg.package}/lib" "${cfg.package}/lib/systemd/systemd-fsck"
"${cfg.package}/lib/systemd/systemd-growfs"
"${cfg.package}/lib/systemd/systemd-hibernate-resume"
"${cfg.package}/lib/systemd/systemd-journald"
"${cfg.package}/lib/systemd/systemd-makefs"
"${cfg.package}/lib/systemd/systemd-modules-load"
"${cfg.package}/lib/systemd/systemd-random-seed"
"${cfg.package}/lib/systemd/systemd-remount-fs"
"${cfg.package}/lib/systemd/systemd-shutdown"
"${cfg.package}/lib/systemd/systemd-sulogin-shell"
"${cfg.package}/lib/systemd/systemd-sysctl"
# additional systemd directories
"${cfg.package}/lib/systemd/system-generators"
# utilities needed by systemd
"${cfg.package.util-linux}/bin/mount" "${cfg.package.util-linux}/bin/mount"
"${cfg.package.util-linux}/bin/umount" "${cfg.package.util-linux}/bin/umount"
"${cfg.package.util-linux}/bin/sulogin" "${cfg.package.util-linux}/bin/sulogin"
# so NSS can look up usernames # so NSS can look up usernames
"${pkgs.glibc}/lib/libnss_files.so" "${pkgs.glibc}/lib/libnss_files.so.2"
]; ] ++ jobScripts;
targets.initrd.aliases = ["default.target"]; targets.initrd.aliases = ["default.target"];
units = units =
@ -395,9 +426,6 @@ in {
(v: let n = escapeSystemdPath v.where; (v: let n = escapeSystemdPath v.where;
in nameValuePair "${n}.automount" (automountToUnit n v)) cfg.automounts); in nameValuePair "${n}.automount" (automountToUnit n v)) cfg.automounts);
services.emergency = mkIf (isBool cfg.emergencyAccess && cfg.emergencyAccess) {
environment.SYSTEMD_SULOGIN_FORCE = "1";
};
# The unit in /run/systemd/generator shadows the unit in # The unit in /run/systemd/generator shadows the unit in
# /etc/systemd/system, but will still apply drop-ins from # /etc/systemd/system, but will still apply drop-ins from
# /etc/systemd/system/foo.service.d/ # /etc/systemd/system/foo.service.d/
@ -412,6 +440,70 @@ in {
'')]; '')];
services."systemd-makefs@".unitConfig.IgnoreOnIsolate = true; services."systemd-makefs@".unitConfig.IgnoreOnIsolate = true;
services."systemd-growfs@".unitConfig.IgnoreOnIsolate = true; services."systemd-growfs@".unitConfig.IgnoreOnIsolate = true;
services.initrd-nixos-activation = {
after = [ "initrd-fs.target" ];
requiredBy = [ "initrd.target" ];
unitConfig.AssertPathExists = "/etc/initrd-release";
serviceConfig.Type = "oneshot";
description = "NixOS Activation";
script = /* bash */ ''
set -uo pipefail
export PATH="/bin:${cfg.package.util-linux}/bin"
# Figure out what closure to boot
closure=
for o in $(< /proc/cmdline); do
case $o in
init=*)
IFS== read -r -a initParam <<< "$o"
closure="$(dirname "''${initParam[1]}")"
;;
esac
done
# Sanity check
if [ -z "''${closure:-}" ]; then
echo 'No init= parameter on the kernel command line' >&2
exit 1
fi
# If we are not booting a NixOS closure (e.g. init=/bin/sh),
# we don't know what root to prepare so we don't do anything
if ! [ -x "/sysroot$closure/prepare-root" ]; then
echo "NEW_INIT=''${initParam[1]}" > /etc/switch-root.conf
echo "$closure does not look like a NixOS installation - not activating"
exit 0
fi
echo 'NEW_INIT=' > /etc/switch-root.conf
# We need to propagate /run for things like /run/booted-system
# and /run/current-system.
mkdir -p /sysroot/run
mount --bind /run /sysroot/run
# Initialize the system
export IN_NIXOS_SYSTEMD_STAGE1=true
exec chroot /sysroot $closure/prepare-root
'';
}; };
# This will either call systemctl with the new init as the last parameter (which
# is the case when not booting a NixOS system) or with an empty string, causing
# systemd to bypass its verification code that checks whether the next file is a systemd
# and using its compiled-in value
services.initrd-switch-root.serviceConfig = {
EnvironmentFile = "-/etc/switch-root.conf";
ExecStart = [
""
''systemctl --no-block switch-root /sysroot "''${NEW_INIT}"''
];
};
};
boot.kernelParams = lib.mkIf (config.boot.resumeDevice != "") [ "resume=${config.boot.resumeDevice}" ];
}; };
} }

View file

@ -60,15 +60,27 @@ with lib;
}; };
users.groups.systemd-timesync.gid = config.ids.gids.systemd-timesync; users.groups.systemd-timesync.gid = config.ids.gids.systemd-timesync;
system.activationScripts.systemd-timesyncd-migration = mkIf (versionOlder config.system.stateVersion "19.09") '' system.activationScripts.systemd-timesyncd-migration =
# workaround an issue of systemd-timesyncd not starting due to upstream systemd reverting their dynamic users changes # workaround an issue of systemd-timesyncd not starting due to upstream systemd reverting their dynamic users changes
# - https://github.com/NixOS/nixpkgs/pull/61321#issuecomment-492423742 # - https://github.com/NixOS/nixpkgs/pull/61321#issuecomment-492423742
# - https://github.com/systemd/systemd/issues/12131 # - https://github.com/systemd/systemd/issues/12131
mkIf (versionOlder config.system.stateVersion "19.09") ''
if [ -L /var/lib/systemd/timesync ]; then if [ -L /var/lib/systemd/timesync ]; then
rm /var/lib/systemd/timesync rm /var/lib/systemd/timesync
mv /var/lib/private/systemd/timesync /var/lib/systemd/timesync mv /var/lib/private/systemd/timesync /var/lib/systemd/timesync
fi fi
''; '';
system.activationScripts.systemd-timesyncd-init-clock =
# Ensure that we have some stored time to prevent systemd-timesyncd to
# resort back to the fallback time.
# If the file doesn't exist we assume that our current system clock is
# good enough to provide an initial value.
''
if ! [ -f /var/lib/systemd/timesync/clock ]; then
test -d /var/lib/systemd/timesync || mkdir -p /var/lib/systemd/timesync
touch /var/lib/systemd/timesync/clock
fi
'';
}; };
} }

View file

@ -642,41 +642,14 @@ in
}; };
scriptArgs = "%i"; scriptArgs = "%i";
path = [ pkgs.gawk cfgZfs.package ]; path = [ cfgZfs.package ];
# ZFS has no way of enumerating just devices in a pool in a way script = ''
# that 'zpool online -e' supports. Thus, we've implemented a
# bit of a strange approach of highlighting just devices.
# See: https://github.com/openzfs/zfs/issues/12505
script = let
# This UUID has been chosen at random and is to provide a
# collision-proof, predictable token to search for
magicIdentifier = "NIXOS-ZFS-ZPOOL-DEVICE-IDENTIFIER-37108bec-aff6-4b58-9e5e-53c7c9766f05";
zpoolScripts = pkgs.writeShellScriptBin "device-highlighter" ''
echo "${magicIdentifier}"
'';
in ''
pool=$1 pool=$1
echo "Expanding all devices for $pool." echo "Expanding all devices for $pool."
# Put our device-highlighter script it to the PATH ${pkgs.zpool-auto-expand-partitions}/bin/zpool_part_disks --automatically-grow "$pool"
export ZPOOL_SCRIPTS_PATH=${zpoolScripts}/bin
# Enable running our precisely specified zpool script as root
export ZPOOL_SCRIPTS_AS_ROOT=1
devices() (
zpool status -c device-highlighter "$pool" \
| awk '($2 == "ONLINE" && $6 == "${magicIdentifier}") { print $1; }'
)
for device in $(devices); do
echo "Attempting to expand $device of $pool..."
if ! zpool online -e "$pool" "$device"; then
echo "Failed to expand '$device' of '$pool'."
fi
done
''; '';
}; };
@ -701,8 +674,6 @@ in
RemainAfterExit = true; RemainAfterExit = true;
}; };
path = [ pkgs.gawk cfgZfs.package ];
script = '' script = ''
for pool in ${poolListProvider}; do for pool in ${poolListProvider}; do
systemctl start --no-block "zpool-expand@$pool" systemctl start --no-block "zpool-expand@$pool"

View file

@ -7,17 +7,22 @@ in {
options.services.lvm = { options.services.lvm = {
package = mkOption { package = mkOption {
type = types.package; type = types.package;
default = if cfg.dmeventd.enable then pkgs.lvm2_dmeventd else pkgs.lvm2; default = pkgs.lvm2;
internal = true; internal = true;
defaultText = literalExpression "pkgs.lvm2"; defaultText = literalExpression "pkgs.lvm2";
description = '' description = ''
This option allows you to override the LVM package that's used on the system This option allows you to override the LVM package that's used on the system
(udev rules, tmpfiles, systemd services). (udev rules, tmpfiles, systemd services).
Defaults to pkgs.lvm2, or pkgs.lvm2_dmeventd if dmeventd is enabled. Defaults to pkgs.lvm2, pkgs.lvm2_dmeventd if dmeventd or pkgs.lvm2_vdo if vdo is enabled.
''; '';
}; };
dmeventd.enable = mkEnableOption "the LVM dmevent daemon"; dmeventd.enable = mkEnableOption "the LVM dmevent daemon";
boot.thin.enable = mkEnableOption "support for booting from ThinLVs"; boot.thin.enable = mkEnableOption "support for booting from ThinLVs";
boot.vdo.enable = mkEnableOption "support for booting from VDOLVs";
};
options.boot.initrd.services.lvm.enable = (mkEnableOption "enable booting from LVM2 in the initrd") // {
visible = false;
}; };
config = mkMerge [ config = mkMerge [
@ -30,8 +35,13 @@ in {
environment.systemPackages = [ cfg.package ]; environment.systemPackages = [ cfg.package ];
systemd.packages = [ cfg.package ]; systemd.packages = [ cfg.package ];
# TODO: update once https://github.com/NixOS/nixpkgs/pull/93006 was merged
services.udev.packages = [ cfg.package.out ]; services.udev.packages = [ cfg.package.out ];
# We need lvm2 for the device-mapper rules
boot.initrd.services.udev.packages = lib.mkIf config.boot.initrd.services.lvm.enable [ cfg.package ];
# The device-mapper rules want to call tools from lvm2
boot.initrd.systemd.initrdBin = lib.mkIf config.boot.initrd.services.lvm.enable [ cfg.package ];
boot.initrd.services.udev.binPackages = lib.mkIf config.boot.initrd.services.lvm.enable [ cfg.package ];
}) })
(mkIf cfg.dmeventd.enable { (mkIf cfg.dmeventd.enable {
systemd.sockets."dm-event".wantedBy = [ "sockets.target" ]; systemd.sockets."dm-event".wantedBy = [ "sockets.target" ];
@ -40,18 +50,21 @@ in {
environment.etc."lvm/lvm.conf".text = '' environment.etc."lvm/lvm.conf".text = ''
dmeventd/executable = "${cfg.package}/bin/dmeventd" dmeventd/executable = "${cfg.package}/bin/dmeventd"
''; '';
services.lvm.package = mkDefault pkgs.lvm2_dmeventd;
}) })
(mkIf cfg.boot.thin.enable { (mkIf cfg.boot.thin.enable {
boot.initrd = { boot.initrd = {
kernelModules = [ "dm-snapshot" "dm-thin-pool" ]; kernelModules = [ "dm-snapshot" "dm-thin-pool" ];
extraUtilsCommands = '' systemd.initrdBin = lib.mkIf config.boot.initrd.services.lvm.enable [ pkgs.thin-provisioning-tools ];
extraUtilsCommands = mkIf (!config.boot.initrd.systemd.enable) ''
for BIN in ${pkgs.thin-provisioning-tools}/bin/*; do for BIN in ${pkgs.thin-provisioning-tools}/bin/*; do
copy_bin_and_libs $BIN copy_bin_and_libs $BIN
done done
''; '';
extraUtilsCommandsTest = '' extraUtilsCommandsTest = mkIf (!config.boot.initrd.systemd.enable) ''
ls ${pkgs.thin-provisioning-tools}/bin/ | grep -v pdata_tools | while read BIN; do ls ${pkgs.thin-provisioning-tools}/bin/ | grep -v pdata_tools | while read BIN; do
$out/bin/$(basename $BIN) --help > /dev/null $out/bin/$(basename $BIN) --help > /dev/null
done done
@ -61,9 +74,45 @@ in {
environment.etc."lvm/lvm.conf".text = concatMapStringsSep "\n" environment.etc."lvm/lvm.conf".text = concatMapStringsSep "\n"
(bin: "global/${bin}_executable = ${pkgs.thin-provisioning-tools}/bin/${bin}") (bin: "global/${bin}_executable = ${pkgs.thin-provisioning-tools}/bin/${bin}")
[ "thin_check" "thin_dump" "thin_repair" "cache_check" "cache_dump" "cache_repair" ]; [ "thin_check" "thin_dump" "thin_repair" "cache_check" "cache_dump" "cache_repair" ];
environment.systemPackages = [ pkgs.thin-provisioning-tools ];
})
(mkIf cfg.boot.vdo.enable {
boot = {
initrd = {
kernelModules = [ "kvdo" ];
systemd.initrdBin = lib.mkIf config.boot.initrd.services.lvm.enable [ pkgs.vdo ];
extraUtilsCommands = mkIf (!config.boot.initrd.systemd.enable)''
ls ${pkgs.vdo}/bin/ | grep -v adaptLVMVDO | while read BIN; do
copy_bin_and_libs ${pkgs.vdo}/bin/$BIN
done
'';
extraUtilsCommandsTest = mkIf (!config.boot.initrd.systemd.enable)''
ls ${pkgs.vdo}/bin/ | grep -v adaptLVMVDO | while read BIN; do
$out/bin/$(basename $BIN) --help > /dev/null
done
'';
};
extraModulePackages = [ config.boot.kernelPackages.kvdo ];
};
services.lvm.package = mkOverride 999 pkgs.lvm2_vdo; # this overrides mkDefault
environment.systemPackages = [ pkgs.vdo ];
}) })
(mkIf (cfg.dmeventd.enable || cfg.boot.thin.enable) { (mkIf (cfg.dmeventd.enable || cfg.boot.thin.enable) {
boot.initrd.preLVMCommands = '' boot.initrd.systemd.contents."/etc/lvm/lvm.conf".text = optionalString (config.boot.initrd.services.lvm.enable && cfg.boot.thin.enable) (concatMapStringsSep "\n"
(bin: "global/${bin}_executable = /bin/${bin}")
[ "thin_check" "thin_dump" "thin_repair" "cache_check" "cache_dump" "cache_repair" ]
) + "\n" + optionalString cfg.dmeventd.enable ''
dmeventd/executable = /bin/false
activation/monitoring = 0
'';
boot.initrd.preLVMCommands = mkIf (!config.boot.initrd.systemd.enable) ''
mkdir -p /etc/lvm mkdir -p /etc/lvm
cat << EOF >> /etc/lvm/lvm.conf cat << EOF >> /etc/lvm/lvm.conf
${optionalString cfg.boot.thin.enable ( ${optionalString cfg.boot.thin.enable (

View file

@ -21,7 +21,11 @@ with lib;
# way to select them anyway. # way to select them anyway.
boot.loader.grub.configurationLimit = 0; boot.loader.grub.configurationLimit = 0;
fileSystems."/".device = "/dev/disk/by-label/nixos"; fileSystems."/" = {
device = "/dev/disk/by-label/nixos";
fsType = "ext4";
autoResize = true;
};
# Allow root logins only using the SSH key that the user specified # Allow root logins only using the SSH key that the user specified
# at instance creation time, ping client connections to avoid timeouts # at instance creation time, ping client connections to avoid timeouts

View file

@ -344,6 +344,10 @@ in
restartIfChanged = false; restartIfChanged = false;
}; };
systemd.services.virtchd = {
path = [ pkgs.cloud-hypervisor ];
};
systemd.services.libvirt-guests = { systemd.services.libvirt-guests = {
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
path = with pkgs; [ coreutils gawk cfg.package ]; path = with pkgs; [ coreutils gawk cfg.package ];

View file

@ -853,8 +853,12 @@ in
(mkIf (pkgs.stdenv.isAarch32 || pkgs.stdenv.isAarch64) [ (mkIf (pkgs.stdenv.isAarch32 || pkgs.stdenv.isAarch64) [
"-device virtio-gpu-pci" "-device usb-ehci,id=usb0" "-device usb-kbd" "-device usb-tablet" "-device virtio-gpu-pci" "-device usb-ehci,id=usb0" "-device usb-kbd" "-device usb-tablet"
]) ])
(mkIf (!cfg.useBootLoader) [ (let
"-kernel ${config.system.build.toplevel}/kernel" alphaNumericChars = lowerChars ++ upperChars ++ (map toString (range 0 9));
# Replace all non-alphanumeric characters with underscores
sanitizeShellIdent = s: concatMapStrings (c: if builtins.elem c alphaNumericChars then c else "_") (stringToCharacters s);
in mkIf (!cfg.useBootLoader) [
"-kernel \${NIXPKGS_QEMU_KERNEL_${sanitizeShellIdent config.system.name}:-${config.system.build.toplevel}/kernel}"
"-initrd ${config.system.build.toplevel}/initrd" "-initrd ${config.system.build.toplevel}/initrd"
''-append "$(cat ${config.system.build.toplevel}/kernel-params) init=${config.system.build.toplevel}/init regInfo=${regInfo}/registration ${consoles} $QEMU_KERNEL_PARAMS"'' ''-append "$(cat ${config.system.build.toplevel}/kernel-params) init=${config.system.build.toplevel}/init regInfo=${regInfo}/registration ${consoles} $QEMU_KERNEL_PARAMS"''
]) ])

View file

@ -0,0 +1,31 @@
import ./make-test-python.nix ({ pkgs, ... }: rec {
name = "all-terminfo";
meta = with pkgs.lib.maintainers; {
maintainers = [ jkarlson ];
};
nodes.machine = { pkgs, config, lib, ... }:
let
infoFilter = name: drv:
let
o = builtins.tryEval drv;
in
o.success && lib.isDerivation o.value && o.value ? outputs && builtins.elem "terminfo" o.value.outputs;
terminfos = lib.filterAttrs infoFilter pkgs;
excludedTerminfos = lib.filterAttrs (_: drv: !(builtins.elem drv.terminfo config.environment.systemPackages)) terminfos;
includedOuts = lib.filterAttrs (_: drv: builtins.elem drv.out config.environment.systemPackages) terminfos;
in
{
environment = {
enableAllTerminfo = true;
etc."terminfo-missing".text = builtins.concatStringsSep "\n" (builtins.attrNames excludedTerminfos);
etc."terminfo-extra-outs".text = builtins.concatStringsSep "\n" (builtins.attrNames includedOuts);
};
};
testScript =
''
machine.fail("grep . /etc/terminfo-missing >&2")
machine.fail("grep . /etc/terminfo-extra-outs >&2")
'';
})

View file

@ -35,6 +35,7 @@ in
agate = handleTest ./web-servers/agate.nix {}; agate = handleTest ./web-servers/agate.nix {};
agda = handleTest ./agda.nix {}; agda = handleTest ./agda.nix {};
airsonic = handleTest ./airsonic.nix {}; airsonic = handleTest ./airsonic.nix {};
allTerminfo = handleTest ./all-terminfo.nix {};
amazon-init-shell = handleTest ./amazon-init-shell.nix {}; amazon-init-shell = handleTest ./amazon-init-shell.nix {};
apfs = handleTest ./apfs.nix {}; apfs = handleTest ./apfs.nix {};
apparmor = handleTest ./apparmor.nix {}; apparmor = handleTest ./apparmor.nix {};
@ -142,6 +143,7 @@ in
engelsystem = handleTest ./engelsystem.nix {}; engelsystem = handleTest ./engelsystem.nix {};
enlightenment = handleTest ./enlightenment.nix {}; enlightenment = handleTest ./enlightenment.nix {};
env = handleTest ./env.nix {}; env = handleTest ./env.nix {};
envoy = handleTest ./envoy.nix {};
ergo = handleTest ./ergo.nix {}; ergo = handleTest ./ergo.nix {};
ergochat = handleTest ./ergochat.nix {}; ergochat = handleTest ./ergochat.nix {};
etc = pkgs.callPackage ../modules/system/etc/test.nix { inherit evalMinimalConfig; }; etc = pkgs.callPackage ../modules/system/etc/test.nix { inherit evalMinimalConfig; };
@ -206,6 +208,7 @@ in
# hibernation. This test happens to work on x86_64-linux but # hibernation. This test happens to work on x86_64-linux but
# not on other platforms. # not on other platforms.
hibernate = handleTestOn ["x86_64-linux"] ./hibernate.nix {}; hibernate = handleTestOn ["x86_64-linux"] ./hibernate.nix {};
hibernate-systemd-stage-1 = handleTestOn ["x86_64-linux"] ./hibernate.nix { systemdStage1 = true; };
hitch = handleTest ./hitch {}; hitch = handleTest ./hitch {};
hledger-web = handleTest ./hledger-web.nix {}; hledger-web = handleTest ./hledger-web.nix {};
hocker-fetchdocker = handleTest ./hocker-fetchdocker {}; hocker-fetchdocker = handleTest ./hocker-fetchdocker {};
@ -274,6 +277,7 @@ in
login = handleTest ./login.nix {}; login = handleTest ./login.nix {};
logrotate = handleTest ./logrotate.nix {}; logrotate = handleTest ./logrotate.nix {};
loki = handleTest ./loki.nix {}; loki = handleTest ./loki.nix {};
lvm2 = handleTest ./lvm2 {};
lxd = handleTest ./lxd.nix {}; lxd = handleTest ./lxd.nix {};
lxd-image = handleTest ./lxd-image.nix {}; lxd-image = handleTest ./lxd-image.nix {};
lxd-nftables = handleTest ./lxd-nftables.nix {}; lxd-nftables = handleTest ./lxd-nftables.nix {};
@ -360,8 +364,9 @@ in
nginx-sandbox = handleTestOn ["x86_64-linux"] ./nginx-sandbox.nix {}; nginx-sandbox = handleTestOn ["x86_64-linux"] ./nginx-sandbox.nix {};
nginx-sso = handleTest ./nginx-sso.nix {}; nginx-sso = handleTest ./nginx-sso.nix {};
nginx-variants = handleTest ./nginx-variants.nix {}; nginx-variants = handleTest ./nginx-variants.nix {};
nifi = handleTestOn ["x86_64-linux"] ./web-apps/nifi.nix {};
nitter = handleTest ./nitter.nix {}; nitter = handleTest ./nitter.nix {};
nix-ld = handleTest ./nix-ld {}; nix-ld = handleTest ./nix-ld.nix {};
nix-serve = handleTest ./nix-serve.nix {}; nix-serve = handleTest ./nix-serve.nix {};
nix-serve-ssh = handleTest ./nix-serve-ssh.nix {}; nix-serve-ssh = handleTest ./nix-serve-ssh.nix {};
nixops = handleTest ./nixops/default.nix {}; nixops = handleTest ./nixops/default.nix {};
@ -396,10 +401,10 @@ in
pam-file-contents = handleTest ./pam/pam-file-contents.nix {}; pam-file-contents = handleTest ./pam/pam-file-contents.nix {};
pam-oath-login = handleTest ./pam/pam-oath-login.nix {}; pam-oath-login = handleTest ./pam/pam-oath-login.nix {};
pam-u2f = handleTest ./pam/pam-u2f.nix {}; pam-u2f = handleTest ./pam/pam-u2f.nix {};
pam-ussh = handleTest ./pam/pam-ussh.nix {};
pantalaimon = handleTest ./matrix/pantalaimon.nix {}; pantalaimon = handleTest ./matrix/pantalaimon.nix {};
pantheon = handleTest ./pantheon.nix {}; pantheon = handleTest ./pantheon.nix {};
paperless-ng = handleTest ./paperless-ng.nix {}; paperless = handleTest ./paperless.nix {};
paperless-ngx = handleTest ./paperless-ngx.nix {};
parsedmarc = handleTest ./parsedmarc {}; parsedmarc = handleTest ./parsedmarc {};
pdns-recursor = handleTest ./pdns-recursor.nix {}; pdns-recursor = handleTest ./pdns-recursor.nix {};
peerflix = handleTest ./peerflix.nix {}; peerflix = handleTest ./peerflix.nix {};
@ -515,6 +520,7 @@ in
systemd-confinement = handleTest ./systemd-confinement.nix {}; systemd-confinement = handleTest ./systemd-confinement.nix {};
systemd-cryptenroll = handleTest ./systemd-cryptenroll.nix {}; systemd-cryptenroll = handleTest ./systemd-cryptenroll.nix {};
systemd-escaping = handleTest ./systemd-escaping.nix {}; systemd-escaping = handleTest ./systemd-escaping.nix {};
systemd-initrd-mdraid = handleTest ./systemd-initrd-mdraid.nix {};
systemd-initrd-simple = handleTest ./systemd-initrd-simple.nix {}; systemd-initrd-simple = handleTest ./systemd-initrd-simple.nix {};
systemd-journal = handleTest ./systemd-journal.nix {}; systemd-journal = handleTest ./systemd-journal.nix {};
systemd-machinectl = handleTest ./systemd-machinectl.nix {}; systemd-machinectl = handleTest ./systemd-machinectl.nix {};

View file

@ -182,10 +182,6 @@ in
atopgpu = makeTest { atopgpu = makeTest {
name = "atop-atopgpu"; name = "atop-atopgpu";
nodes.machine = { nodes.machine = {
nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (getName pkg) [
"cudatoolkit"
];
programs.atop = { programs.atop = {
enable = true; enable = true;
atopgpu.enable = true; atopgpu.enable = true;
@ -205,10 +201,6 @@ in
everything = makeTest { everything = makeTest {
name = "atop-everthing"; name = "atop-everthing";
nodes.machine = { nodes.machine = {
nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (getName pkg) [
"cudatoolkit"
];
programs.atop = { programs.atop = {
enable = true; enable = true;
settings = { settings = {

View file

@ -7,7 +7,7 @@ import ./make-test-python.nix ({ pkgs, ... }:
let let
remoteSystem = remoteSystem =
if pkgs.system == "aarch64-linux" if pkgs.stdenv.hostPlatform.system == "aarch64-linux"
then "x86_64-linux" then "x86_64-linux"
else "aarch64-linux"; else "aarch64-linux";
@ -18,7 +18,7 @@ let
# NOTE: Since this file can't control where the test will be _run_ we don't # NOTE: Since this file can't control where the test will be _run_ we don't
# cross-compile _to_ a different system but _from_ a different system # cross-compile _to_ a different system but _from_ a different system
crossSystem = pkgs.system; crossSystem = pkgs.stdenv.hostPlatform.system;
}; };
hello1 = remoteCrossPkgs.dockerTools.buildImage { hello1 = remoteCrossPkgs.dockerTools.buildImage {

View file

@ -315,7 +315,7 @@ import ./make-test-python.nix ({ pkgs, ... }: {
"docker inspect ${pkgs.dockerTools.examples.cross.imageName} " "docker inspect ${pkgs.dockerTools.examples.cross.imageName} "
+ "| ${pkgs.jq}/bin/jq -r .[].Architecture" + "| ${pkgs.jq}/bin/jq -r .[].Architecture"
).strip() ).strip()
== "${if pkgs.system == "aarch64-linux" then "amd64" else "arm64"}" == "${if pkgs.stdenv.hostPlatform.system == "aarch64-linux" then "amd64" else "arm64"}"
) )
with subtest("buildLayeredImage doesn't dereference /nix/store symlink layers"): with subtest("buildLayeredImage doesn't dereference /nix/store symlink layers"):

View file

@ -0,0 +1,33 @@
import ./make-test-python.nix ({ pkgs, lib, ...} : {
name = "envoy";
meta = with pkgs.lib.maintainers; {
maintainers = [ cameronnemo ];
};
nodes.machine = { pkgs, ... }: {
services.envoy.enable = true;
services.envoy.settings = {
admin = {
access_log_path = "/dev/null";
address = {
socket_address = {
protocol = "TCP";
address = "127.0.0.1";
port_value = 9901;
};
};
};
static_resources = {
listeners = [];
clusters = [];
};
};
};
testScript = ''
machine.start()
machine.wait_for_unit("envoy.service")
machine.wait_for_open_port(9901)
machine.wait_until_succeeds("curl -fsS localhost:9901/ready")
'';
})

View file

@ -44,6 +44,6 @@ in
{ nodes, ... }: { nodes, ... }:
'' ''
start_all() start_all()
node1.succeed("${fenicsScript}") fenicsnode.succeed("${fenicsScript}")
''; '';
}) })

View file

@ -3,6 +3,7 @@
{ system ? builtins.currentSystem { system ? builtins.currentSystem
, config ? {} , config ? {}
, pkgs ? import ../.. { inherit system config; } , pkgs ? import ../.. { inherit system config; }
, systemdStage1 ? false
}: }:
with import ../lib/testing-python.nix { inherit system pkgs; }; with import ../lib/testing-python.nix { inherit system pkgs; };
@ -29,6 +30,11 @@ let
"/".device = "/dev/vda2"; "/".device = "/dev/vda2";
}; };
swapDevices = mkOverride 0 [ { device = "/dev/vda1"; } ]; swapDevices = mkOverride 0 [ { device = "/dev/vda1"; } ];
boot.resumeDevice = mkIf systemdStage1 "/dev/vda1";
boot.initrd.systemd = mkIf systemdStage1 {
enable = true;
emergencyAccess = true;
};
}; };
installedSystem = (import ../lib/eval-config.nix { installedSystem = (import ../lib/eval-config.nix {
inherit system; inherit system;

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