Project import generated by Copybara.
GitOrigin-RevId: 395879c28386e1abf20c7ecacd45880759548391
This commit is contained in:
parent
576896970a
commit
3cbfd2b52c
1939 changed files with 41662 additions and 38968 deletions
6
third_party/nixpkgs/.github/CODEOWNERS
vendored
6
third_party/nixpkgs/.github/CODEOWNERS
vendored
|
@ -39,7 +39,7 @@
|
|||
/pkgs/top-level/stage.nix @nbp @Ericson2314 @matthewbauer
|
||||
/pkgs/top-level/splice.nix @Ericson2314 @matthewbauer
|
||||
/pkgs/top-level/release-cross.nix @Ericson2314 @matthewbauer
|
||||
/pkgs/stdenv/generic @Ericson2314 @matthewbauer
|
||||
/pkgs/stdenv/generic @Ericson2314 @matthewbauer @cab404
|
||||
/pkgs/stdenv/cross @Ericson2314 @matthewbauer
|
||||
/pkgs/build-support/cc-wrapper @Ericson2314 @orivej
|
||||
/pkgs/build-support/bintools-wrapper @Ericson2314 @orivej
|
||||
|
@ -219,9 +219,9 @@
|
|||
# Podman, CRI-O modules and related
|
||||
/nixos/modules/virtualisation/containers.nix @NixOS/podman @zowoq @adisbladis
|
||||
/nixos/modules/virtualisation/cri-o.nix @NixOS/podman @zowoq @adisbladis
|
||||
/nixos/modules/virtualisation/podman.nix @NixOS/podman @zowoq @adisbladis
|
||||
/nixos/modules/virtualisation/podman @NixOS/podman @zowoq @adisbladis
|
||||
/nixos/tests/cri-o.nix @NixOS/podman @zowoq @adisbladis
|
||||
/nixos/tests/podman.nix @NixOS/podman @zowoq @adisbladis
|
||||
/nixos/tests/podman @NixOS/podman @zowoq @adisbladis
|
||||
|
||||
# Docker tools
|
||||
/pkgs/build-support/docker @roberth @utdemir
|
||||
|
|
|
@ -31,7 +31,8 @@ jobs:
|
|||
- uses: cachix/install-nix-action@v16
|
||||
with:
|
||||
# nixpkgs commit is pinned so that it doesn't break
|
||||
nix_path: nixpkgs=https://github.com/NixOS/nixpkgs/archive/f93ecc4f6bc60414d8b73dbdf615ceb6a2c604df.tar.gz
|
||||
# editorconfig-checker 2.4.0
|
||||
nix_path: nixpkgs=https://github.com/NixOS/nixpkgs/archive/c473cc8714710179df205b153f4e9fa007107ff9.tar.gz
|
||||
- name: install editorconfig-checker
|
||||
run: nix-env -iA editorconfig-checker -f '<nixpkgs>'
|
||||
- name: Checking EditorConfig
|
||||
|
|
|
@ -72,7 +72,18 @@ The `dotnetCorePackages.sdk` contains both a runtime and the full sdk of a given
|
|||
To package Dotnet applications, you can use `buildDotnetModule`. This has similar arguments to `stdenv.mkDerivation`, with the following additions:
|
||||
|
||||
* `projectFile` has to be used for specifying the dotnet project file relative to the source root. These usually have `.sln` or `.csproj` file extensions. This can be an array of multiple projects as well.
|
||||
* `nugetDeps` has to be used to specify the NuGet dependency file. Unfortunately, these cannot be deterministically fetched without a lockfile. This file should be generated using `nuget-to-nix` tool, which is available in nixpkgs.
|
||||
* `nugetDeps` has to be used to specify the NuGet dependency file. Unfortunately, these cannot be deterministically fetched without a lockfile. A script to fetch these is available as `passthru.fetch-deps`. This file can also be generated manually using `nuget-to-nix` tool, which is available in nixpkgs.
|
||||
* `packNupkg` is used to pack project as a `nupkg`, and installs it to `$out/share`. If set to `true`, the derivation can be used as a dependency for another dotnet project by adding it to `projectReferences`.
|
||||
* `projectReferences` can be used to resolve `ProjectReference` project items. Referenced projects can be packed with `buildDotnetModule` by setting the `packNupkg = true` attribute and passing a list of derivations to `projectReferences`. Since we are sharing referenced projects as NuGets they must be added to csproj/fsproj files as `PackageReference` as well.
|
||||
For example, your project has a local dependency:
|
||||
```xml
|
||||
<ProjectReference Include="../foo/bar.fsproj" />
|
||||
```
|
||||
To enable discovery through `projectReferences` you would need to add:
|
||||
```xml
|
||||
<ProjectReference Include="../foo/bar.fsproj" />
|
||||
<PackageReference Include="bar" Version="*" Condition=" '$(ContinuousIntegrationBuild)'=='true' "/>
|
||||
```
|
||||
* `executables` is used to specify which executables get wrapped to `$out/bin`, relative to `$out/lib/$pname`. If this is unset, all executables generated will get installed. If you do not want to install any, set this to `[]`.
|
||||
* `runtimeDeps` is used to wrap libraries into `LD_LIBRARY_PATH`. This is how dotnet usually handles runtime dependencies.
|
||||
* `buildType` is used to change the type of build. Possible values are `Release`, `Debug`, etc. By default, this is set to `Release`.
|
||||
|
@ -83,22 +94,29 @@ To package Dotnet applications, you can use `buildDotnetModule`. This has simila
|
|||
* `disabledTests` is used to disable running specific unit tests. This gets passed as: `dotnet test --filter "FullyQualifiedName!={}"`, to ensure compatibility with all unit test frameworks.
|
||||
* `dotnetRestoreFlags` can be used to pass flags to `dotnet restore`.
|
||||
* `dotnetBuildFlags` can be used to pass flags to `dotnet build`.
|
||||
* `dotnetTestFlags` can be used to pass flags to `dotnet test`.
|
||||
* `dotnetTestFlags` can be used to pass flags to `dotnet test`. Used only if `doCheck` is set to `true`.
|
||||
* `dotnetInstallFlags` can be used to pass flags to `dotnet install`.
|
||||
* `dotnetPackFlags` can be used to pass flags to `dotnet pack`. Used only if `packNupkg` is set to `true`.
|
||||
* `dotnetFlags` can be used to pass flags to all of the above phases.
|
||||
|
||||
When packaging a new application, you need to fetch it's dependencies. You can set `nugetDeps` to an empty string to make the derivation temporarily evaluate, and then run `nix-build -A package.passthru.fetch-deps` to generate it's dependency fetching script. After running the script, you should have the location of the generated lockfile printed to the console. This can be copied to a stable directory. Note that if either `projectFile` or `nugetDeps` are unset, this script cannot be generated!
|
||||
|
||||
Here is an example `default.nix`, using some of the previously discussed arguments:
|
||||
```nix
|
||||
{ lib, buildDotnetModule, dotnetCorePackages, ffmpeg }:
|
||||
|
||||
buildDotnetModule rec {
|
||||
let
|
||||
referencedProject = import ../../bar { ... };
|
||||
in buildDotnetModule rec {
|
||||
pname = "someDotnetApplication";
|
||||
version = "0.1";
|
||||
|
||||
src = ./.;
|
||||
|
||||
projectFile = "src/project.sln";
|
||||
nugetDeps = ./deps.nix; # File generated with `nuget-to-nix path/to/src > deps.nix`.
|
||||
nugetDeps = ./deps.nix; # File generated with `nix-build -A package.passthru.fetch-deps`.
|
||||
|
||||
projectReferences = [ referencedProject ]; # `referencedProject` must contain `nupkg` in the folder structure.
|
||||
|
||||
dotnet-sdk = dotnetCorePackages.sdk_3_1;
|
||||
dotnet-runtime = dotnetCorePackages.net_5_0;
|
||||
|
@ -107,6 +125,8 @@ buildDotnetModule rec {
|
|||
executables = [ "foo" ]; # This wraps "$out/lib/$pname/foo" to `$out/bin/foo`.
|
||||
executables = []; # Don't install any executables.
|
||||
|
||||
packNupkg = true; # This packs the project as "foo-0.1.nupkg" at `$out/share`.
|
||||
|
||||
runtimeDeps = [ ffmpeg ]; # This will wrap ffmpeg's library path into `LD_LIBRARY_PATH`.
|
||||
}
|
||||
```
|
||||
|
|
|
@ -92,7 +92,7 @@ For convenience, it also adds `dconf.lib` for a GIO module implementing a GSetti
|
|||
|
||||
- []{#ssec-gnome-hooks-glib} `glib` setup hook will populate `GSETTINGS_SCHEMAS_PATH` and then `wrapGAppsHook` will prepend it to `XDG_DATA_DIRS`.
|
||||
|
||||
- []{#ssec-gnome-hooks-gdk-pixbuf} `gdk-pixbuf` setup hook will populate `GDK_PIXBUF_MODULE_FILE` with the path to biggest `loaders.cache` file from the dependencies containing [GdkPixbuf loaders](ssec-gnome-gdk-pixbuf-loaders). This works fine when there are only two packages containing loaders (`gdk-pixbuf` and e.g. `librsvg`) – it will choose the second one, reasonably expecting that it will be bigger since it describes extra loader in addition to the default ones. But when there are more than two loader packages, this logic will break. One possible solution would be constructing a custom cache file for each package containing a program like `services/x11/gdk-pixbuf.nix` NixOS module does. `wrapGAppsHook` copies the `GDK_PIXBUF_MODULE_FILE` environment variable into the produced wrapper.
|
||||
- []{#ssec-gnome-hooks-gdk-pixbuf} `gdk-pixbuf` setup hook will populate `GDK_PIXBUF_MODULE_FILE` with the path to biggest `loaders.cache` file from the dependencies containing [GdkPixbuf loaders](#ssec-gnome-gdk-pixbuf-loaders). This works fine when there are only two packages containing loaders (`gdk-pixbuf` and e.g. `librsvg`) – it will choose the second one, reasonably expecting that it will be bigger since it describes extra loader in addition to the default ones. But when there are more than two loader packages, this logic will break. One possible solution would be constructing a custom cache file for each package containing a program like `services/x11/gdk-pixbuf.nix` NixOS module does. `wrapGAppsHook` copies the `GDK_PIXBUF_MODULE_FILE` environment variable into the produced wrapper.
|
||||
|
||||
- []{#ssec-gnome-hooks-gtk-drop-icon-theme-cache} One of `gtk3`’s setup hooks will remove `icon-theme.cache` files from package’s icon theme directories to avoid conflicts. Icon theme packages should prevent this with `dontDropIconThemeCache = true;`.
|
||||
|
||||
|
|
|
@ -128,7 +128,7 @@ Let's present the luarocks way first and the manual one in a second time.
|
|||
|
||||
### Packaging a library on luarocks {#packaging-a-library-on-luarocks}
|
||||
|
||||
[Luarocks.org](www.luarocks.org) is the main repository of lua packages.
|
||||
[Luarocks.org](https://luarocks.org/) is the main repository of lua packages.
|
||||
The site proposes two types of packages, the rockspec and the src.rock
|
||||
(equivalent of a [rockspec](https://github.com/luarocks/luarocks/wiki/Rockspec-format) but with the source).
|
||||
These packages can have different build types such as `cmake`, `builtin` etc .
|
||||
|
|
|
@ -995,18 +995,18 @@ called with `callPackage` and passed `python` or `pythonPackages` (possibly
|
|||
specifying an interpreter version), like this:
|
||||
|
||||
```nix
|
||||
{ lib, python3Packages }:
|
||||
{ lib, python3 }:
|
||||
|
||||
python3Packages.buildPythonApplication rec {
|
||||
python3.pkgs.buildPythonApplication rec {
|
||||
pname = "luigi";
|
||||
version = "2.7.9";
|
||||
|
||||
src = python3Packages.fetchPypi {
|
||||
src = python3.pkgs.fetchPypi {
|
||||
inherit pname version;
|
||||
sha256 = "035w8gqql36zlan0xjrzz9j4lh9hs0qrsgnbyw07qs7lnkvbdv9x";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = with python3Packages; [ tornado_4 python-daemon ];
|
||||
propagatedBuildInputs = with python3.pkgs; [ tornado python-daemon ];
|
||||
|
||||
meta = with lib; {
|
||||
...
|
||||
|
@ -1632,3 +1632,25 @@ would be:
|
|||
```ShellSession
|
||||
$ maintainers/scripts/update-python-libraries --target minor --commit --use-pkgs-prefix pkgs/development/python-modules/**/default.nix
|
||||
```
|
||||
|
||||
## CPython Update Schedule
|
||||
|
||||
With [PEP 602](https://www.python.org/dev/peps/pep-0602/), CPython now
|
||||
follows a yearly release cadence. In nixpkgs, all supported interpreters
|
||||
are made available, but only the most recent two
|
||||
interpreters package sets are built; this is a compromise between being
|
||||
the latest interpreter, and what the majority of the Python packages support.
|
||||
|
||||
New CPython interpreters are released in October. Generally, it takes some
|
||||
time for the majority of active Python projects to support the latest stable
|
||||
interpreter. To help ease the migration for Nixpkgs users
|
||||
between Python interpreters the schedule below will be used:
|
||||
|
||||
| When | Event |
|
||||
| --- | --- |
|
||||
| After YY.11 Release | Bump CPython package set window. The latest and previous latest stable should now be built. |
|
||||
| After YY.05 Release | Bump default CPython interpreter to latest stable. |
|
||||
|
||||
In practice, this means that the Python community will have had a stable interpreter
|
||||
for ~2 months before attempting to update the package set. And this will
|
||||
allow for ~7 months for Python applications to support the latest interpreter.
|
||||
|
|
|
@ -201,6 +201,19 @@ $ nix-shell --run 'ruby -rpg -e "puts PG.library_version"'
|
|||
|
||||
Of course for this use-case one could also use overlays since the configuration for `pg` depends on the `postgresql` alias, but for demonstration purposes this has to suffice.
|
||||
|
||||
### Platform-specific gems
|
||||
|
||||
Right now, bundix has some issues with pre-built, platform-specific gems: [bundix PR #68](https://github.com/nix-community/bundix/pull/68).
|
||||
Until this is solved, you can tell bundler to not use platform-specific gems and instead build them from source each time:
|
||||
- globally (will be set in `~/.config/.bundle/config`):
|
||||
```shell
|
||||
$ bundle config set force_ruby_platform true
|
||||
```
|
||||
- locally (will be set in `<project-root>/.bundle/config`):
|
||||
```shell
|
||||
$ bundle config set --local force_ruby_platform true
|
||||
```
|
||||
|
||||
### Adding a gem to the default gemset {#adding-a-gem-to-the-default-gemset}
|
||||
|
||||
Now that you know how to get a working Ruby environment with Nix, it's time to go forward and start actually developing with Ruby. We will first have a look at how Ruby gems are packaged on Nix. Then, we will look at how you can use development mode with your code.
|
||||
|
|
|
@ -293,7 +293,7 @@ Test flags, e.g., `--package foo`, can be passed to `cargo test` via the
|
|||
|
||||
Another attribute, called `checkFlags`, is used to pass arguments to the test
|
||||
binary itself, as stated
|
||||
(here)[https://doc.rust-lang.org/cargo/commands/cargo-test.html].
|
||||
[here](https://doc.rust-lang.org/cargo/commands/cargo-test.html).
|
||||
|
||||
#### Tests relying on the structure of the `target/` directory {#tests-relying-on-the-structure-of-the-target-directory}
|
||||
|
||||
|
|
|
@ -309,9 +309,9 @@ Sample output2:
|
|||
|
||||
## Adding new plugins to nixpkgs {#adding-new-plugins-to-nixpkgs}
|
||||
|
||||
Nix expressions for Vim plugins are stored in [pkgs/misc/vim-plugins](/pkgs/misc/vim-plugins). For the vast majority of plugins, Nix expressions are automatically generated by running [`./update.py`](/pkgs/misc/vim-plugins/update.py). This creates a [generated.nix](/pkgs/misc/vim-plugins/generated.nix) file based on the plugins listed in [vim-plugin-names](/pkgs/misc/vim-plugins/vim-plugin-names). Plugins are listed in alphabetical order in `vim-plugin-names` using the format `[github username]/[repository]@[gitref]`. For example https://github.com/scrooloose/nerdtree becomes `scrooloose/nerdtree`.
|
||||
Nix expressions for Vim plugins are stored in [pkgs/misc/vim-plugins](https://github.com/NixOS/nixpkgs/tree/master/pkgs/misc/vim-plugins). For the vast majority of plugins, Nix expressions are automatically generated by running [`./update.py`](https://github.com/NixOS/nixpkgs/blob/master/pkgs/misc/vim-plugins/update.py). This creates a [generated.nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/misc/vim-plugins/generated.nix) file based on the plugins listed in [vim-plugin-names](https://github.com/NixOS/nixpkgs/blob/master/pkgs/misc/vim-plugins/vim-plugin-names). Plugins are listed in alphabetical order in `vim-plugin-names` using the format `[github username]/[repository]@[gitref]`. For example https://github.com/scrooloose/nerdtree becomes `scrooloose/nerdtree`.
|
||||
|
||||
Some plugins require overrides in order to function properly. Overrides are placed in [overrides.nix](/pkgs/misc/vim-plugins/overrides.nix). Overrides are most often required when a plugin requires some dependencies, or extra steps are required during the build process. For example `deoplete-fish` requires both `deoplete-nvim` and `vim-fish`, and so the following override was added:
|
||||
Some plugins require overrides in order to function properly. Overrides are placed in [overrides.nix](https://github.com/NixOS/nixpkgs/blob/master/pkgs/misc/vim-plugins/overrides.nix). Overrides are most often required when a plugin requires some dependencies, or extra steps are required during the build process. For example `deoplete-fish` requires both `deoplete-nvim` and `vim-fish`, and so the following override was added:
|
||||
|
||||
```nix
|
||||
deoplete-fish = super.deoplete-fish.overrideAttrs(old: {
|
||||
|
|
12
third_party/nixpkgs/doc/stdenv/stdenv.chapter.md
vendored
12
third_party/nixpkgs/doc/stdenv/stdenv.chapter.md
vendored
|
@ -796,7 +796,7 @@ The standard environment provides a number of useful functions.
|
|||
|
||||
### `makeWrapper` \<executable\> \<wrapperfile\> \<args\> {#fun-makeWrapper}
|
||||
|
||||
Constructs a wrapper for a program with various possible arguments. For example:
|
||||
Constructs a wrapper for a program with various possible arguments. It is defined as part of 2 setup-hooks named `makeWrapper` and `makeBinaryWrapper` that implement the same bash functions. Hence, to use it you have to add `makeWrapper` to your `nativeBuildInputs`. Here's an example usage:
|
||||
|
||||
```bash
|
||||
# adds `FOOBAR=baz` to `$out/bin/foo`’s environment
|
||||
|
@ -808,9 +808,11 @@ makeWrapper $out/bin/foo $wrapperfile --set FOOBAR baz
|
|||
makeWrapper $out/bin/foo $wrapperfile --prefix PATH : ${lib.makeBinPath [ hello git ]}
|
||||
```
|
||||
|
||||
There’s many more kinds of arguments, they are documented in `nixpkgs/pkgs/build-support/setup-hooks/make-wrapper.sh`.
|
||||
There’s many more kinds of arguments, they are documented in `nixpkgs/pkgs/build-support/setup-hooks/make-wrapper.sh` for the `makeWrapper` implementation and in `nixpkgs/pkgs/build-support/setup-hooks/make-binary-wrapper.sh` for the `makeBinaryWrapper` implementation.
|
||||
|
||||
`wrapProgram` is a convenience function you probably want to use most of the time.
|
||||
`wrapProgram` is a convenience function you probably want to use most of the time, implemented by both `makeWrapper` and `makeBinaryWrapper`.
|
||||
|
||||
Using the `makeBinaryWrapper` implementation is usually preferred, as it creates a tiny _compiled_ wrapper executable, that can be used as a shebang interpreter. This is needed mostly on Darwin, where shebangs cannot point to scripts, [due to a limitation with the `execve`-syscall](https://stackoverflow.com/questions/67100831/macos-shebang-with-absolute-path-not-working). Compiled wrappers generated by `makeBinaryWrapper` can be inspected with `less <path-to-wrapper>` - by scrolling past the binary data you should be able to see the shell command that generated the executable and there see the environment variables that were injected into the wrapper.
|
||||
|
||||
### `substitute` \<infile\> \<outfile\> \<subs\> {#fun-substitute}
|
||||
|
||||
|
@ -885,9 +887,9 @@ someVar=$(stripHash $name)
|
|||
|
||||
### `wrapProgram` \<executable\> \<makeWrapperArgs\> {#fun-wrapProgram}
|
||||
|
||||
Convenience function for `makeWrapper` that automatically creates a sane wrapper file. It takes all the same arguments as `makeWrapper`, except for `--argv0`.
|
||||
Convenience function for `makeWrapper` that replaces `<\executable\>` with a wrapper that executes the original program. It takes all the same arguments as `makeWrapper`, except for `--inherit-argv0` (used by the `makeBinaryWrapper` implementation) and `--argv0` (used by both `makeWrapper` and `makeBinaryWrapper` wrapper implementations).
|
||||
|
||||
It cannot be applied multiple times, since it will overwrite the wrapper file.
|
||||
If you will apply it multiple times, it will overwrite the wrapper file and you will end up with double wrapping, which should be avoided.
|
||||
|
||||
## Package setup hooks {#ssec-setup-hooks}
|
||||
|
||||
|
|
2
third_party/nixpkgs/lib/default.nix
vendored
2
third_party/nixpkgs/lib/default.nix
vendored
|
@ -105,7 +105,7 @@ let
|
|||
makeScope makeScopeWithSplicing;
|
||||
inherit (self.meta) addMetaAttrs dontDistribute setName updateName
|
||||
appendToName mapDerivationAttrset setPrio lowPrio lowPrioSet hiPrio
|
||||
hiPrioSet;
|
||||
hiPrioSet getLicenseFromSpdxId;
|
||||
inherit (self.sources) pathType pathIsDirectory cleanSourceFilter
|
||||
cleanSource sourceByRegex sourceFilesBySuffices
|
||||
commitIdFromGitRepo cleanSourceWith pathHasContext
|
||||
|
|
27
third_party/nixpkgs/lib/meta.nix
vendored
27
third_party/nixpkgs/lib/meta.nix
vendored
|
@ -99,4 +99,31 @@ rec {
|
|||
availableOn = platform: pkg:
|
||||
lib.any (platformMatch platform) pkg.meta.platforms &&
|
||||
lib.all (elem: !platformMatch platform elem) (pkg.meta.badPlatforms or []);
|
||||
|
||||
/* Get the corresponding attribute in lib.licenses
|
||||
from the SPDX ID.
|
||||
For SPDX IDs, see
|
||||
https://spdx.org/licenses
|
||||
|
||||
Type:
|
||||
getLicenseFromSpdxId :: str -> AttrSet
|
||||
|
||||
Example:
|
||||
lib.getLicenseFromSpdxId "MIT" == lib.licenses.mit
|
||||
=> true
|
||||
lib.getLicenseFromSpdxId "mIt" == lib.licenses.mit
|
||||
=> true
|
||||
lib.getLicenseFromSpdxId "MY LICENSE"
|
||||
=> trace: warning: getLicenseFromSpdxId: No license matches the given SPDX ID: MY LICENSE
|
||||
=> { shortName = "MY LICENSE"; }
|
||||
*/
|
||||
getLicenseFromSpdxId =
|
||||
let
|
||||
spdxLicenses = lib.mapAttrs (id: ls: assert lib.length ls == 1; builtins.head ls)
|
||||
(lib.groupBy (l: lib.toLower l.spdxId) (lib.filter (l: l ? spdxId) (lib.attrValues lib.licenses)));
|
||||
in licstr:
|
||||
spdxLicenses.${ lib.toLower licstr } or (
|
||||
lib.warn "getLicenseFromSpdxId: No license matches the given SPDX ID: ${licstr}"
|
||||
{ shortName = licstr; }
|
||||
);
|
||||
}
|
||||
|
|
55
third_party/nixpkgs/lib/modules.nix
vendored
55
third_party/nixpkgs/lib/modules.nix
vendored
|
@ -13,8 +13,6 @@ let
|
|||
elem
|
||||
filter
|
||||
findFirst
|
||||
flip
|
||||
foldl
|
||||
foldl'
|
||||
getAttrFromPath
|
||||
head
|
||||
|
@ -101,9 +99,31 @@ rec {
|
|||
check ? true
|
||||
}:
|
||||
let
|
||||
withWarnings = x:
|
||||
lib.warnIf (evalModulesArgs?args) "The args argument to evalModules is deprecated. Please set config._module.args instead."
|
||||
lib.warnIf (evalModulesArgs?check) "The check argument to evalModules is deprecated. Please set config._module.check instead."
|
||||
x;
|
||||
|
||||
legacyModules =
|
||||
optional (evalModulesArgs?args) {
|
||||
config = {
|
||||
_module.args = args;
|
||||
};
|
||||
}
|
||||
++ optional (evalModulesArgs?check) {
|
||||
config = {
|
||||
_module.check = mkDefault check;
|
||||
};
|
||||
};
|
||||
regularModules = modules ++ legacyModules;
|
||||
|
||||
# This internal module declare internal options under the `_module'
|
||||
# attribute. These options are fragile, as they are used by the
|
||||
# module system to change the interpretation of modules.
|
||||
#
|
||||
# When extended with extendModules or moduleType, a fresh instance of
|
||||
# this module is used, to avoid conflicts and allow chaining of
|
||||
# extendModules.
|
||||
internalModule = rec {
|
||||
_file = ./modules.nix;
|
||||
|
||||
|
@ -125,7 +145,7 @@ rec {
|
|||
_module.check = mkOption {
|
||||
type = types.bool;
|
||||
internal = true;
|
||||
default = check;
|
||||
default = true;
|
||||
description = "Whether to check whether all option definitions have matching declarations.";
|
||||
};
|
||||
|
||||
|
@ -151,14 +171,14 @@ rec {
|
|||
_module.args = {
|
||||
inherit extendModules;
|
||||
moduleType = type;
|
||||
} // args;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
merged =
|
||||
let collected = collectModules
|
||||
(specialArgs.modulesPath or "")
|
||||
(modules ++ [ internalModule ])
|
||||
(regularModules ++ [ internalModule ])
|
||||
({ inherit lib options config specialArgs; } // specialArgs);
|
||||
in mergeModules prefix (reverseList collected);
|
||||
|
||||
|
@ -222,7 +242,7 @@ rec {
|
|||
prefix ? [],
|
||||
}:
|
||||
evalModules (evalModulesArgs // {
|
||||
modules = evalModulesArgs.modules ++ modules;
|
||||
modules = regularModules ++ modules;
|
||||
specialArgs = evalModulesArgs.specialArgs or {} // specialArgs;
|
||||
prefix = extendArgs.prefix or evalModulesArgs.prefix;
|
||||
});
|
||||
|
@ -231,7 +251,7 @@ rec {
|
|||
inherit modules specialArgs;
|
||||
};
|
||||
|
||||
result = {
|
||||
result = withWarnings {
|
||||
options = checked options;
|
||||
config = checked (removeAttrs config [ "_module" ]);
|
||||
_module = checked (config._module);
|
||||
|
@ -452,7 +472,7 @@ rec {
|
|||
[{ inherit (module) file; inherit value; }]
|
||||
) configs;
|
||||
|
||||
resultsByName = flip mapAttrs declsByName (name: decls:
|
||||
resultsByName = mapAttrs (name: decls:
|
||||
# We're descending into attribute ‘name’.
|
||||
let
|
||||
loc = prefix ++ [name];
|
||||
|
@ -473,7 +493,7 @@ rec {
|
|||
in
|
||||
throw "The option `${showOption loc}' in `${firstOption._file}' is a prefix of options in `${firstNonOption._file}'."
|
||||
else
|
||||
mergeModules' loc decls defns);
|
||||
mergeModules' loc decls defns) declsByName;
|
||||
|
||||
matchedOptions = mapAttrs (n: v: v.matchedOptions) resultsByName;
|
||||
|
||||
|
@ -487,7 +507,14 @@ rec {
|
|||
inherit matchedOptions;
|
||||
|
||||
# Transforms unmatchedDefnsByName into a list of definitions
|
||||
unmatchedDefns = concatLists (mapAttrsToList (name: defs:
|
||||
unmatchedDefns =
|
||||
if configs == []
|
||||
then
|
||||
# When no config values exist, there can be no unmatched config, so
|
||||
# we short circuit and avoid evaluating more _options_ than necessary.
|
||||
[]
|
||||
else
|
||||
concatLists (mapAttrsToList (name: defs:
|
||||
map (def: def // {
|
||||
# Set this so we know when the definition first left unmatched territory
|
||||
prefix = [name] ++ (def.prefix or []);
|
||||
|
@ -587,6 +614,8 @@ rec {
|
|||
definitions = map (def: def.value) res.defsFinal;
|
||||
files = map (def: def.file) res.defsFinal;
|
||||
inherit (res) isDefined;
|
||||
# This allows options to be correctly displayed using `${options.path.to.it}`
|
||||
__toString = _: showOption loc;
|
||||
};
|
||||
|
||||
# Merge definitions of a value of a given type.
|
||||
|
@ -906,7 +935,7 @@ rec {
|
|||
mkMergedOptionModule = from: to: mergeFn:
|
||||
{ config, options, ... }:
|
||||
{
|
||||
options = foldl recursiveUpdate {} (map (path: setAttrByPath path (mkOption {
|
||||
options = foldl' recursiveUpdate {} (map (path: setAttrByPath path (mkOption {
|
||||
visible = false;
|
||||
# To use the value in mergeFn without triggering errors
|
||||
default = "_mkMergedOptionModule";
|
||||
|
@ -1010,7 +1039,7 @@ rec {
|
|||
|
||||
/* Use this function to import a JSON file as NixOS configuration.
|
||||
|
||||
importJSON -> path -> attrs
|
||||
modules.importJSON :: path -> attrs
|
||||
*/
|
||||
importJSON = file: {
|
||||
_file = file;
|
||||
|
@ -1019,7 +1048,7 @@ rec {
|
|||
|
||||
/* Use this function to import a TOML file as NixOS configuration.
|
||||
|
||||
importTOML -> path -> attrs
|
||||
modules.importTOML :: path -> attrs
|
||||
*/
|
||||
importTOML = file: {
|
||||
_file = file;
|
||||
|
|
4
third_party/nixpkgs/lib/systems/doubles.nix
vendored
4
third_party/nixpkgs/lib/systems/doubles.nix
vendored
|
@ -39,8 +39,8 @@ let
|
|||
"riscv32-netbsd" "riscv64-netbsd" "x86_64-netbsd"
|
||||
|
||||
# none
|
||||
"aarch64-none" "arm-none" "armv6l-none" "avr-none" "i686-none"
|
||||
"msp430-none" "or1k-none" "m68k-none" "powerpc-none"
|
||||
"aarch64_be-none" "aarch64-none" "arm-none" "armv6l-none" "avr-none" "i686-none"
|
||||
"msp430-none" "or1k-none" "m68k-none" "powerpc-none" "powerpcle-none"
|
||||
"riscv32-none" "riscv64-none" "s390-none" "s390x-none" "vc4-none"
|
||||
"x86_64-none"
|
||||
|
||||
|
|
1
third_party/nixpkgs/lib/systems/examples.nix
vendored
1
third_party/nixpkgs/lib/systems/examples.nix
vendored
|
@ -290,6 +290,7 @@ rec {
|
|||
libc = "nblibc";
|
||||
};
|
||||
|
||||
# this is broken and never worked fully
|
||||
x86_64-netbsd-llvm = {
|
||||
config = "x86_64-unknown-netbsd";
|
||||
libc = "nblibc";
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
{ lib }:
|
||||
rec {
|
||||
# List of systems that are built by Hydra.
|
||||
hydra = tier1 ++ tier2 ++ tier3;
|
||||
hydra = tier1 ++ tier2 ++ tier3 ++ [
|
||||
"aarch64-darwin"
|
||||
];
|
||||
|
||||
tier1 = [
|
||||
"x86_64-linux"
|
||||
|
@ -16,7 +18,6 @@ rec {
|
|||
];
|
||||
|
||||
tier3 = [
|
||||
"aarch64-darwin"
|
||||
"armv6l-linux"
|
||||
"armv7l-linux"
|
||||
"i686-linux"
|
||||
|
|
2
third_party/nixpkgs/lib/tests/misc.nix
vendored
2
third_party/nixpkgs/lib/tests/misc.nix
vendored
|
@ -496,7 +496,7 @@ runTests {
|
|||
|
||||
testToPretty =
|
||||
let
|
||||
deriv = derivation { name = "test"; builder = "/bin/sh"; system = builtins.currentSystem; };
|
||||
deriv = derivation { name = "test"; builder = "/bin/sh"; system = "aarch64-linux"; };
|
||||
in {
|
||||
expr = mapAttrs (const (generators.toPretty { multiline = false; })) rec {
|
||||
int = 42;
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
{ lib, ... }: {
|
||||
{ lib, ... }:
|
||||
let
|
||||
deathtrapArgs = lib.mapAttrs
|
||||
(k: _: throw "The module system is too strict, accessing an unused option's ${k} mkOption-attribute.")
|
||||
(lib.functionArgs lib.mkOption);
|
||||
in
|
||||
{
|
||||
options.value = lib.mkOption {
|
||||
type = lib.types.attrsOf lib.types.str;
|
||||
default = {};
|
||||
};
|
||||
options.testing-laziness-so-don't-read-me = lib.mkOption deathtrapArgs;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
{ lib, ... }: {
|
||||
{ lib, ... }:
|
||||
let
|
||||
deathtrapArgs = lib.mapAttrs
|
||||
(k: _: throw "The module system is too strict, accessing an unused option's ${k} mkOption-attribute.")
|
||||
(lib.functionArgs lib.mkOption);
|
||||
in
|
||||
{
|
||||
options.nest.foo = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
};
|
||||
options.nest.unused = lib.mkOption deathtrapArgs;
|
||||
config.nest.bar = "bar";
|
||||
}
|
||||
|
|
|
@ -278,6 +278,12 @@
|
|||
githubId = 1250775;
|
||||
name = "Adolfo E. García Castro";
|
||||
};
|
||||
AdsonCicilioti = {
|
||||
name = "Adson Cicilioti";
|
||||
email = "adson.cicilioti@live.com";
|
||||
github = "AdsonCicilioti";
|
||||
githubId = 6278398;
|
||||
};
|
||||
adsr = {
|
||||
email = "as@php.net";
|
||||
github = "adsr";
|
||||
|
@ -351,10 +357,10 @@
|
|||
name = "AmirHossein Roozbahani";
|
||||
};
|
||||
ahuzik = {
|
||||
email = "ales.guzik@gmail.com";
|
||||
github = "alesguzik";
|
||||
email = "ah1990au@gmail.com";
|
||||
github = "alesya-h";
|
||||
githubId = 209175;
|
||||
name = "Ales Huzik";
|
||||
name = "Alesya Huzik";
|
||||
};
|
||||
aij = {
|
||||
email = "aij+git@mrph.org";
|
||||
|
@ -1408,6 +1414,12 @@
|
|||
githubId = 251106;
|
||||
name = "Daniel Bergey";
|
||||
};
|
||||
bergkvist = {
|
||||
email = "tobias@bergkv.ist";
|
||||
github = "bergkvist";
|
||||
githubId = 410028;
|
||||
name = "Tobias Bergkvist";
|
||||
};
|
||||
betaboon = {
|
||||
email = "betaboon@0x80.ninja";
|
||||
github = "betaboon";
|
||||
|
@ -3683,6 +3695,7 @@
|
|||
};
|
||||
evils = {
|
||||
email = "evils.devils@protonmail.com";
|
||||
matrix = "@evils:nixos.dev";
|
||||
github = "evils";
|
||||
githubId = 30512529;
|
||||
name = "Evils";
|
||||
|
@ -4856,6 +4869,16 @@
|
|||
githubId = 12491746;
|
||||
name = "Masato Yonekawa";
|
||||
};
|
||||
hyshka = {
|
||||
name = "Bryan Hyshka";
|
||||
email = "bryan@hyshka.com";
|
||||
github = "hyshka";
|
||||
githubId = 2090758;
|
||||
keys = [{
|
||||
longkeyid = "rsa2048/0xDB2D93D1BFAAA6EA";
|
||||
fingerprint = "24F4 1925 28C4 8797 E539 F247 DB2D 93D1 BFAA A6EA";
|
||||
}];
|
||||
};
|
||||
hyzual = {
|
||||
email = "hyzual@gmail.com";
|
||||
github = "Hyzual";
|
||||
|
@ -7665,6 +7688,12 @@
|
|||
githubId = 21156022;
|
||||
name = "Michal Minář";
|
||||
};
|
||||
michzappa = {
|
||||
email = "me@michzappa.com";
|
||||
github = "michzappa";
|
||||
githubId = 59343378;
|
||||
name = "Michael Zappa";
|
||||
};
|
||||
mickours = {
|
||||
email = "mickours@gmail.com<";
|
||||
github = "mickours";
|
||||
|
@ -9015,6 +9044,12 @@
|
|||
githubId = 116740;
|
||||
name = "Paweł Pacana";
|
||||
};
|
||||
pb- = {
|
||||
email = "pbaecher@gmail.com";
|
||||
github = "pb-";
|
||||
githubId = 84886;
|
||||
name = "Paul Baecher";
|
||||
};
|
||||
pbogdan = {
|
||||
email = "ppbogdan@gmail.com";
|
||||
github = "pbogdan";
|
||||
|
@ -12095,6 +12130,12 @@
|
|||
githubId = 122319;
|
||||
name = "Renato Alves";
|
||||
};
|
||||
unrooted = {
|
||||
name = "Konrad Klawikowski";
|
||||
email = "konrad.root.klawikowski@gmail.com";
|
||||
github = "unrooted";
|
||||
githubId = 30440603;
|
||||
};
|
||||
uralbash = {
|
||||
email = "root@uralbash.ru";
|
||||
github = "uralbash";
|
||||
|
@ -12544,6 +12585,12 @@
|
|||
githubId = 78392041;
|
||||
name = "Winter";
|
||||
};
|
||||
wintrmvte = {
|
||||
name = "Jakub Lutczyn";
|
||||
email = "kubalutczyn@gmail.com";
|
||||
github = "wintrmvte";
|
||||
githubId = 41823252;
|
||||
};
|
||||
wirew0rm = {
|
||||
email = "alex@wirew0rm.de";
|
||||
github = "wirew0rm";
|
||||
|
@ -12622,6 +12669,12 @@
|
|||
githubId = 28888242;
|
||||
name = "WORLDofPEACE";
|
||||
};
|
||||
wr0belj = {
|
||||
name = "Jakub Wróbel";
|
||||
email = "wrobel.jakub@protonmail.com";
|
||||
github = "wr0belj";
|
||||
githubId = 40501814;
|
||||
};
|
||||
wscott = {
|
||||
email = "wsc9tt@gmail.com";
|
||||
github = "wscott";
|
||||
|
@ -12799,6 +12852,12 @@
|
|||
githubId = 11229748;
|
||||
name = "Lin Yinfeng";
|
||||
};
|
||||
ylecornec = {
|
||||
email = "yves.stan.lecornec@tweag.io";
|
||||
github = "ylecornec";
|
||||
githubId = 5978566;
|
||||
name = "Yves-Stan Le Cornec";
|
||||
};
|
||||
ylwghst = {
|
||||
email = "ylwghst@onionmail.info";
|
||||
github = "ylwghst";
|
||||
|
@ -13367,4 +13426,10 @@
|
|||
github = "vdot0x23";
|
||||
githubId = 40716069;
|
||||
};
|
||||
jpagex = {
|
||||
name = "Jérémy Pagé";
|
||||
email = "contact@jeremypage.me";
|
||||
github = "jpagex";
|
||||
githubId = 635768;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,20 +4,19 @@
|
|||
# Example how to work with the `lib.maintainers` attrset.
|
||||
# Can be used to check whether all user handles are still valid.
|
||||
|
||||
set -e
|
||||
|
||||
# nixpkgs='<nixpkgs>'
|
||||
# if [ -n "$1" ]; then
|
||||
set -o errexit -o noclobber -o nounset -o pipefail
|
||||
shopt -s failglob inherit_errexit
|
||||
|
||||
function checkCommits {
|
||||
local user="$1"
|
||||
local tmp=$(mktemp)
|
||||
local ret status tmp user
|
||||
user="$1"
|
||||
tmp=$(mktemp)
|
||||
curl --silent -w "%{http_code}" \
|
||||
"https://github.com/NixOS/nixpkgs/commits?author=$user" \
|
||||
> "$tmp"
|
||||
# the last line of tmp contains the http status
|
||||
local status=$(tail -n1 "$tmp")
|
||||
local ret=
|
||||
status=$(tail -n1 "$tmp")
|
||||
ret=
|
||||
case $status in
|
||||
200) if <"$tmp" grep -i "no commits found" > /dev/null; then
|
||||
ret=1
|
||||
|
@ -31,7 +30,7 @@ function checkCommits {
|
|||
checkCommits "$user"
|
||||
ret=$?
|
||||
;;
|
||||
*) printf "BAD STATUS: $(tail -n1 $tmp) for %s\n" "$user"; ret=1
|
||||
*) printf "BAD STATUS: $(tail -n1 "$tmp") for %s\n" "$user"; ret=1
|
||||
ret=1
|
||||
;;
|
||||
esac
|
||||
|
@ -63,4 +62,5 @@ nix-instantiate -A lib.maintainers --eval --strict --json \
|
|||
| jq -r '.[]|.github|select(.)' \
|
||||
| parallel -j5 checkUser
|
||||
|
||||
# To check some arbitrary users:
|
||||
# parallel -j100 checkUser ::: "eelco" "profpatsch" "Profpatsch" "a"
|
||||
|
|
|
@ -385,7 +385,7 @@ def check_results(
|
|||
sys.exit(1)
|
||||
|
||||
def parse_plugin_line(line: str) -> PluginDesc:
|
||||
branch = "master"
|
||||
branch = "HEAD"
|
||||
alias = None
|
||||
name, repo = line.split("/")
|
||||
if " as " in repo:
|
||||
|
|
30
third_party/nixpkgs/maintainers/team-list.nix
vendored
30
third_party/nixpkgs/maintainers/team-list.nix
vendored
|
@ -29,6 +29,20 @@ with lib.maintainers; {
|
|||
scope = "Maintain ACME-related packages and modules.";
|
||||
};
|
||||
|
||||
bazel = {
|
||||
members = [
|
||||
mboes
|
||||
marsam
|
||||
uri-canva
|
||||
cbley
|
||||
olebedev
|
||||
groodt
|
||||
aherrmann
|
||||
ylecornec
|
||||
];
|
||||
scope = "Bazel build tool & related tools https://bazel.build/";
|
||||
};
|
||||
|
||||
beam = {
|
||||
members = [
|
||||
ankhers
|
||||
|
@ -233,6 +247,15 @@ with lib.maintainers; {
|
|||
scope = "Maintain Podman and CRI-O related packages and modules.";
|
||||
};
|
||||
|
||||
redcodelabs = {
|
||||
members = [
|
||||
unrooted
|
||||
wr0belj
|
||||
wintrmvte
|
||||
];
|
||||
scope = "Maintain Red Code Labs related packages and modules.";
|
||||
};
|
||||
|
||||
sage = {
|
||||
members = [
|
||||
timokau
|
||||
|
@ -259,4 +282,11 @@ with lib.maintainers; {
|
|||
];
|
||||
scope = "coqui-ai TTS (formerly Mozilla TTS) and leaf packages";
|
||||
};
|
||||
|
||||
xfce = {
|
||||
members = [
|
||||
romildo
|
||||
];
|
||||
scope = "Maintain Xfce desktop environment and related packages.";
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ containers.database =
|
|||
{ config =
|
||||
{ config, pkgs, ... }:
|
||||
{ services.postgresql.enable = true;
|
||||
services.postgresql.package = pkgs.postgresql_9_6;
|
||||
services.postgresql.package = pkgs.postgresql_10;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
|
|
@ -161,7 +161,7 @@ let
|
|||
in rec {
|
||||
inherit generatedSources;
|
||||
|
||||
inherit (optionsDoc) optionsJSON optionsXML optionsDocBook;
|
||||
inherit (optionsDoc) optionsJSON optionsDocBook;
|
||||
|
||||
# Generate the NixOS manual.
|
||||
manualHTML = runCommand "nixos-manual-html"
|
||||
|
|
|
@ -11,7 +11,7 @@ containers.database =
|
|||
{ config =
|
||||
{ config, pkgs, ... }:
|
||||
{ services.postgresql.enable = true;
|
||||
services.postgresql.package = pkgs.postgresql_9_6;
|
||||
services.postgresql.package = pkgs.postgresql_10;
|
||||
};
|
||||
};
|
||||
</programlisting>
|
||||
|
|
|
@ -273,6 +273,13 @@
|
|||
<link xlink:href="options.html#opt-services.peertube.enable">services.peertube</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://maddy.email">maddy</link>, a
|
||||
composable all-in-one mail server. Available as
|
||||
<link xlink:href="options.html#opt-services.maddy.enable">services.maddy</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://sr.ht">sourcehut</link>, a
|
||||
|
|
|
@ -19,8 +19,31 @@
|
|||
</section>
|
||||
<section xml:id="sec-release-22.05-new-services">
|
||||
<title>New Services</title>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://github.com/intel/linux-sgx#install-the-intelr-sgx-psw">aesmd</link>,
|
||||
the Intel SGX Architectural Enclave Service Manager. Available
|
||||
as
|
||||
<link linkend="opt-services.aesmd.enable">services.aesmd</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-overview.html">filebeat</link>,
|
||||
a lightweight shipper for forwarding and centralizing log
|
||||
data. Available as
|
||||
<link linkend="opt-services.filebeat.enable">services.filebeat</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://github.com/ngoduykhanh/PowerDNS-Admin">PowerDNS-Admin</link>,
|
||||
a web interface for the PowerDNS server. Available at
|
||||
<link xlink:href="options.html#opt-services.powerdns-admin.enable">services.powerdns-admin</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
<section xml:id="sec-release-22.05-incompatibilities">
|
||||
<title>Backward Incompatibilities</title>
|
||||
|
@ -75,11 +98,85 @@
|
|||
release based on GTK+3 and Python 3.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <literal>writers.writePython2</literal> and corresponding
|
||||
<literal>writers.writePython2Bin</literal> convenience
|
||||
functions to create executable Python 2 scripts in the store
|
||||
were removed in preparation of removal of the Python 2
|
||||
interpreter. Scripts have to be converted to Python 3 for use
|
||||
with <literal>writers.writePython3</literal> or
|
||||
<literal>writers.writePyPy2</literal> needs to be used.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
<section xml:id="sec-release-22.05-notable-changes">
|
||||
<title>Other Notable Changes</title>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
The option
|
||||
<link linkend="opt-services.redis.servers">services.redis.servers</link>
|
||||
was added to support per-application
|
||||
<literal>redis-server</literal> which is more secure since
|
||||
Redis databases are only mere key prefixes without any
|
||||
configuration or ACL of their own. Backward-compatibility is
|
||||
preserved by mapping old
|
||||
<literal>services.redis.settings</literal> to
|
||||
<literal>services.redis.servers."".settings</literal>,
|
||||
but you are strongly encouraged to name each
|
||||
<literal>redis-server</literal> instance after the application
|
||||
using it, instead of keeping that nameless one. Except for the
|
||||
nameless
|
||||
<literal>services.redis.servers.""</literal> still
|
||||
accessible at <literal>127.0.0.1:6379</literal>, and to the
|
||||
members of the Unix group <literal>redis</literal> through the
|
||||
Unix socket <literal>/run/redis/redis.sock</literal>, all
|
||||
other <literal>services.redis.servers.${serverName}</literal>
|
||||
are only accessible by default to the members of the Unix
|
||||
group <literal>redis-${serverName}</literal> through the Unix
|
||||
socket <literal>/run/redis-${serverName}/redis.sock</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The
|
||||
<literal>writers.writePyPy2</literal>/<literal>writers.writePyPy3</literal>
|
||||
and corresponding
|
||||
<literal>writers.writePyPy2Bin</literal>/<literal>writers.writePyPy3Bin</literal>
|
||||
convenience functions to create executable Python 2/3 scripts
|
||||
using the PyPy interpreter were added.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <literal>influxdb2</literal> package was split into
|
||||
<literal>influxdb2-server</literal> and
|
||||
<literal>influxdb2-cli</literal>, matching the split that took
|
||||
place upstream. A combined <literal>influxdb2</literal>
|
||||
package is still provided in this release for backwards
|
||||
compatibilty, but will be removed at a later date.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <literal>services.unifi.openPorts</literal> option default
|
||||
value of <literal>true</literal> is now deprecated and will be
|
||||
changed to <literal>false</literal> in 22.11. Configurations
|
||||
using this default will print a warning when rebuilt.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The option
|
||||
<link linkend="opt-services.ssh.enableAskPassword">services.ssh.enableAskPassword</link>
|
||||
was added, decoupling the setting of
|
||||
<literal>SSH_ASKPASS</literal> from
|
||||
<literal>services.xserver.enable</literal>. This allows easy
|
||||
usage in non-X11 environments, e.g. Wayland.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
</section>
|
||||
|
|
|
@ -74,6 +74,8 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
- [PeerTube](https://joinpeertube.org/), developed by Framasoft, is the free and decentralized alternative to video platforms. Available at [services.peertube](options.html#opt-services.peertube.enable).
|
||||
|
||||
- [maddy](https://maddy.email), a composable all-in-one mail server. Available as [services.maddy](options.html#opt-services.maddy.enable).
|
||||
|
||||
- [sourcehut](https://sr.ht), a collection of tools useful for software development. Available as [services.sourcehut](options.html#opt-services.sourcehut.enable).
|
||||
|
||||
- [ucarp](https://download.pureftpd.org/pub/ucarp/README), an userspace implementation of the Common Address Redundancy Protocol (CARP). Available as [networking.ucarp](options.html#opt-networking.ucarp.enable).
|
||||
|
|
|
@ -8,6 +8,12 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
## New Services {#sec-release-22.05-new-services}
|
||||
|
||||
- [aesmd](https://github.com/intel/linux-sgx#install-the-intelr-sgx-psw), the Intel SGX Architectural Enclave Service Manager. Available as [services.aesmd](#opt-services.aesmd.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).
|
||||
|
||||
- [PowerDNS-Admin](https://github.com/ngoduykhanh/PowerDNS-Admin), a web interface for the PowerDNS server. Available at [services.powerdns-admin](options.html#opt-services.powerdns-admin.enable).
|
||||
|
||||
## Backward Incompatibilities {#sec-release-22.05-incompatibilities}
|
||||
|
||||
- `pkgs.ghc` now refers to `pkgs.targetPackages.haskellPackages.ghc`.
|
||||
|
@ -32,4 +38,39 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
- `pkgs.claws-mail-gtk2`, representing Claws Mail's older release version three, was removed in order to get rid of Python 2.
|
||||
Please switch to `claws-mail`, which is Claws Mail's latest release based on GTK+3 and Python 3.
|
||||
|
||||
- The `writers.writePython2` and corresponding `writers.writePython2Bin` convenience functions to create executable Python 2 scripts in the store were removed in preparation of removal of the Python 2 interpreter.
|
||||
Scripts have to be converted to Python 3 for use with `writers.writePython3` or `writers.writePyPy2` needs to be used.
|
||||
|
||||
## Other Notable Changes {#sec-release-22.05-notable-changes}
|
||||
|
||||
- The option [services.redis.servers](#opt-services.redis.servers) was added
|
||||
to support per-application `redis-server` which is more secure since Redis databases
|
||||
are only mere key prefixes without any configuration or ACL of their own.
|
||||
Backward-compatibility is preserved by mapping old `services.redis.settings`
|
||||
to `services.redis.servers."".settings`, but you are strongly encouraged
|
||||
to name each `redis-server` instance after the application using it,
|
||||
instead of keeping that nameless one.
|
||||
Except for the nameless `services.redis.servers.""`
|
||||
still accessible at `127.0.0.1:6379`,
|
||||
and to the members of the Unix group `redis`
|
||||
through the Unix socket `/run/redis/redis.sock`,
|
||||
all other `services.redis.servers.${serverName}`
|
||||
are only accessible by default
|
||||
to the members of the Unix group `redis-${serverName}`
|
||||
through the Unix socket `/run/redis-${serverName}/redis.sock`.
|
||||
|
||||
- The `writers.writePyPy2`/`writers.writePyPy3` and corresponding `writers.writePyPy2Bin`/`writers.writePyPy3Bin` convenience functions to create executable Python 2/3 scripts using the PyPy interpreter were added.
|
||||
|
||||
- The `influxdb2` package was split into `influxdb2-server` and
|
||||
`influxdb2-cli`, matching the split that took place upstream. A
|
||||
combined `influxdb2` package is still provided in this release for
|
||||
backwards compatibilty, but will be removed at a later date.
|
||||
|
||||
- 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.
|
||||
|
||||
- The option
|
||||
[services.ssh.enableAskPassword](#opt-services.ssh.enableAskPassword) was
|
||||
added, decoupling the setting of `SSH_ASKPASS` from
|
||||
`services.xserver.enable`. This allows easy usage in non-X11 environments,
|
||||
e.g. Wayland.
|
||||
|
|
48
third_party/nixpkgs/nixos/lib/eval-config.nix
vendored
48
third_party/nixpkgs/nixos/lib/eval-config.nix
vendored
|
@ -8,6 +8,7 @@
|
|||
# as subcomponents (e.g. the container feature, or nixops if network
|
||||
# expressions are ever made modular at the top level) can just use
|
||||
# types.submodule instead of using eval-config.nix
|
||||
evalConfigArgs@
|
||||
{ # !!! system can be set modularly, would be nice to remove
|
||||
system ? builtins.currentSystem
|
||||
, # !!! is this argument needed any more? The pkgs argument can
|
||||
|
@ -28,7 +29,7 @@
|
|||
in if e == "" then [] else [(import e)]
|
||||
}:
|
||||
|
||||
let extraArgs_ = extraArgs; pkgs_ = pkgs;
|
||||
let pkgs_ = pkgs;
|
||||
in
|
||||
|
||||
let
|
||||
|
@ -51,28 +52,49 @@ let
|
|||
};
|
||||
};
|
||||
|
||||
noUserModules = lib.evalModules {
|
||||
inherit prefix check;
|
||||
modules = baseModules ++ extraModules ++ [ pkgsModule ];
|
||||
args = extraArgs;
|
||||
withWarnings = x:
|
||||
lib.warnIf (evalConfigArgs?extraArgs) "The extraArgs argument to eval-config.nix is deprecated. Please set config._module.args instead."
|
||||
lib.warnIf (evalConfigArgs?check) "The check argument to eval-config.nix is deprecated. Please set config._module.check instead."
|
||||
x;
|
||||
|
||||
legacyModules =
|
||||
lib.optional (evalConfigArgs?extraArgs) {
|
||||
config = {
|
||||
_module.args = extraArgs;
|
||||
};
|
||||
}
|
||||
++ lib.optional (evalConfigArgs?check) {
|
||||
config = {
|
||||
_module.check = lib.mkDefault check;
|
||||
};
|
||||
};
|
||||
allUserModules = modules ++ legacyModules;
|
||||
|
||||
noUserModules = lib.evalModules ({
|
||||
inherit prefix;
|
||||
modules = baseModules ++ extraModules ++ [ pkgsModule modulesModule ];
|
||||
specialArgs =
|
||||
{ modulesPath = builtins.toString ../modules; } // specialArgs;
|
||||
};
|
||||
});
|
||||
|
||||
# These are the extra arguments passed to every module. In
|
||||
# particular, Nixpkgs is passed through the "pkgs" argument.
|
||||
extraArgs = extraArgs_ // {
|
||||
# Extra arguments that are useful for constructing a similar configuration.
|
||||
modulesModule = {
|
||||
config = {
|
||||
_module.args = {
|
||||
inherit noUserModules baseModules extraModules modules;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
in rec {
|
||||
nixosWithUserModules = noUserModules.extendModules { modules = allUserModules; };
|
||||
|
||||
in withWarnings {
|
||||
|
||||
# Merge the option definitions in all modules, forming the full
|
||||
# system configuration.
|
||||
inherit (noUserModules.extendModules { inherit modules; })
|
||||
config options _module type;
|
||||
inherit (nixosWithUserModules) config options _module type;
|
||||
|
||||
inherit extraArgs;
|
||||
|
||||
inherit (_module.args) pkgs;
|
||||
inherit (nixosWithUserModules._module.args) pkgs;
|
||||
}
|
||||
|
|
|
@ -24,18 +24,25 @@
|
|||
}:
|
||||
|
||||
let
|
||||
# Replace functions by the string <function>
|
||||
substFunction = x:
|
||||
if builtins.isAttrs x then lib.mapAttrs (name: substFunction) x
|
||||
else if builtins.isList x then map substFunction x
|
||||
# Make a value safe for JSON. Functions are replaced by the string "<function>",
|
||||
# derivations are replaced with an attrset
|
||||
# { _type = "derivation"; name = <name of that derivation>; }.
|
||||
# We need to handle derivations specially because consumers want to know about them,
|
||||
# but we can't easily use the type,name subset of keys (since type is often used as
|
||||
# a module option and might cause confusion). Use _type,name instead to the same
|
||||
# effect, since _type is already used by the module system.
|
||||
substSpecial = x:
|
||||
if lib.isDerivation x then { _type = "derivation"; name = x.name; }
|
||||
else if builtins.isAttrs x then lib.mapAttrs (name: substSpecial) x
|
||||
else if builtins.isList x then map substSpecial x
|
||||
else if lib.isFunction x then "<function>"
|
||||
else x;
|
||||
|
||||
optionsListDesc = lib.flip map optionsListVisible
|
||||
optionsList = lib.flip map optionsListVisible
|
||||
(opt: transformOptions opt
|
||||
// lib.optionalAttrs (opt ? example) { example = substFunction opt.example; }
|
||||
// lib.optionalAttrs (opt ? default) { default = substFunction opt.default; }
|
||||
// lib.optionalAttrs (opt ? type) { type = substFunction opt.type; }
|
||||
// lib.optionalAttrs (opt ? example) { example = substSpecial opt.example; }
|
||||
// lib.optionalAttrs (opt ? default) { default = substSpecial opt.default; }
|
||||
// lib.optionalAttrs (opt ? type) { type = substSpecial opt.type; }
|
||||
// lib.optionalAttrs (opt ? relatedPackages && opt.relatedPackages != []) { relatedPackages = genRelatedPackages opt.relatedPackages opt.name; }
|
||||
);
|
||||
|
||||
|
@ -69,96 +76,25 @@ let
|
|||
+ "</listitem>";
|
||||
in "<itemizedlist>${lib.concatStringsSep "\n" (map (p: describe (unpack p)) packages)}</itemizedlist>";
|
||||
|
||||
# Custom "less" that pushes up all the things ending in ".enable*"
|
||||
# and ".package*"
|
||||
optionLess = a: b:
|
||||
let
|
||||
ise = lib.hasPrefix "enable";
|
||||
isp = lib.hasPrefix "package";
|
||||
cmp = lib.splitByAndCompare ise lib.compare
|
||||
(lib.splitByAndCompare isp lib.compare lib.compare);
|
||||
in lib.compareLists cmp a.loc b.loc < 0;
|
||||
|
||||
# Remove invisible and internal options.
|
||||
optionsListVisible = lib.filter (opt: opt.visible && !opt.internal) (lib.optionAttrSetToDocList options);
|
||||
|
||||
# Customly sort option list for the man page.
|
||||
# Always ensure that the sort order matches sortXML.py!
|
||||
optionsList = lib.sort optionLess optionsListDesc;
|
||||
|
||||
# Convert the list of options into an XML file.
|
||||
# This file is *not* sorted sorted to save on eval time, since the docbook XML
|
||||
# and the manpage depend on it and thus we evaluate this on every system rebuild.
|
||||
optionsXML = builtins.toFile "options.xml" (builtins.toXML optionsListDesc);
|
||||
|
||||
optionsNix = builtins.listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) optionsList);
|
||||
|
||||
# TODO: declarations: link to github
|
||||
singleAsciiDoc = name: value: ''
|
||||
== ${name}
|
||||
|
||||
${value.description}
|
||||
|
||||
[discrete]
|
||||
=== details
|
||||
|
||||
Type:: ${value.type}
|
||||
${ if lib.hasAttr "default" value
|
||||
then ''
|
||||
Default::
|
||||
+
|
||||
----
|
||||
${builtins.toJSON value.default}
|
||||
----
|
||||
''
|
||||
else "No Default:: {blank}"
|
||||
}
|
||||
${ if value.readOnly
|
||||
then "Read Only:: {blank}"
|
||||
else ""
|
||||
}
|
||||
${ if lib.hasAttr "example" value
|
||||
then ''
|
||||
Example::
|
||||
+
|
||||
----
|
||||
${builtins.toJSON value.example}
|
||||
----
|
||||
''
|
||||
else "No Example:: {blank}"
|
||||
}
|
||||
'';
|
||||
|
||||
singleMDDoc = name: value: ''
|
||||
## ${lib.escape [ "<" ">" ] name}
|
||||
${value.description}
|
||||
|
||||
${lib.optionalString (value ? type) ''
|
||||
*_Type_*:
|
||||
${value.type}
|
||||
''}
|
||||
|
||||
${lib.optionalString (value ? default) ''
|
||||
*_Default_*
|
||||
```
|
||||
${builtins.toJSON value.default}
|
||||
```
|
||||
''}
|
||||
|
||||
${lib.optionalString (value ? example) ''
|
||||
*_Example_*
|
||||
```
|
||||
${builtins.toJSON value.example}
|
||||
```
|
||||
''}
|
||||
'';
|
||||
|
||||
in {
|
||||
in rec {
|
||||
inherit optionsNix;
|
||||
|
||||
optionsAsciiDoc = lib.concatStringsSep "\n" (lib.mapAttrsToList singleAsciiDoc optionsNix);
|
||||
optionsAsciiDoc = pkgs.runCommand "options.adoc" {} ''
|
||||
${pkgs.python3Minimal}/bin/python ${./generateAsciiDoc.py} \
|
||||
< ${optionsJSON}/share/doc/nixos/options.json \
|
||||
> $out
|
||||
'';
|
||||
|
||||
optionsMDDoc = lib.concatStringsSep "\n" (lib.mapAttrsToList singleMDDoc optionsNix);
|
||||
optionsCommonMark = pkgs.runCommand "options.md" {} ''
|
||||
${pkgs.python3Minimal}/bin/python ${./generateCommonMark.py} \
|
||||
< ${optionsJSON}/share/doc/nixos/options.json \
|
||||
> $out
|
||||
'';
|
||||
|
||||
optionsJSON = pkgs.runCommand "options.json"
|
||||
{ meta.description = "List of NixOS options in JSON format";
|
||||
|
@ -176,7 +112,19 @@ in {
|
|||
mkdir -p $out/nix-support
|
||||
echo "file json $dst/options.json" >> $out/nix-support/hydra-build-products
|
||||
echo "file json-br $dst/options.json.br" >> $out/nix-support/hydra-build-products
|
||||
''; # */
|
||||
'';
|
||||
|
||||
# Convert options.json into an XML file.
|
||||
# The actual generation of the xml file is done in nix purely for the convenience
|
||||
# of not having to generate the xml some other way
|
||||
optionsXML = pkgs.runCommand "options.xml" {} ''
|
||||
export NIX_STORE_DIR=$TMPDIR/store
|
||||
export NIX_STATE_DIR=$TMPDIR/state
|
||||
${pkgs.nix}/bin/nix-instantiate \
|
||||
--eval --xml --strict ${./optionsJSONtoXML.nix} \
|
||||
--argstr file ${optionsJSON}/share/doc/nixos/options.json \
|
||||
> "$out"
|
||||
'';
|
||||
|
||||
optionsDocBook = pkgs.runCommand "options-docbook.xml" {} ''
|
||||
optionsXML=${optionsXML}
|
||||
|
|
37
third_party/nixpkgs/nixos/lib/make-options-doc/generateAsciiDoc.py
vendored
Normal file
37
third_party/nixpkgs/nixos/lib/make-options-doc/generateAsciiDoc.py
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
import json
|
||||
import sys
|
||||
|
||||
options = json.load(sys.stdin)
|
||||
# TODO: declarations: link to github
|
||||
for (name, value) in options.items():
|
||||
print(f'== {name}')
|
||||
print()
|
||||
print(value['description'])
|
||||
print()
|
||||
print('[discrete]')
|
||||
print('=== details')
|
||||
print()
|
||||
print(f'Type:: {value["type"]}')
|
||||
if 'default' in value:
|
||||
print('Default::')
|
||||
print('+')
|
||||
print('----')
|
||||
print(json.dumps(value['default'], ensure_ascii=False, separators=(',', ':')))
|
||||
print('----')
|
||||
print()
|
||||
else:
|
||||
print('No Default:: {blank}')
|
||||
if value['readOnly']:
|
||||
print('Read Only:: {blank}')
|
||||
else:
|
||||
print()
|
||||
if 'example' in value:
|
||||
print('Example::')
|
||||
print('+')
|
||||
print('----')
|
||||
print(json.dumps(value['example'], ensure_ascii=False, separators=(',', ':')))
|
||||
print('----')
|
||||
print()
|
||||
else:
|
||||
print('No Example:: {blank}')
|
||||
print()
|
27
third_party/nixpkgs/nixos/lib/make-options-doc/generateCommonMark.py
vendored
Normal file
27
third_party/nixpkgs/nixos/lib/make-options-doc/generateCommonMark.py
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
import json
|
||||
import sys
|
||||
|
||||
options = json.load(sys.stdin)
|
||||
for (name, value) in options.items():
|
||||
print('##', name.replace('<', '\\<').replace('>', '\\>'))
|
||||
print(value['description'])
|
||||
print()
|
||||
if 'type' in value:
|
||||
print('*_Type_*:')
|
||||
print(value['type'])
|
||||
print()
|
||||
print()
|
||||
if 'default' in value:
|
||||
print('*_Default_*')
|
||||
print('```')
|
||||
print(json.dumps(value['default'], ensure_ascii=False, separators=(',', ':')))
|
||||
print('```')
|
||||
print()
|
||||
print()
|
||||
if 'example' in value:
|
||||
print('*_Example_*')
|
||||
print('```')
|
||||
print(json.dumps(value['example'], ensure_ascii=False, separators=(',', ':')))
|
||||
print('```')
|
||||
print()
|
||||
print()
|
|
@ -189,7 +189,7 @@
|
|||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template match="derivation">
|
||||
<xsl:template match="attrs[attr[@name = '_type' and string[@value = 'derivation']]]">
|
||||
<replaceable>(build of <xsl:value-of select="attr[@name = 'name']/string/@value" />)</replaceable>
|
||||
</xsl:template>
|
||||
|
||||
|
|
6
third_party/nixpkgs/nixos/lib/make-options-doc/optionsJSONtoXML.nix
vendored
Normal file
6
third_party/nixpkgs/nixos/lib/make-options-doc/optionsJSONtoXML.nix
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
{ file }:
|
||||
|
||||
builtins.attrValues
|
||||
(builtins.mapAttrs
|
||||
(name: def: def // { inherit name; })
|
||||
(builtins.fromJSON (builtins.readFile file)))
|
|
@ -19,7 +19,6 @@ def sortKey(opt):
|
|||
for p in opt.findall('attr[@name="loc"]/list/string')
|
||||
]
|
||||
|
||||
# always ensure that the sort order matches the order used in the nix expression!
|
||||
options.sort(key=sortKey)
|
||||
|
||||
doc = ET.Element("expr")
|
||||
|
|
|
@ -21,8 +21,15 @@ stdenv.mkDerivation {
|
|||
# for nix-store --load-db.
|
||||
cp $closureInfo/registration nix-path-registration
|
||||
|
||||
# 64 cores on i686 does not work
|
||||
# fails with FATAL ERROR: mangle2:: xz compress failed with error code 5
|
||||
if ((NIX_BUILD_CORES > 48)); then
|
||||
NIX_BUILD_CORES=48
|
||||
fi
|
||||
|
||||
# Generate the squashfs image.
|
||||
mksquashfs nix-path-registration $(cat $closureInfo/store-paths) $out \
|
||||
-no-hardlinks -keep-as-directory -all-root -b 1048576 -comp ${comp}
|
||||
-no-hardlinks -keep-as-directory -all-root -b 1048576 -comp ${comp} \
|
||||
-processors $NIX_BUILD_CORES
|
||||
'';
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{ config, lib }:
|
||||
{ lib, systemdUtils }:
|
||||
|
||||
with systemdUtils.lib;
|
||||
with lib;
|
||||
with import ./systemd-lib.nix { inherit config lib pkgs; };
|
||||
|
||||
let
|
||||
checkService = checkUnitConfig "Service" [
|
32
third_party/nixpkgs/nixos/lib/test-driver/default.nix
vendored
Normal file
32
third_party/nixpkgs/nixos/lib/test-driver/default.nix
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
{ lib
|
||||
, python3Packages
|
||||
, enableOCR ? false
|
||||
, qemu_pkg ? qemu_test
|
||||
, coreutils
|
||||
, imagemagick_light
|
||||
, libtiff
|
||||
, netpbm
|
||||
, qemu_test
|
||||
, socat
|
||||
, tesseract4
|
||||
, vde2
|
||||
}:
|
||||
|
||||
python3Packages.buildPythonApplication rec {
|
||||
pname = "nixos-test-driver";
|
||||
version = "1.0";
|
||||
src = ./.;
|
||||
|
||||
propagatedBuildInputs = [ coreutils netpbm python3Packages.colorama python3Packages.ptpython qemu_pkg socat vde2 ]
|
||||
++ (lib.optionals enableOCR [ imagemagick_light tesseract4 ]);
|
||||
|
||||
doCheck = true;
|
||||
checkInputs = with python3Packages; [ mypy pylint black ];
|
||||
checkPhase = ''
|
||||
mypy --disallow-untyped-defs \
|
||||
--no-implicit-optional \
|
||||
--ignore-missing-imports ${src}/test_driver
|
||||
pylint --errors-only ${src}/test_driver
|
||||
black --check --diff ${src}/test_driver
|
||||
'';
|
||||
}
|
13
third_party/nixpkgs/nixos/lib/test-driver/setup.py
vendored
Normal file
13
third_party/nixpkgs/nixos/lib/test-driver/setup.py
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
name="nixos-test-driver",
|
||||
version='1.0',
|
||||
packages=find_packages(),
|
||||
entry_points={
|
||||
"console_scripts": [
|
||||
"nixos-test-driver=test_driver:main",
|
||||
"generate-driver-symbols=test_driver:generate_driver_symbols"
|
||||
]
|
||||
},
|
||||
)
|
100
third_party/nixpkgs/nixos/lib/test-driver/test_driver/__init__.py
vendored
Executable file
100
third_party/nixpkgs/nixos/lib/test-driver/test_driver/__init__.py
vendored
Executable file
|
@ -0,0 +1,100 @@
|
|||
from pathlib import Path
|
||||
import argparse
|
||||
import ptpython.repl
|
||||
import os
|
||||
import time
|
||||
|
||||
from test_driver.logger import rootlog
|
||||
from test_driver.driver import Driver
|
||||
|
||||
|
||||
class EnvDefault(argparse.Action):
|
||||
"""An argpars Action that takes values from the specified
|
||||
environment variable as the flags default value.
|
||||
"""
|
||||
|
||||
def __init__(self, envvar, required=False, default=None, nargs=None, **kwargs): # type: ignore
|
||||
if not default and envvar:
|
||||
if envvar in os.environ:
|
||||
if nargs is not None and (nargs.isdigit() or nargs in ["*", "+"]):
|
||||
default = os.environ[envvar].split()
|
||||
else:
|
||||
default = os.environ[envvar]
|
||||
kwargs["help"] = (
|
||||
kwargs["help"] + f" (default from environment: {default})"
|
||||
)
|
||||
if required and default:
|
||||
required = False
|
||||
super(EnvDefault, self).__init__(
|
||||
default=default, required=required, nargs=nargs, **kwargs
|
||||
)
|
||||
|
||||
def __call__(self, parser, namespace, values, option_string=None): # type: ignore
|
||||
setattr(namespace, self.dest, values)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
arg_parser = argparse.ArgumentParser(prog="nixos-test-driver")
|
||||
arg_parser.add_argument(
|
||||
"-K",
|
||||
"--keep-vm-state",
|
||||
help="re-use a VM state coming from a previous run",
|
||||
action="store_true",
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
"-I",
|
||||
"--interactive",
|
||||
help="drop into a python repl and run the tests interactively",
|
||||
action="store_true",
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
"--start-scripts",
|
||||
metavar="START-SCRIPT",
|
||||
action=EnvDefault,
|
||||
envvar="startScripts",
|
||||
nargs="*",
|
||||
help="start scripts for participating virtual machines",
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
"--vlans",
|
||||
metavar="VLAN",
|
||||
action=EnvDefault,
|
||||
envvar="vlans",
|
||||
nargs="*",
|
||||
help="vlans to span by the driver",
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
"testscript",
|
||||
action=EnvDefault,
|
||||
envvar="testScript",
|
||||
help="the test script to run",
|
||||
type=Path,
|
||||
)
|
||||
|
||||
args = arg_parser.parse_args()
|
||||
|
||||
if not args.keep_vm_state:
|
||||
rootlog.info("Machine state will be reset. To keep it, pass --keep-vm-state")
|
||||
|
||||
with Driver(
|
||||
args.start_scripts, args.vlans, args.testscript.read_text(), args.keep_vm_state
|
||||
) as driver:
|
||||
if args.interactive:
|
||||
ptpython.repl.embed(driver.test_symbols(), {})
|
||||
else:
|
||||
tic = time.time()
|
||||
driver.run_tests()
|
||||
toc = time.time()
|
||||
rootlog.info(f"test script finished in {(toc-tic):.2f}s")
|
||||
|
||||
|
||||
def generate_driver_symbols() -> None:
|
||||
"""
|
||||
This generates a file with symbols of the test-driver code that can be used
|
||||
in user's test scripts. That list is then used by pyflakes to lint those
|
||||
scripts.
|
||||
"""
|
||||
d = Driver([], [], "")
|
||||
test_symbols = d.test_symbols()
|
||||
with open("driver-symbols", "w") as fp:
|
||||
fp.write(",".join(test_symbols.keys()))
|
161
third_party/nixpkgs/nixos/lib/test-driver/test_driver/driver.py
vendored
Normal file
161
third_party/nixpkgs/nixos/lib/test-driver/test_driver/driver.py
vendored
Normal file
|
@ -0,0 +1,161 @@
|
|||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Iterator, List
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
from test_driver.logger import rootlog
|
||||
from test_driver.machine import Machine, NixStartScript, retry
|
||||
from test_driver.vlan import VLan
|
||||
|
||||
|
||||
class Driver:
|
||||
"""A handle to the driver that sets up the environment
|
||||
and runs the tests"""
|
||||
|
||||
tests: str
|
||||
vlans: List[VLan]
|
||||
machines: List[Machine]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
start_scripts: List[str],
|
||||
vlans: List[int],
|
||||
tests: str,
|
||||
keep_vm_state: bool = False,
|
||||
):
|
||||
self.tests = tests
|
||||
|
||||
tmp_dir = Path(os.environ.get("TMPDIR", tempfile.gettempdir()))
|
||||
tmp_dir.mkdir(mode=0o700, exist_ok=True)
|
||||
|
||||
with rootlog.nested("start all VLans"):
|
||||
self.vlans = [VLan(nr, tmp_dir) for nr in vlans]
|
||||
|
||||
def cmd(scripts: List[str]) -> Iterator[NixStartScript]:
|
||||
for s in scripts:
|
||||
yield NixStartScript(s)
|
||||
|
||||
self.machines = [
|
||||
Machine(
|
||||
start_command=cmd,
|
||||
keep_vm_state=keep_vm_state,
|
||||
name=cmd.machine_name,
|
||||
tmp_dir=tmp_dir,
|
||||
)
|
||||
for cmd in cmd(start_scripts)
|
||||
]
|
||||
|
||||
def __enter__(self) -> "Driver":
|
||||
return self
|
||||
|
||||
def __exit__(self, *_: Any) -> None:
|
||||
with rootlog.nested("cleanup"):
|
||||
for machine in self.machines:
|
||||
machine.release()
|
||||
|
||||
def subtest(self, name: str) -> Iterator[None]:
|
||||
"""Group logs under a given test name"""
|
||||
with rootlog.nested(name):
|
||||
try:
|
||||
yield
|
||||
return True
|
||||
except Exception as e:
|
||||
rootlog.error(f'Test "{name}" failed with error: "{e}"')
|
||||
raise e
|
||||
|
||||
def test_symbols(self) -> Dict[str, Any]:
|
||||
@contextmanager
|
||||
def subtest(name: str) -> Iterator[None]:
|
||||
return self.subtest(name)
|
||||
|
||||
general_symbols = dict(
|
||||
start_all=self.start_all,
|
||||
test_script=self.test_script,
|
||||
machines=self.machines,
|
||||
vlans=self.vlans,
|
||||
driver=self,
|
||||
log=rootlog,
|
||||
os=os,
|
||||
create_machine=self.create_machine,
|
||||
subtest=subtest,
|
||||
run_tests=self.run_tests,
|
||||
join_all=self.join_all,
|
||||
retry=retry,
|
||||
serial_stdout_off=self.serial_stdout_off,
|
||||
serial_stdout_on=self.serial_stdout_on,
|
||||
Machine=Machine, # for typing
|
||||
)
|
||||
machine_symbols = {m.name: m for m in self.machines}
|
||||
# If there's exactly one machine, make it available under the name
|
||||
# "machine", even if it's not called that.
|
||||
if len(self.machines) == 1:
|
||||
(machine_symbols["machine"],) = self.machines
|
||||
vlan_symbols = {
|
||||
f"vlan{v.nr}": self.vlans[idx] for idx, v in enumerate(self.vlans)
|
||||
}
|
||||
print(
|
||||
"additionally exposed symbols:\n "
|
||||
+ ", ".join(map(lambda m: m.name, self.machines))
|
||||
+ ",\n "
|
||||
+ ", ".join(map(lambda v: f"vlan{v.nr}", self.vlans))
|
||||
+ ",\n "
|
||||
+ ", ".join(list(general_symbols.keys()))
|
||||
)
|
||||
return {**general_symbols, **machine_symbols, **vlan_symbols}
|
||||
|
||||
def test_script(self) -> None:
|
||||
"""Run the test script"""
|
||||
with rootlog.nested("run the VM test script"):
|
||||
symbols = self.test_symbols() # call eagerly
|
||||
exec(self.tests, symbols, None)
|
||||
|
||||
def run_tests(self) -> None:
|
||||
"""Run the test script (for non-interactive test runs)"""
|
||||
self.test_script()
|
||||
# TODO: Collect coverage data
|
||||
for machine in self.machines:
|
||||
if machine.is_up():
|
||||
machine.execute("sync")
|
||||
|
||||
def start_all(self) -> None:
|
||||
"""Start all machines"""
|
||||
with rootlog.nested("start all VMs"):
|
||||
for machine in self.machines:
|
||||
machine.start()
|
||||
|
||||
def join_all(self) -> None:
|
||||
"""Wait for all machines to shut down"""
|
||||
with rootlog.nested("wait for all VMs to finish"):
|
||||
for machine in self.machines:
|
||||
machine.wait_for_shutdown()
|
||||
|
||||
def create_machine(self, args: Dict[str, Any]) -> Machine:
|
||||
rootlog.warning(
|
||||
"Using legacy create_machine(), please instantiate the"
|
||||
"Machine class directly, instead"
|
||||
)
|
||||
tmp_dir = Path(os.environ.get("TMPDIR", tempfile.gettempdir()))
|
||||
tmp_dir.mkdir(mode=0o700, exist_ok=True)
|
||||
|
||||
if args.get("startCommand"):
|
||||
start_command: str = args.get("startCommand", "")
|
||||
cmd = NixStartScript(start_command)
|
||||
name = args.get("name", cmd.machine_name)
|
||||
else:
|
||||
cmd = Machine.create_startcommand(args) # type: ignore
|
||||
name = args.get("name", "machine")
|
||||
|
||||
return Machine(
|
||||
tmp_dir=tmp_dir,
|
||||
start_command=cmd,
|
||||
name=name,
|
||||
keep_vm_state=args.get("keep_vm_state", False),
|
||||
allow_reboot=args.get("allow_reboot", False),
|
||||
)
|
||||
|
||||
def serial_stdout_on(self) -> None:
|
||||
rootlog._print_serial_logs = True
|
||||
|
||||
def serial_stdout_off(self) -> None:
|
||||
rootlog._print_serial_logs = False
|
101
third_party/nixpkgs/nixos/lib/test-driver/test_driver/logger.py
vendored
Normal file
101
third_party/nixpkgs/nixos/lib/test-driver/test_driver/logger.py
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
from colorama import Style
|
||||
from contextlib import contextmanager
|
||||
from typing import Any, Dict, Iterator
|
||||
from queue import Queue, Empty
|
||||
from xml.sax.saxutils import XMLGenerator
|
||||
import codecs
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import unicodedata
|
||||
|
||||
|
||||
class Logger:
|
||||
def __init__(self) -> None:
|
||||
self.logfile = os.environ.get("LOGFILE", "/dev/null")
|
||||
self.logfile_handle = codecs.open(self.logfile, "wb")
|
||||
self.xml = XMLGenerator(self.logfile_handle, encoding="utf-8")
|
||||
self.queue: "Queue[Dict[str, str]]" = Queue()
|
||||
|
||||
self.xml.startDocument()
|
||||
self.xml.startElement("logfile", attrs={})
|
||||
|
||||
self._print_serial_logs = True
|
||||
|
||||
@staticmethod
|
||||
def _eprint(*args: object, **kwargs: Any) -> None:
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
def close(self) -> None:
|
||||
self.xml.endElement("logfile")
|
||||
self.xml.endDocument()
|
||||
self.logfile_handle.close()
|
||||
|
||||
def sanitise(self, message: str) -> str:
|
||||
return "".join(ch for ch in message if unicodedata.category(ch)[0] != "C")
|
||||
|
||||
def maybe_prefix(self, message: str, attributes: Dict[str, str]) -> str:
|
||||
if "machine" in attributes:
|
||||
return "{}: {}".format(attributes["machine"], message)
|
||||
return message
|
||||
|
||||
def log_line(self, message: str, attributes: Dict[str, str]) -> None:
|
||||
self.xml.startElement("line", attributes)
|
||||
self.xml.characters(message)
|
||||
self.xml.endElement("line")
|
||||
|
||||
def info(self, *args, **kwargs) -> None: # type: ignore
|
||||
self.log(*args, **kwargs)
|
||||
|
||||
def warning(self, *args, **kwargs) -> None: # type: ignore
|
||||
self.log(*args, **kwargs)
|
||||
|
||||
def error(self, *args, **kwargs) -> None: # type: ignore
|
||||
self.log(*args, **kwargs)
|
||||
sys.exit(1)
|
||||
|
||||
def log(self, message: str, attributes: Dict[str, str] = {}) -> None:
|
||||
self._eprint(self.maybe_prefix(message, attributes))
|
||||
self.drain_log_queue()
|
||||
self.log_line(message, attributes)
|
||||
|
||||
def log_serial(self, message: str, machine: str) -> None:
|
||||
self.enqueue({"msg": message, "machine": machine, "type": "serial"})
|
||||
if self._print_serial_logs:
|
||||
self._eprint(
|
||||
Style.DIM + "{} # {}".format(machine, message) + Style.RESET_ALL
|
||||
)
|
||||
|
||||
def enqueue(self, item: Dict[str, str]) -> None:
|
||||
self.queue.put(item)
|
||||
|
||||
def drain_log_queue(self) -> None:
|
||||
try:
|
||||
while True:
|
||||
item = self.queue.get_nowait()
|
||||
msg = self.sanitise(item["msg"])
|
||||
del item["msg"]
|
||||
self.log_line(msg, item)
|
||||
except Empty:
|
||||
pass
|
||||
|
||||
@contextmanager
|
||||
def nested(self, message: str, attributes: Dict[str, str] = {}) -> Iterator[None]:
|
||||
self._eprint(self.maybe_prefix(message, attributes))
|
||||
|
||||
self.xml.startElement("nest", attrs={})
|
||||
self.xml.startElement("head", attributes)
|
||||
self.xml.characters(message)
|
||||
self.xml.endElement("head")
|
||||
|
||||
tic = time.time()
|
||||
self.drain_log_queue()
|
||||
yield
|
||||
self.drain_log_queue()
|
||||
toc = time.time()
|
||||
self.log("(finished: {}, in {:.2f} seconds)".format(message, toc - tic))
|
||||
|
||||
self.xml.endElement("nest")
|
||||
|
||||
|
||||
rootlog = Logger()
|
424
third_party/nixpkgs/nixos/lib/test-driver/test-driver.py → third_party/nixpkgs/nixos/lib/test-driver/test_driver/machine.py
vendored
Executable file → Normal file
424
third_party/nixpkgs/nixos/lib/test-driver/test-driver.py → third_party/nixpkgs/nixos/lib/test-driver/test_driver/machine.py
vendored
Executable file → Normal file
|
@ -1,19 +1,11 @@
|
|||
#! /somewhere/python3
|
||||
from contextlib import contextmanager, _GeneratorContextManager
|
||||
from queue import Queue, Empty
|
||||
from typing import Tuple, Any, Callable, Dict, Iterator, Optional, List, Iterable
|
||||
from xml.sax.saxutils import XMLGenerator
|
||||
from colorama import Style
|
||||
from contextlib import _GeneratorContextManager
|
||||
from pathlib import Path
|
||||
import queue
|
||||
import io
|
||||
import threading
|
||||
import argparse
|
||||
from queue import Queue
|
||||
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple
|
||||
import base64
|
||||
import codecs
|
||||
import io
|
||||
import os
|
||||
import ptpython.repl
|
||||
import pty
|
||||
import queue
|
||||
import re
|
||||
import shlex
|
||||
import shutil
|
||||
|
@ -21,8 +13,10 @@ import socket
|
|||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import threading
|
||||
import time
|
||||
import unicodedata
|
||||
|
||||
from test_driver.logger import rootlog
|
||||
|
||||
CHAR_TO_KEY = {
|
||||
"A": "shift-a",
|
||||
|
@ -88,115 +82,10 @@ CHAR_TO_KEY = {
|
|||
}
|
||||
|
||||
|
||||
class Logger:
|
||||
def __init__(self) -> None:
|
||||
self.logfile = os.environ.get("LOGFILE", "/dev/null")
|
||||
self.logfile_handle = codecs.open(self.logfile, "wb")
|
||||
self.xml = XMLGenerator(self.logfile_handle, encoding="utf-8")
|
||||
self.queue: "Queue[Dict[str, str]]" = Queue()
|
||||
|
||||
self.xml.startDocument()
|
||||
self.xml.startElement("logfile", attrs={})
|
||||
|
||||
self._print_serial_logs = True
|
||||
|
||||
@staticmethod
|
||||
def _eprint(*args: object, **kwargs: Any) -> None:
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
|
||||
def close(self) -> None:
|
||||
self.xml.endElement("logfile")
|
||||
self.xml.endDocument()
|
||||
self.logfile_handle.close()
|
||||
|
||||
def sanitise(self, message: str) -> str:
|
||||
return "".join(ch for ch in message if unicodedata.category(ch)[0] != "C")
|
||||
|
||||
def maybe_prefix(self, message: str, attributes: Dict[str, str]) -> str:
|
||||
if "machine" in attributes:
|
||||
return "{}: {}".format(attributes["machine"], message)
|
||||
return message
|
||||
|
||||
def log_line(self, message: str, attributes: Dict[str, str]) -> None:
|
||||
self.xml.startElement("line", attributes)
|
||||
self.xml.characters(message)
|
||||
self.xml.endElement("line")
|
||||
|
||||
def info(self, *args, **kwargs) -> None: # type: ignore
|
||||
self.log(*args, **kwargs)
|
||||
|
||||
def warning(self, *args, **kwargs) -> None: # type: ignore
|
||||
self.log(*args, **kwargs)
|
||||
|
||||
def error(self, *args, **kwargs) -> None: # type: ignore
|
||||
self.log(*args, **kwargs)
|
||||
sys.exit(1)
|
||||
|
||||
def log(self, message: str, attributes: Dict[str, str] = {}) -> None:
|
||||
self._eprint(self.maybe_prefix(message, attributes))
|
||||
self.drain_log_queue()
|
||||
self.log_line(message, attributes)
|
||||
|
||||
def log_serial(self, message: str, machine: str) -> None:
|
||||
self.enqueue({"msg": message, "machine": machine, "type": "serial"})
|
||||
if self._print_serial_logs:
|
||||
self._eprint(
|
||||
Style.DIM + "{} # {}".format(machine, message) + Style.RESET_ALL
|
||||
)
|
||||
|
||||
def enqueue(self, item: Dict[str, str]) -> None:
|
||||
self.queue.put(item)
|
||||
|
||||
def drain_log_queue(self) -> None:
|
||||
try:
|
||||
while True:
|
||||
item = self.queue.get_nowait()
|
||||
msg = self.sanitise(item["msg"])
|
||||
del item["msg"]
|
||||
self.log_line(msg, item)
|
||||
except Empty:
|
||||
pass
|
||||
|
||||
@contextmanager
|
||||
def nested(self, message: str, attributes: Dict[str, str] = {}) -> Iterator[None]:
|
||||
self._eprint(self.maybe_prefix(message, attributes))
|
||||
|
||||
self.xml.startElement("nest", attrs={})
|
||||
self.xml.startElement("head", attributes)
|
||||
self.xml.characters(message)
|
||||
self.xml.endElement("head")
|
||||
|
||||
tic = time.time()
|
||||
self.drain_log_queue()
|
||||
yield
|
||||
self.drain_log_queue()
|
||||
toc = time.time()
|
||||
self.log("(finished: {}, in {:.2f} seconds)".format(message, toc - tic))
|
||||
|
||||
self.xml.endElement("nest")
|
||||
|
||||
|
||||
rootlog = Logger()
|
||||
|
||||
|
||||
def make_command(args: list) -> str:
|
||||
return " ".join(map(shlex.quote, (map(str, args))))
|
||||
|
||||
|
||||
def retry(fn: Callable, timeout: int = 900) -> None:
|
||||
"""Call the given function repeatedly, with 1 second intervals,
|
||||
until it returns True or a timeout is reached.
|
||||
"""
|
||||
|
||||
for _ in range(timeout):
|
||||
if fn(False):
|
||||
return
|
||||
time.sleep(1)
|
||||
|
||||
if not fn(True):
|
||||
raise Exception(f"action timed out after {timeout} seconds")
|
||||
|
||||
|
||||
def _perform_ocr_on_screenshot(
|
||||
screenshot_path: str, model_ids: Iterable[int]
|
||||
) -> List[str]:
|
||||
|
@ -228,6 +117,20 @@ def _perform_ocr_on_screenshot(
|
|||
return model_results
|
||||
|
||||
|
||||
def retry(fn: Callable, timeout: int = 900) -> None:
|
||||
"""Call the given function repeatedly, with 1 second intervals,
|
||||
until it returns True or a timeout is reached.
|
||||
"""
|
||||
|
||||
for _ in range(timeout):
|
||||
if fn(False):
|
||||
return
|
||||
time.sleep(1)
|
||||
|
||||
if not fn(True):
|
||||
raise Exception(f"action timed out after {timeout} seconds")
|
||||
|
||||
|
||||
class StartCommand:
|
||||
"""The Base Start Command knows how to append the necesary
|
||||
runtime qemu options as determined by a particular test driver
|
||||
|
@ -1066,286 +969,3 @@ class Machine:
|
|||
self.shell.close()
|
||||
self.monitor.close()
|
||||
self.serial_thread.join()
|
||||
|
||||
|
||||
class VLan:
|
||||
"""This class handles a VLAN that the run-vm scripts identify via its
|
||||
number handles. The network's lifetime equals the object's lifetime.
|
||||
"""
|
||||
|
||||
nr: int
|
||||
socket_dir: Path
|
||||
|
||||
process: subprocess.Popen
|
||||
pid: int
|
||||
fd: io.TextIOBase
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<Vlan Nr. {self.nr}>"
|
||||
|
||||
def __init__(self, nr: int, tmp_dir: Path):
|
||||
self.nr = nr
|
||||
self.socket_dir = tmp_dir / f"vde{self.nr}.ctl"
|
||||
|
||||
# TODO: don't side-effect environment here
|
||||
os.environ[f"QEMU_VDE_SOCKET_{self.nr}"] = str(self.socket_dir)
|
||||
|
||||
rootlog.info("start vlan")
|
||||
pty_master, pty_slave = pty.openpty()
|
||||
|
||||
self.process = subprocess.Popen(
|
||||
["vde_switch", "-s", self.socket_dir, "--dirmode", "0700"],
|
||||
stdin=pty_slave,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
shell=False,
|
||||
)
|
||||
self.pid = self.process.pid
|
||||
self.fd = os.fdopen(pty_master, "w")
|
||||
self.fd.write("version\n")
|
||||
|
||||
# TODO: perl version checks if this can be read from
|
||||
# an if not, dies. we could hang here forever. Fix it.
|
||||
assert self.process.stdout is not None
|
||||
self.process.stdout.readline()
|
||||
if not (self.socket_dir / "ctl").exists():
|
||||
rootlog.error("cannot start vde_switch")
|
||||
|
||||
rootlog.info(f"running vlan (pid {self.pid})")
|
||||
|
||||
def __del__(self) -> None:
|
||||
rootlog.info(f"kill vlan (pid {self.pid})")
|
||||
self.fd.close()
|
||||
self.process.terminate()
|
||||
|
||||
|
||||
class Driver:
|
||||
"""A handle to the driver that sets up the environment
|
||||
and runs the tests"""
|
||||
|
||||
tests: str
|
||||
vlans: List[VLan]
|
||||
machines: List[Machine]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
start_scripts: List[str],
|
||||
vlans: List[int],
|
||||
tests: str,
|
||||
keep_vm_state: bool = False,
|
||||
):
|
||||
self.tests = tests
|
||||
|
||||
tmp_dir = Path(os.environ.get("TMPDIR", tempfile.gettempdir()))
|
||||
tmp_dir.mkdir(mode=0o700, exist_ok=True)
|
||||
|
||||
with rootlog.nested("start all VLans"):
|
||||
self.vlans = [VLan(nr, tmp_dir) for nr in vlans]
|
||||
|
||||
def cmd(scripts: List[str]) -> Iterator[NixStartScript]:
|
||||
for s in scripts:
|
||||
yield NixStartScript(s)
|
||||
|
||||
self.machines = [
|
||||
Machine(
|
||||
start_command=cmd,
|
||||
keep_vm_state=keep_vm_state,
|
||||
name=cmd.machine_name,
|
||||
tmp_dir=tmp_dir,
|
||||
)
|
||||
for cmd in cmd(start_scripts)
|
||||
]
|
||||
|
||||
def __enter__(self) -> "Driver":
|
||||
return self
|
||||
|
||||
def __exit__(self, *_: Any) -> None:
|
||||
with rootlog.nested("cleanup"):
|
||||
for machine in self.machines:
|
||||
machine.release()
|
||||
|
||||
def subtest(self, name: str) -> Iterator[None]:
|
||||
"""Group logs under a given test name"""
|
||||
with rootlog.nested(name):
|
||||
try:
|
||||
yield
|
||||
return True
|
||||
except Exception as e:
|
||||
rootlog.error(f'Test "{name}" failed with error: "{e}"')
|
||||
raise e
|
||||
|
||||
def test_symbols(self) -> Dict[str, Any]:
|
||||
@contextmanager
|
||||
def subtest(name: str) -> Iterator[None]:
|
||||
return self.subtest(name)
|
||||
|
||||
general_symbols = dict(
|
||||
start_all=self.start_all,
|
||||
test_script=self.test_script,
|
||||
machines=self.machines,
|
||||
vlans=self.vlans,
|
||||
driver=self,
|
||||
log=rootlog,
|
||||
os=os,
|
||||
create_machine=self.create_machine,
|
||||
subtest=subtest,
|
||||
run_tests=self.run_tests,
|
||||
join_all=self.join_all,
|
||||
retry=retry,
|
||||
serial_stdout_off=self.serial_stdout_off,
|
||||
serial_stdout_on=self.serial_stdout_on,
|
||||
Machine=Machine, # for typing
|
||||
)
|
||||
machine_symbols = {m.name: m for m in self.machines}
|
||||
# If there's exactly one machine, make it available under the name
|
||||
# "machine", even if it's not called that.
|
||||
if len(self.machines) == 1:
|
||||
(machine_symbols["machine"],) = self.machines
|
||||
vlan_symbols = {
|
||||
f"vlan{v.nr}": self.vlans[idx] for idx, v in enumerate(self.vlans)
|
||||
}
|
||||
print(
|
||||
"additionally exposed symbols:\n "
|
||||
+ ", ".join(map(lambda m: m.name, self.machines))
|
||||
+ ",\n "
|
||||
+ ", ".join(map(lambda v: f"vlan{v.nr}", self.vlans))
|
||||
+ ",\n "
|
||||
+ ", ".join(list(general_symbols.keys()))
|
||||
)
|
||||
return {**general_symbols, **machine_symbols, **vlan_symbols}
|
||||
|
||||
def test_script(self) -> None:
|
||||
"""Run the test script"""
|
||||
with rootlog.nested("run the VM test script"):
|
||||
symbols = self.test_symbols() # call eagerly
|
||||
exec(self.tests, symbols, None)
|
||||
|
||||
def run_tests(self) -> None:
|
||||
"""Run the test script (for non-interactive test runs)"""
|
||||
self.test_script()
|
||||
# TODO: Collect coverage data
|
||||
for machine in self.machines:
|
||||
if machine.is_up():
|
||||
machine.execute("sync")
|
||||
|
||||
def start_all(self) -> None:
|
||||
"""Start all machines"""
|
||||
with rootlog.nested("start all VMs"):
|
||||
for machine in self.machines:
|
||||
machine.start()
|
||||
|
||||
def join_all(self) -> None:
|
||||
"""Wait for all machines to shut down"""
|
||||
with rootlog.nested("wait for all VMs to finish"):
|
||||
for machine in self.machines:
|
||||
machine.wait_for_shutdown()
|
||||
|
||||
def create_machine(self, args: Dict[str, Any]) -> Machine:
|
||||
rootlog.warning(
|
||||
"Using legacy create_machine(), please instantiate the"
|
||||
"Machine class directly, instead"
|
||||
)
|
||||
tmp_dir = Path(os.environ.get("TMPDIR", tempfile.gettempdir()))
|
||||
tmp_dir.mkdir(mode=0o700, exist_ok=True)
|
||||
|
||||
if args.get("startCommand"):
|
||||
start_command: str = args.get("startCommand", "")
|
||||
cmd = NixStartScript(start_command)
|
||||
name = args.get("name", cmd.machine_name)
|
||||
else:
|
||||
cmd = Machine.create_startcommand(args) # type: ignore
|
||||
name = args.get("name", "machine")
|
||||
|
||||
return Machine(
|
||||
tmp_dir=tmp_dir,
|
||||
start_command=cmd,
|
||||
name=name,
|
||||
keep_vm_state=args.get("keep_vm_state", False),
|
||||
allow_reboot=args.get("allow_reboot", False),
|
||||
)
|
||||
|
||||
def serial_stdout_on(self) -> None:
|
||||
rootlog._print_serial_logs = True
|
||||
|
||||
def serial_stdout_off(self) -> None:
|
||||
rootlog._print_serial_logs = False
|
||||
|
||||
|
||||
class EnvDefault(argparse.Action):
|
||||
"""An argpars Action that takes values from the specified
|
||||
environment variable as the flags default value.
|
||||
"""
|
||||
|
||||
def __init__(self, envvar, required=False, default=None, nargs=None, **kwargs): # type: ignore
|
||||
if not default and envvar:
|
||||
if envvar in os.environ:
|
||||
if nargs is not None and (nargs.isdigit() or nargs in ["*", "+"]):
|
||||
default = os.environ[envvar].split()
|
||||
else:
|
||||
default = os.environ[envvar]
|
||||
kwargs["help"] = (
|
||||
kwargs["help"] + f" (default from environment: {default})"
|
||||
)
|
||||
if required and default:
|
||||
required = False
|
||||
super(EnvDefault, self).__init__(
|
||||
default=default, required=required, nargs=nargs, **kwargs
|
||||
)
|
||||
|
||||
def __call__(self, parser, namespace, values, option_string=None): # type: ignore
|
||||
setattr(namespace, self.dest, values)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
arg_parser = argparse.ArgumentParser(prog="nixos-test-driver")
|
||||
arg_parser.add_argument(
|
||||
"-K",
|
||||
"--keep-vm-state",
|
||||
help="re-use a VM state coming from a previous run",
|
||||
action="store_true",
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
"-I",
|
||||
"--interactive",
|
||||
help="drop into a python repl and run the tests interactively",
|
||||
action="store_true",
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
"--start-scripts",
|
||||
metavar="START-SCRIPT",
|
||||
action=EnvDefault,
|
||||
envvar="startScripts",
|
||||
nargs="*",
|
||||
help="start scripts for participating virtual machines",
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
"--vlans",
|
||||
metavar="VLAN",
|
||||
action=EnvDefault,
|
||||
envvar="vlans",
|
||||
nargs="*",
|
||||
help="vlans to span by the driver",
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
"testscript",
|
||||
action=EnvDefault,
|
||||
envvar="testScript",
|
||||
help="the test script to run",
|
||||
type=Path,
|
||||
)
|
||||
|
||||
args = arg_parser.parse_args()
|
||||
|
||||
if not args.keep_vm_state:
|
||||
rootlog.info("Machine state will be reset. To keep it, pass --keep-vm-state")
|
||||
|
||||
with Driver(
|
||||
args.start_scripts, args.vlans, args.testscript.read_text(), args.keep_vm_state
|
||||
) as driver:
|
||||
if args.interactive:
|
||||
ptpython.repl.embed(driver.test_symbols(), {})
|
||||
else:
|
||||
tic = time.time()
|
||||
driver.run_tests()
|
||||
toc = time.time()
|
||||
rootlog.info(f"test script finished in {(toc-tic):.2f}s")
|
58
third_party/nixpkgs/nixos/lib/test-driver/test_driver/vlan.py
vendored
Normal file
58
third_party/nixpkgs/nixos/lib/test-driver/test_driver/vlan.py
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
from pathlib import Path
|
||||
import io
|
||||
import os
|
||||
import pty
|
||||
import subprocess
|
||||
|
||||
from test_driver.logger import rootlog
|
||||
|
||||
|
||||
class VLan:
|
||||
"""This class handles a VLAN that the run-vm scripts identify via its
|
||||
number handles. The network's lifetime equals the object's lifetime.
|
||||
"""
|
||||
|
||||
nr: int
|
||||
socket_dir: Path
|
||||
|
||||
process: subprocess.Popen
|
||||
pid: int
|
||||
fd: io.TextIOBase
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<Vlan Nr. {self.nr}>"
|
||||
|
||||
def __init__(self, nr: int, tmp_dir: Path):
|
||||
self.nr = nr
|
||||
self.socket_dir = tmp_dir / f"vde{self.nr}.ctl"
|
||||
|
||||
# TODO: don't side-effect environment here
|
||||
os.environ[f"QEMU_VDE_SOCKET_{self.nr}"] = str(self.socket_dir)
|
||||
|
||||
rootlog.info("start vlan")
|
||||
pty_master, pty_slave = pty.openpty()
|
||||
|
||||
self.process = subprocess.Popen(
|
||||
["vde_switch", "-s", self.socket_dir, "--dirmode", "0700"],
|
||||
stdin=pty_slave,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
shell=False,
|
||||
)
|
||||
self.pid = self.process.pid
|
||||
self.fd = os.fdopen(pty_master, "w")
|
||||
self.fd.write("version\n")
|
||||
|
||||
# TODO: perl version checks if this can be read from
|
||||
# an if not, dies. we could hang here forever. Fix it.
|
||||
assert self.process.stdout is not None
|
||||
self.process.stdout.readline()
|
||||
if not (self.socket_dir / "ctl").exists():
|
||||
rootlog.error("cannot start vde_switch")
|
||||
|
||||
rootlog.info(f"running vlan (pid {self.pid})")
|
||||
|
||||
def __del__(self) -> None:
|
||||
rootlog.info(f"kill vlan (pid {self.pid})")
|
||||
self.fd.close()
|
||||
self.process.terminate()
|
73
third_party/nixpkgs/nixos/lib/testing-python.nix
vendored
73
third_party/nixpkgs/nixos/lib/testing-python.nix
vendored
|
@ -16,65 +16,6 @@ rec {
|
|||
|
||||
inherit pkgs;
|
||||
|
||||
# Reifies and correctly wraps the python test driver for
|
||||
# the respective qemu version and with or without ocr support
|
||||
pythonTestDriver = {
|
||||
qemu_pkg ? pkgs.qemu_test
|
||||
, enableOCR ? false
|
||||
}:
|
||||
let
|
||||
name = "nixos-test-driver";
|
||||
testDriverScript = ./test-driver/test-driver.py;
|
||||
ocrProg = tesseract4.override { enableLanguages = [ "eng" ]; };
|
||||
imagemagick_tiff = imagemagick_light.override { inherit libtiff; };
|
||||
in stdenv.mkDerivation {
|
||||
inherit name;
|
||||
|
||||
nativeBuildInputs = [ makeWrapper ];
|
||||
buildInputs = [ (python3.withPackages (p: [ p.ptpython p.colorama ])) ];
|
||||
checkInputs = with python3Packages; [ pylint black mypy ];
|
||||
|
||||
dontUnpack = true;
|
||||
|
||||
preferLocalBuild = true;
|
||||
|
||||
buildPhase = ''
|
||||
python <<EOF
|
||||
from pydoc import importfile
|
||||
with open('driver-symbols', 'w') as fp:
|
||||
t = importfile('${testDriverScript}')
|
||||
d = t.Driver([],[],"")
|
||||
test_symbols = d.test_symbols()
|
||||
fp.write(','.join(test_symbols.keys()))
|
||||
EOF
|
||||
'';
|
||||
|
||||
doCheck = true;
|
||||
checkPhase = ''
|
||||
mypy --disallow-untyped-defs \
|
||||
--no-implicit-optional \
|
||||
--ignore-missing-imports ${testDriverScript}
|
||||
pylint --errors-only ${testDriverScript}
|
||||
black --check --diff ${testDriverScript}
|
||||
'';
|
||||
|
||||
installPhase =
|
||||
''
|
||||
mkdir -p $out/bin
|
||||
cp ${testDriverScript} $out/bin/nixos-test-driver
|
||||
chmod u+x $out/bin/nixos-test-driver
|
||||
# TODO: copy user script part into this file (append)
|
||||
|
||||
wrapProgram $out/bin/nixos-test-driver \
|
||||
--argv0 ${name} \
|
||||
--prefix PATH : "${lib.makeBinPath [ qemu_pkg vde2 netpbm coreutils socat ]}" \
|
||||
${lib.optionalString enableOCR
|
||||
"--prefix PATH : '${ocrProg}/bin:${imagemagick_tiff}/bin'"} \
|
||||
|
||||
install -m 0644 -vD driver-symbols $out/nix-support/driver-symbols
|
||||
'';
|
||||
};
|
||||
|
||||
# Run an automated test suite in the given virtual network.
|
||||
runTests = { driver, pos }:
|
||||
stdenv.mkDerivation {
|
||||
|
@ -112,8 +53,15 @@ rec {
|
|||
, passthru ? {}
|
||||
}:
|
||||
let
|
||||
# FIXME: get this pkg from the module system
|
||||
testDriver = pythonTestDriver { inherit qemu_pkg enableOCR;};
|
||||
# Reifies and correctly wraps the python test driver for
|
||||
# the respective qemu version and with or without ocr support
|
||||
testDriver = pkgs.callPackage ./test-driver {
|
||||
inherit enableOCR;
|
||||
qemu_pkg = qemu_test;
|
||||
imagemagick_light = imagemagick_light.override { inherit libtiff; };
|
||||
tesseract4 = tesseract4.override { enableLanguages = [ "eng" ]; };
|
||||
};
|
||||
|
||||
|
||||
testDriverName =
|
||||
let
|
||||
|
@ -178,10 +126,11 @@ rec {
|
|||
echo -n "$testScript" > $out/test-script
|
||||
ln -s ${testDriver}/bin/nixos-test-driver $out/bin/nixos-test-driver
|
||||
|
||||
${testDriver}/bin/generate-driver-symbols
|
||||
${lib.optionalString (!skipLint) ''
|
||||
PYFLAKES_BUILTINS="$(
|
||||
echo -n ${lib.escapeShellArg (lib.concatStringsSep "," nodeHostNames)},
|
||||
< ${lib.escapeShellArg "${testDriver}/nix-support/driver-symbols"}
|
||||
< ${lib.escapeShellArg "driver-symbols"}
|
||||
)" ${python3Packages.pyflakes}/bin/pyflakes $out/test-script
|
||||
''}
|
||||
|
||||
|
|
7
third_party/nixpkgs/nixos/lib/utils.nix
vendored
7
third_party/nixpkgs/nixos/lib/utils.nix
vendored
|
@ -1,4 +1,4 @@
|
|||
pkgs: with pkgs.lib;
|
||||
{ lib, config, pkgs }: with lib;
|
||||
|
||||
rec {
|
||||
|
||||
|
@ -165,4 +165,9 @@ rec {
|
|||
${builtins.toJSON set}
|
||||
EOF
|
||||
'';
|
||||
|
||||
systemdUtils = {
|
||||
lib = import ./systemd-lib.nix { inherit lib config pkgs; };
|
||||
unitOptions = import ./systemd-unit-options.nix { inherit lib systemdUtils; };
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
# /etc files related to networking, such as /etc/services.
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.networking;
|
||||
opt = options.networking;
|
||||
|
||||
localhostMultiple = any (elem "localhost") (attrValues (removeAttrs cfg.hosts [ "127.0.0.1" "::1" ]));
|
||||
|
||||
|
@ -78,6 +79,7 @@ in
|
|||
httpProxy = lib.mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = cfg.proxy.default;
|
||||
defaultText = literalExpression "config.${opt.proxy.default}";
|
||||
description = ''
|
||||
This option specifies the http_proxy environment variable.
|
||||
'';
|
||||
|
@ -87,6 +89,7 @@ in
|
|||
httpsProxy = lib.mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = cfg.proxy.default;
|
||||
defaultText = literalExpression "config.${opt.proxy.default}";
|
||||
description = ''
|
||||
This option specifies the https_proxy environment variable.
|
||||
'';
|
||||
|
@ -96,6 +99,7 @@ in
|
|||
ftpProxy = lib.mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = cfg.proxy.default;
|
||||
defaultText = literalExpression "config.${opt.proxy.default}";
|
||||
description = ''
|
||||
This option specifies the ftp_proxy environment variable.
|
||||
'';
|
||||
|
@ -105,6 +109,7 @@ in
|
|||
rsyncProxy = lib.mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = cfg.proxy.default;
|
||||
defaultText = literalExpression "config.${opt.proxy.default}";
|
||||
description = ''
|
||||
This option specifies the rsync_proxy environment variable.
|
||||
'';
|
||||
|
@ -114,6 +119,7 @@ in
|
|||
allProxy = lib.mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = cfg.proxy.default;
|
||||
defaultText = literalExpression "config.${opt.proxy.default}";
|
||||
description = ''
|
||||
This option specifies the all_proxy environment variable.
|
||||
'';
|
||||
|
|
|
@ -41,12 +41,17 @@ let
|
|||
pkgs.zstd
|
||||
];
|
||||
|
||||
defaultPackages = map (pkg: setPrio ((pkg.meta.priority or 5) + 3) pkg)
|
||||
[ pkgs.nano
|
||||
pkgs.perl
|
||||
pkgs.rsync
|
||||
pkgs.strace
|
||||
defaultPackageNames =
|
||||
[ "nano"
|
||||
"perl"
|
||||
"rsync"
|
||||
"strace"
|
||||
];
|
||||
defaultPackages =
|
||||
map
|
||||
(n: let pkg = pkgs.${n}; in setPrio ((pkg.meta.priority or 5) + 3) pkg)
|
||||
defaultPackageNames;
|
||||
defaultPackagesText = "[ ${concatMapStringsSep " " (n: "pkgs.${n}") defaultPackageNames } ]";
|
||||
|
||||
in
|
||||
|
||||
|
@ -73,6 +78,11 @@ in
|
|||
defaultPackages = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = defaultPackages;
|
||||
defaultText = literalDocBook ''
|
||||
these packages, with their <literal>meta.priority</literal> numerically increased
|
||||
(thus lowering their installation priority):
|
||||
<programlisting>${defaultPackagesText}</programlisting>
|
||||
'';
|
||||
example = [];
|
||||
description = ''
|
||||
Set of default packages that aren't strictly necessary
|
||||
|
|
47
third_party/nixpkgs/nixos/modules/hardware/cpu/intel-sgx.nix
vendored
Normal file
47
third_party/nixpkgs/nixos/modules/hardware/cpu/intel-sgx.nix
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
{ config, lib, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.hardware.cpu.intel.sgx.provision;
|
||||
defaultGroup = "sgx_prv";
|
||||
in
|
||||
{
|
||||
options.hardware.cpu.intel.sgx.provision = {
|
||||
enable = mkEnableOption "access to the Intel SGX provisioning device";
|
||||
user = mkOption {
|
||||
description = "Owner to assign to the SGX provisioning device.";
|
||||
type = types.str;
|
||||
default = "root";
|
||||
};
|
||||
group = mkOption {
|
||||
description = "Group to assign to the SGX provisioning device.";
|
||||
type = types.str;
|
||||
default = defaultGroup;
|
||||
};
|
||||
mode = mkOption {
|
||||
description = "Mode to set for the SGX provisioning device.";
|
||||
type = types.str;
|
||||
default = "0660";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = hasAttr cfg.user config.users.users;
|
||||
message = "Given user does not exist";
|
||||
}
|
||||
{
|
||||
assertion = (cfg.group == defaultGroup) || (hasAttr cfg.group config.users.groups);
|
||||
message = "Given group does not exist";
|
||||
}
|
||||
];
|
||||
|
||||
users.groups = optionalAttrs (cfg.group == defaultGroup) {
|
||||
"${cfg.group}" = { };
|
||||
};
|
||||
|
||||
services.udev.extraRules = ''
|
||||
SUBSYSTEM=="misc", KERNEL=="sgx_provision", OWNER="${cfg.user}", GROUP="${cfg.group}", MODE="${cfg.mode}"
|
||||
'';
|
||||
};
|
||||
}
|
37
third_party/nixpkgs/nixos/modules/hardware/gpgsmartcards.nix
vendored
Normal file
37
third_party/nixpkgs/nixos/modules/hardware/gpgsmartcards.nix
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
# gnupg's manual describes how to setup ccid udev rules:
|
||||
# https://www.gnupg.org/howtos/card-howto/en/ch02s03.html
|
||||
# gnupg folks advised me (https://dev.gnupg.org/T5409) to look at debian's rules:
|
||||
# https://salsa.debian.org/debian/gnupg2/-/blob/debian/main/debian/scdaemon.udev
|
||||
|
||||
# the latest rev of the entire debian gnupg2 repo as of 2021-04-28
|
||||
# the scdaemon.udev file was last commited on 2021-01-05 (7817a03):
|
||||
scdaemonUdevRev = "01898735a015541e3ffb43c7245ac1e612f40836";
|
||||
|
||||
scdaemonRules = pkgs.fetchurl {
|
||||
url = "https://salsa.debian.org/debian/gnupg2/-/raw/${scdaemonUdevRev}/debian/scdaemon.udev";
|
||||
sha256 = "08v0vp6950bz7galvc92zdss89y9vcwbinmbfcdldy8x72w6rqr3";
|
||||
};
|
||||
|
||||
# per debian's udev deb hook (https://man7.org/linux/man-pages/man1/dh_installudev.1.html)
|
||||
destination = "60-scdaemon.rules";
|
||||
|
||||
scdaemonUdevRulesPkg = pkgs.runCommandNoCC "scdaemon-udev-rules" {} ''
|
||||
loc="$out/lib/udev/rules.d/"
|
||||
mkdir -p "''${loc}"
|
||||
cp "${scdaemonRules}" "''${loc}/${destination}"
|
||||
'';
|
||||
|
||||
cfg = config.hardware.gpgSmartcards;
|
||||
in {
|
||||
options.hardware.gpgSmartcards = {
|
||||
enable = mkEnableOption "udev rules for gnupg smart cards";
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.udev.packages = [ scdaemonUdevRulesPkg ];
|
||||
};
|
||||
}
|
|
@ -5,7 +5,6 @@ let
|
|||
cfg = config.hardware.keyboard.zsa;
|
||||
in
|
||||
{
|
||||
# TODO: make group configurable like in https://github.com/NixOS/nixpkgs/blob/0b2b4b8c4e729535a61db56468809c5c2d3d175c/pkgs/tools/security/nitrokey-app/udev-rules.nix ?
|
||||
options.hardware.keyboard.zsa = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
|
@ -14,7 +13,6 @@ in
|
|||
Enables udev rules for keyboards from ZSA like the ErgoDox EZ, Planck EZ and Moonlander Mark I.
|
||||
You need it when you want to flash a new configuration on the keyboard
|
||||
or use their live training in the browser.
|
||||
Access to the keyboard is granted to users in the "plugdev" group.
|
||||
You may want to install the wally-cli package.
|
||||
'';
|
||||
};
|
||||
|
@ -22,6 +20,5 @@ in
|
|||
|
||||
config = mkIf cfg.enable {
|
||||
services.udev.packages = [ pkgs.zsa-udev-rules ];
|
||||
users.groups.plugdev = {};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ in
|
|||
|
||||
config = mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.path;
|
||||
description = ''
|
||||
Path to the configuration file which maps the memory, IRQs
|
||||
and ports used by the PCMCIA hardware.
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkOption mkEnableOption types mkIf mkMerge optional versionOlder;
|
||||
inherit (lib) literalExpression mkOption mkEnableOption types mkIf mkMerge optional versionOlder;
|
||||
cfg = config.hardware.system76;
|
||||
opt = options.hardware.system76;
|
||||
|
||||
kpkgs = config.boot.kernelPackages;
|
||||
modules = [ "system76" "system76-io" ] ++ (optional (versionOlder kpkgs.kernel.version "5.5") "system76-acpi");
|
||||
|
@ -60,6 +61,7 @@ in {
|
|||
|
||||
firmware-daemon.enable = mkOption {
|
||||
default = cfg.enableAll;
|
||||
defaultText = literalExpression "config.${opt.enableAll}";
|
||||
example = true;
|
||||
description = "Whether to enable the system76 firmware daemon";
|
||||
type = types.bool;
|
||||
|
@ -67,6 +69,7 @@ in {
|
|||
|
||||
kernel-modules.enable = mkOption {
|
||||
default = cfg.enableAll;
|
||||
defaultText = literalExpression "config.${opt.enableAll}";
|
||||
example = true;
|
||||
description = "Whether to make the system76 out-of-tree kernel modules available";
|
||||
type = types.bool;
|
||||
|
@ -74,6 +77,7 @@ in {
|
|||
|
||||
power-daemon.enable = mkOption {
|
||||
default = cfg.enableAll;
|
||||
defaultText = literalExpression "config.${opt.enableAll}";
|
||||
example = true;
|
||||
description = "Whether to enable the system76 power daemon";
|
||||
type = types.bool;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, lib, pkgs, baseModules, extraModules, modules, modulesPath, ... }:
|
||||
{ config, lib, pkgs, extendModules, noUserModules, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -6,11 +6,8 @@ let
|
|||
|
||||
cfg = config.documentation;
|
||||
|
||||
manualModules =
|
||||
baseModules
|
||||
# Modules for which to show options even when not imported
|
||||
++ [ ../virtualisation/qemu-vm.nix ]
|
||||
++ optionals cfg.nixos.includeAllModules (extraModules ++ modules);
|
||||
/* Modules for which to show options even when not imported. */
|
||||
extraDocModules = [ ../virtualisation/qemu-vm.nix ];
|
||||
|
||||
/* For the purpose of generating docs, evaluate options with each derivation
|
||||
in `pkgs` (recursively) replaced by a fake with path "\${pkgs.attribute.path}".
|
||||
|
@ -24,13 +21,10 @@ let
|
|||
extraSources = cfg.nixos.extraModuleSources;
|
||||
options =
|
||||
let
|
||||
scrubbedEval = evalModules {
|
||||
modules = [ { nixpkgs.localSystem = config.nixpkgs.localSystem; } ] ++ manualModules;
|
||||
args = (config._module.args) // { modules = [ ]; };
|
||||
specialArgs = {
|
||||
pkgs = scrubDerivations "pkgs" pkgs;
|
||||
inherit modulesPath;
|
||||
};
|
||||
extendNixOS = if cfg.nixos.includeAllModules then extendModules else noUserModules.extendModules;
|
||||
scrubbedEval = extendNixOS {
|
||||
modules = extraDocModules;
|
||||
specialArgs.pkgs = scrubDerivations "pkgs" pkgs;
|
||||
};
|
||||
scrubDerivations = namePrefix: pkgSet: mapAttrs
|
||||
(name: value:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{ pkgs, ... }:
|
||||
{ lib, config, pkgs, ... }:
|
||||
|
||||
{
|
||||
_module.args = {
|
||||
utils = import ../../lib/utils.nix pkgs;
|
||||
utils = import ../../lib/utils.nix { inherit lib config pkgs; };
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.system.nixos;
|
||||
opt = options.system.nixos;
|
||||
in
|
||||
|
||||
{
|
||||
|
@ -53,6 +54,7 @@ in
|
|||
stateVersion = mkOption {
|
||||
type = types.str;
|
||||
default = cfg.release;
|
||||
defaultText = literalExpression "config.${opt.release}";
|
||||
description = ''
|
||||
Every once in a while, a new NixOS release may change
|
||||
configuration defaults in a way incompatible with stateful
|
||||
|
|
|
@ -45,11 +45,13 @@
|
|||
./hardware/ckb-next.nix
|
||||
./hardware/cpu/amd-microcode.nix
|
||||
./hardware/cpu/intel-microcode.nix
|
||||
./hardware/cpu/intel-sgx.nix
|
||||
./hardware/corectrl.nix
|
||||
./hardware/digitalbitbox.nix
|
||||
./hardware/device-tree.nix
|
||||
./hardware/gkraken.nix
|
||||
./hardware/flirc.nix
|
||||
./hardware/gpgsmartcards.nix
|
||||
./hardware/i2c.nix
|
||||
./hardware/sensor/hddtemp.nix
|
||||
./hardware/sensor/iio.nix
|
||||
|
@ -446,6 +448,7 @@
|
|||
./services/hardware/xow.nix
|
||||
./services/logging/SystemdJournal2Gelf.nix
|
||||
./services/logging/awstats.nix
|
||||
./services/logging/filebeat.nix
|
||||
./services/logging/fluentd.nix
|
||||
./services/logging/graylog.nix
|
||||
./services/logging/heartbeat.nix
|
||||
|
@ -467,6 +470,7 @@
|
|||
./services/mail/dovecot.nix
|
||||
./services/mail/dspam.nix
|
||||
./services/mail/exim.nix
|
||||
./services/mail/maddy.nix
|
||||
./services/mail/mail.nix
|
||||
./services/mail/mailcatcher.nix
|
||||
./services/mail/mailhog.nix
|
||||
|
@ -926,6 +930,7 @@
|
|||
./services/search/kibana.nix
|
||||
./services/search/meilisearch.nix
|
||||
./services/search/solr.nix
|
||||
./services/security/aesmd.nix
|
||||
./services/security/certmgr.nix
|
||||
./services/security/cfssl.nix
|
||||
./services/security/clamav.nix
|
||||
|
@ -1021,6 +1026,7 @@
|
|||
./services/web-apps/plantuml-server.nix
|
||||
./services/web-apps/plausible.nix
|
||||
./services/web-apps/pgpkeyserver-lite.nix
|
||||
./services/web-apps/powerdns-admin.nix
|
||||
./services/web-apps/matomo.nix
|
||||
./services/web-apps/moinmoin.nix
|
||||
./services/web-apps/openwebrx.nix
|
||||
|
@ -1191,8 +1197,7 @@
|
|||
./virtualisation/kvmgt.nix
|
||||
./virtualisation/openvswitch.nix
|
||||
./virtualisation/parallels-guest.nix
|
||||
./virtualisation/podman.nix
|
||||
./virtualisation/podman-network-socket-ghostunnel.nix
|
||||
./virtualisation/podman/default.nix
|
||||
./virtualisation/qemu-guest-agent.nix
|
||||
./virtualisation/railcar.nix
|
||||
./virtualisation/spice-usb-redirection.nix
|
||||
|
|
|
@ -3,6 +3,18 @@
|
|||
with lib;
|
||||
let
|
||||
cfg = config.programs.captive-browser;
|
||||
browserDefault = chromium: concatStringsSep " " [
|
||||
''env XDG_CONFIG_HOME="$PREV_CONFIG_HOME"''
|
||||
''${chromium}/bin/chromium''
|
||||
''--user-data-dir=''${XDG_DATA_HOME:-$HOME/.local/share}/chromium-captive''
|
||||
''--proxy-server="socks5://$PROXY"''
|
||||
''--host-resolver-rules="MAP * ~NOTFOUND , EXCLUDE localhost"''
|
||||
''--no-first-run''
|
||||
''--new-window''
|
||||
''--incognito''
|
||||
''-no-default-browser-check''
|
||||
''http://cache.nixos.org/''
|
||||
];
|
||||
in
|
||||
{
|
||||
###### interface
|
||||
|
@ -26,18 +38,8 @@ in
|
|||
# the options below are the same as in "captive-browser.toml"
|
||||
browser = mkOption {
|
||||
type = types.str;
|
||||
default = concatStringsSep " " [
|
||||
''env XDG_CONFIG_HOME="$PREV_CONFIG_HOME"''
|
||||
''${pkgs.chromium}/bin/chromium''
|
||||
''--user-data-dir=''${XDG_DATA_HOME:-$HOME/.local/share}/chromium-captive''
|
||||
''--proxy-server="socks5://$PROXY"''
|
||||
''--host-resolver-rules="MAP * ~NOTFOUND , EXCLUDE localhost"''
|
||||
''--no-first-run''
|
||||
''--new-window''
|
||||
''--incognito''
|
||||
''-no-default-browser-check''
|
||||
''http://cache.nixos.org/''
|
||||
];
|
||||
default = browserDefault pkgs.chromium;
|
||||
defaultText = literalExpression (browserDefault "\${pkgs.chromium}");
|
||||
description = ''
|
||||
The shell (/bin/sh) command executed once the proxy starts.
|
||||
When browser exits, the proxy exits. An extra env var PROXY is available.
|
||||
|
|
|
@ -60,7 +60,7 @@ in
|
|||
environment.systemPackages = [ pkgs.dconf ];
|
||||
|
||||
# Needed for unwrapped applications
|
||||
environment.sessionVariables.GIO_EXTRA_MODULES = mkIf cfg.enable [ "${pkgs.dconf.lib}/lib/gio/modules" ];
|
||||
environment.variables.GIO_EXTRA_MODULES = mkIf cfg.enable [ "${pkgs.dconf.lib}/lib/gio/modules" ];
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@ in
|
|||
type = types.nullOr (types.enum pkgs.pinentry.flavors);
|
||||
example = "gnome3";
|
||||
default = defaultPinentryFlavor;
|
||||
defaultText = literalDocBook ''matching the configured desktop environment'';
|
||||
description = ''
|
||||
Which pinentry interface to use. If not null, the path to the
|
||||
pinentry binary will be passed to gpg-agent via commandline and
|
||||
|
|
|
@ -33,6 +33,13 @@ in
|
|||
|
||||
programs.ssh = {
|
||||
|
||||
enableAskPassword = mkOption {
|
||||
type = types.bool;
|
||||
default = config.services.xserver.enable;
|
||||
defaultText = literalExpression "config.services.xserver.enable";
|
||||
description = "Whether to configure SSH_ASKPASS in the environment.";
|
||||
};
|
||||
|
||||
askPassword = mkOption {
|
||||
type = types.str;
|
||||
default = "${pkgs.x11_ssh_askpass}/libexec/x11-ssh-askpass";
|
||||
|
@ -287,7 +294,7 @@ in
|
|||
# Allow ssh-agent to ask for confirmation. This requires the
|
||||
# unit to know about the user's $DISPLAY (via ‘systemctl
|
||||
# import-environment’).
|
||||
environment.SSH_ASKPASS = optionalString config.services.xserver.enable askPasswordWrapper;
|
||||
environment.SSH_ASKPASS = optionalString cfg.enableAskPassword askPasswordWrapper;
|
||||
environment.DISPLAY = "fake"; # required to make ssh-agent start $SSH_ASKPASS
|
||||
};
|
||||
|
||||
|
@ -298,7 +305,7 @@ in
|
|||
fi
|
||||
'';
|
||||
|
||||
environment.variables.SSH_ASKPASS = optionalString config.services.xserver.enable askPassword;
|
||||
environment.variables.SSH_ASKPASS = optionalString cfg.enableAskPassword askPassword;
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# This module defines global configuration for the zshell.
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -9,6 +9,7 @@ let
|
|||
cfge = config.environment;
|
||||
|
||||
cfg = config.programs.zsh;
|
||||
opt = options.programs.zsh;
|
||||
|
||||
zshAliases = concatStringsSep "\n" (
|
||||
mapAttrsFlatten (k: v: "alias ${k}=${escapeShellArg v}")
|
||||
|
@ -147,6 +148,7 @@ in
|
|||
|
||||
enableGlobalCompInit = mkOption {
|
||||
default = cfg.enableCompletion;
|
||||
defaultText = literalExpression "config.${opt.enableCompletion}";
|
||||
description = ''
|
||||
Enable execution of compinit call for all interactive zsh shells.
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
with lib;
|
||||
let
|
||||
cfg = config.security.acme;
|
||||
opt = options.security.acme;
|
||||
|
||||
# Used to calculate timer accuracy for coalescing
|
||||
numCerts = length (builtins.attrNames cfg.certs);
|
||||
|
@ -163,9 +164,8 @@ let
|
|||
[ "--dns" data.dnsProvider ]
|
||||
++ optionals (!data.dnsPropagationCheck) [ "--dns.disable-cp" ]
|
||||
++ optionals (data.dnsResolver != null) [ "--dns.resolvers" data.dnsResolver ]
|
||||
) else (
|
||||
[ "--http" "--http.webroot" data.webroot ]
|
||||
);
|
||||
) else if data.listenHTTP != null then [ "--http" "--http.port" data.listenHTTP ]
|
||||
else [ "--http" "--http.webroot" data.webroot ];
|
||||
|
||||
commonOpts = [
|
||||
"--accept-tos" # Checking the option is covered by the assertions
|
||||
|
@ -321,11 +321,14 @@ let
|
|||
}
|
||||
fi
|
||||
'');
|
||||
} // optionalAttrs (data.listenHTTP != null && toInt (elemAt (splitString ":" data.listenHTTP) 1) < 1024) {
|
||||
AmbientCapabilities = "CAP_NET_BIND_SERVICE";
|
||||
};
|
||||
|
||||
# Working directory will be /tmp
|
||||
script = ''
|
||||
set -euxo pipefail
|
||||
${optionalString data.enableDebugLogs "set -x"}
|
||||
set -euo pipefail
|
||||
|
||||
# This reimplements the expiration date check, but without querying
|
||||
# the acme server first. By doing this offline, we avoid errors
|
||||
|
@ -438,6 +441,8 @@ let
|
|||
default = "_mkMergedOptionModule";
|
||||
};
|
||||
|
||||
enableDebugLogs = mkEnableOption "debug logging for this certificate" // { default = cfg.enableDebugLogs; };
|
||||
|
||||
webroot = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
|
@ -451,6 +456,17 @@ let
|
|||
'';
|
||||
};
|
||||
|
||||
listenHTTP = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = ":1360";
|
||||
description = ''
|
||||
Interface and port to listen on to solve HTTP challenges
|
||||
in the form [INTERFACE]:PORT.
|
||||
If you use a port other than 80, you must proxy port 80 to this port.
|
||||
'';
|
||||
};
|
||||
|
||||
server = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
|
@ -470,6 +486,7 @@ let
|
|||
email = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = cfg.email;
|
||||
defaultText = literalExpression "config.${opt.email}";
|
||||
description = "Contact email address for the CA to be able to reach you.";
|
||||
};
|
||||
|
||||
|
@ -616,6 +633,8 @@ in {
|
|||
options = {
|
||||
security.acme = {
|
||||
|
||||
enableDebugLogs = mkEnableOption "debug logging for all certificates by default" // { default = true; };
|
||||
|
||||
validMinDays = mkOption {
|
||||
type = types.int;
|
||||
default = 30;
|
||||
|
@ -778,6 +797,28 @@ in {
|
|||
`security.acme.certs.${cert}.webroot` are mutually exclusive.
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = data.webroot == null || data.listenHTTP == null;
|
||||
message = ''
|
||||
Options `security.acme.certs.${cert}.webroot` and
|
||||
`security.acme.certs.${cert}.listenHTTP` are mutually exclusive.
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = data.listenHTTP == null || data.dnsProvider == null;
|
||||
message = ''
|
||||
Options `security.acme.certs.${cert}.listenHTTP` and
|
||||
`security.acme.certs.${cert}.dnsProvider` are mutually exclusive.
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = data.dnsProvider != null || data.webroot != null || data.listenHTTP != null;
|
||||
message = ''
|
||||
One of `security.acme.certs.${cert}.dnsProvider`,
|
||||
`security.acme.certs.${cert}.webroot`, or
|
||||
`security.acme.certs.${cert}.listenHTTP` must be provided.
|
||||
'';
|
||||
}
|
||||
]) cfg.certs));
|
||||
|
||||
users.users.acme = {
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkOption types;
|
||||
inherit (lib) literalExpression mkOption types;
|
||||
cfg = config.security.dhparams;
|
||||
opt = options.security.dhparams;
|
||||
|
||||
bitType = types.addCheck types.int (b: b >= 16) // {
|
||||
name = "bits";
|
||||
|
@ -13,6 +14,7 @@ let
|
|||
options.bits = mkOption {
|
||||
type = bitType;
|
||||
default = cfg.defaultBitSize;
|
||||
defaultText = literalExpression "config.${opt.defaultBitSize}";
|
||||
description = ''
|
||||
The bit size for the prime that is used during a Diffie-Hellman
|
||||
key exchange.
|
||||
|
|
|
@ -295,9 +295,14 @@ let
|
|||
};
|
||||
|
||||
limits = mkOption {
|
||||
default = [];
|
||||
type = limitsType;
|
||||
description = ''
|
||||
Attribute set describing resource limits. Defaults to the
|
||||
value of <option>security.pam.loginLimits</option>.
|
||||
The meaning of the values is explained in <citerefentry>
|
||||
<refentrytitle>limits.conf</refentrytitle><manvolnum>5</manvolnum>
|
||||
</citerefentry>.
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -648,6 +653,51 @@ let
|
|||
"${domain} ${type} ${item} ${toString value}\n")
|
||||
limits);
|
||||
|
||||
limitsType = with lib.types; listOf (submodule ({ ... }: {
|
||||
options = {
|
||||
domain = mkOption {
|
||||
description = "Username, groupname, or wildcard this limit applies to";
|
||||
example = "@wheel";
|
||||
type = str;
|
||||
};
|
||||
|
||||
type = mkOption {
|
||||
description = "Type of this limit";
|
||||
type = enum [ "-" "hard" "soft" ];
|
||||
default = "-";
|
||||
};
|
||||
|
||||
item = mkOption {
|
||||
description = "Item this limit applies to";
|
||||
type = enum [
|
||||
"core"
|
||||
"data"
|
||||
"fsize"
|
||||
"memlock"
|
||||
"nofile"
|
||||
"rss"
|
||||
"stack"
|
||||
"cpu"
|
||||
"nproc"
|
||||
"as"
|
||||
"maxlogins"
|
||||
"maxsyslogins"
|
||||
"priority"
|
||||
"locks"
|
||||
"sigpending"
|
||||
"msgqueue"
|
||||
"nice"
|
||||
"rtprio"
|
||||
];
|
||||
};
|
||||
|
||||
value = mkOption {
|
||||
description = "Value of this limit";
|
||||
type = oneOf [ str int ];
|
||||
};
|
||||
};
|
||||
}));
|
||||
|
||||
motd = pkgs.writeText "motd" config.users.motd;
|
||||
|
||||
makePAMService = name: service:
|
||||
|
@ -669,6 +719,7 @@ in
|
|||
|
||||
security.pam.loginLimits = mkOption {
|
||||
default = [];
|
||||
type = limitsType;
|
||||
example =
|
||||
[ { domain = "ftp";
|
||||
type = "hard";
|
||||
|
@ -688,7 +739,8 @@ in
|
|||
<varname>domain</varname>, <varname>type</varname>,
|
||||
<varname>item</varname>, and <varname>value</varname>
|
||||
attribute. The syntax and semantics of these attributes
|
||||
must be that described in the limits.conf(5) man page.
|
||||
must be that described in <citerefentry><refentrytitle>limits.conf</refentrytitle>
|
||||
<manvolnum>5</manvolnum></citerefentry>.
|
||||
|
||||
Note that these limits do not apply to systemd services,
|
||||
whose limits can be changed via <option>systemd.extraConfig</option>
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
{ config, pkgs, lib, utils, ... }:
|
||||
|
||||
let
|
||||
toplevelConfig = config;
|
||||
inherit (lib) types;
|
||||
inherit (import ../system/boot/systemd-lib.nix {
|
||||
inherit config pkgs lib;
|
||||
}) mkPathSafeName;
|
||||
inherit (utils.systemdUtils.lib) mkPathSafeName;
|
||||
in {
|
||||
options.systemd.services = lib.mkOption {
|
||||
type = types.attrsOf (types.submodule ({ name, config, ... }: {
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.mpdscribble;
|
||||
mpdCfg = config.services.mpd;
|
||||
mpdOpt = options.services.mpd;
|
||||
|
||||
endpointUrls = {
|
||||
"last.fm" = "http://post.audioscrobbler.com";
|
||||
|
@ -108,6 +109,11 @@ in {
|
|||
mpdCfg.network.listenAddress
|
||||
else
|
||||
"localhost");
|
||||
defaultText = literalExpression ''
|
||||
if config.${mpdOpt.network.listenAddress} != "any"
|
||||
then config.${mpdOpt.network.listenAddress}
|
||||
else "localhost"
|
||||
'';
|
||||
type = types.str;
|
||||
description = ''
|
||||
Host for the mpdscribble daemon to search for a mpd daemon on.
|
||||
|
@ -122,6 +128,10 @@ in {
|
|||
mpdCfg.credentials).passwordFile
|
||||
else
|
||||
null;
|
||||
defaultText = literalDocBook ''
|
||||
The first password file with read access configured for MPD when using a local instance,
|
||||
otherwise <literal>null</literal>.
|
||||
'';
|
||||
type = types.nullOr types.str;
|
||||
description = ''
|
||||
File containing the password for the mpd daemon.
|
||||
|
@ -132,6 +142,7 @@ in {
|
|||
|
||||
port = mkOption {
|
||||
default = mpdCfg.network.port;
|
||||
defaultText = literalExpression "config.${mpdOpt.network.port}";
|
||||
type = types.port;
|
||||
description = ''
|
||||
Port for the mpdscribble daemon to search for a mpd daemon on.
|
||||
|
|
|
@ -54,12 +54,12 @@ let
|
|||
# tcp json rpc
|
||||
++ [ "--tcp.enabled ${toString cfg.tcp.enable}" ]
|
||||
++ optionals cfg.tcp.enable [
|
||||
"--tcp.address ${cfg.tcp.listenAddress}"
|
||||
"--tcp.bind_to_address ${cfg.tcp.listenAddress}"
|
||||
"--tcp.port ${toString cfg.tcp.port}" ]
|
||||
# http json rpc
|
||||
++ [ "--http.enabled ${toString cfg.http.enable}" ]
|
||||
++ optionals cfg.http.enable [
|
||||
"--http.address ${cfg.http.listenAddress}"
|
||||
"--http.bind_to_address ${cfg.http.listenAddress}"
|
||||
"--http.port ${toString cfg.http.port}"
|
||||
] ++ optional (cfg.http.docRoot != null) "--http.doc_root \"${toString cfg.http.docRoot}\"");
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, pkgs, utils, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
# Type for a valid systemd unit option. Needed for correctly passing "timerConfig" to "systemd.timers"
|
||||
unitOption = (import ../../system/boot/systemd-unit-options.nix { inherit config lib; }).unitOption;
|
||||
inherit (utils.systemdUtils.unitOptions) unitOption;
|
||||
in
|
||||
{
|
||||
options.services.restic.backups = mkOption {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
{ config, lib, pkgs, utils, ... }:
|
||||
{ config, lib, options, pkgs, utils, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
gcfg = config.services.tarsnap;
|
||||
opt = options.services.tarsnap;
|
||||
|
||||
configFile = name: cfg: ''
|
||||
keyfile ${cfg.keyfile}
|
||||
|
@ -59,12 +60,13 @@ in
|
|||
};
|
||||
|
||||
archives = mkOption {
|
||||
type = types.attrsOf (types.submodule ({ config, ... }:
|
||||
type = types.attrsOf (types.submodule ({ config, options, ... }:
|
||||
{
|
||||
options = {
|
||||
keyfile = mkOption {
|
||||
type = types.str;
|
||||
default = gcfg.keyfile;
|
||||
defaultText = literalExpression "config.${opt.keyfile}";
|
||||
description = ''
|
||||
Set a specific keyfile for this archive. This defaults to
|
||||
<literal>"/root/tarsnap.key"</literal> if left unspecified.
|
||||
|
@ -87,6 +89,9 @@ in
|
|||
cachedir = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = "/var/cache/tarsnap/${utils.escapeSystemdPath config.keyfile}";
|
||||
defaultText = literalExpression ''
|
||||
"/var/cache/tarsnap/''${utils.escapeSystemdPath config.${options.keyfile}}"
|
||||
'';
|
||||
description = ''
|
||||
The cache allows tarsnap to identify previously stored data
|
||||
blocks, reducing archival time and bandwidth usage.
|
||||
|
@ -320,21 +325,22 @@ in
|
|||
${optionalString cfg.explicitSymlinks "-H"} \
|
||||
${optionalString cfg.followSymlinks "-L"} \
|
||||
${concatStringsSep " " cfg.directories}'';
|
||||
cachedir = escapeShellArg cfg.cachedir;
|
||||
in if (cfg.cachedir != null) then ''
|
||||
mkdir -p ${cfg.cachedir}
|
||||
chmod 0700 ${cfg.cachedir}
|
||||
mkdir -p ${cachedir}
|
||||
chmod 0700 ${cachedir}
|
||||
|
||||
( flock 9
|
||||
if [ ! -e ${cfg.cachedir}/firstrun ]; then
|
||||
if [ ! -e ${cachedir}/firstrun ]; then
|
||||
( flock 10
|
||||
flock -u 9
|
||||
${tarsnap} --fsck
|
||||
flock 9
|
||||
) 10>${cfg.cachedir}/firstrun
|
||||
) 10>${cachedir}/firstrun
|
||||
fi
|
||||
) 9>${cfg.cachedir}/lockf
|
||||
) 9>${cachedir}/lockf
|
||||
|
||||
exec flock ${cfg.cachedir}/firstrun ${run}
|
||||
exec flock ${cachedir}/firstrun ${run}
|
||||
'' else "exec ${run}";
|
||||
|
||||
serviceConfig = {
|
||||
|
@ -356,22 +362,23 @@ in
|
|||
tarsnap = ''tarsnap --configfile "/etc/tarsnap/${name}.conf"'';
|
||||
lastArchive = "$(${tarsnap} --list-archives | sort | tail -1)";
|
||||
run = ''${tarsnap} -x -f "${lastArchive}" ${optionalString cfg.verbose "-v"}'';
|
||||
cachedir = escapeShellArg cfg.cachedir;
|
||||
|
||||
in if (cfg.cachedir != null) then ''
|
||||
mkdir -p ${cfg.cachedir}
|
||||
chmod 0700 ${cfg.cachedir}
|
||||
mkdir -p ${cachedir}
|
||||
chmod 0700 ${cachedir}
|
||||
|
||||
( flock 9
|
||||
if [ ! -e ${cfg.cachedir}/firstrun ]; then
|
||||
if [ ! -e ${cachedir}/firstrun ]; then
|
||||
( flock 10
|
||||
flock -u 9
|
||||
${tarsnap} --fsck
|
||||
flock 9
|
||||
) 10>${cfg.cachedir}/firstrun
|
||||
) 10>${cachedir}/firstrun
|
||||
fi
|
||||
) 9>${cfg.cachedir}/lockf
|
||||
) 9>${cachedir}/lockf
|
||||
|
||||
exec flock ${cfg.cachedir}/firstrun ${run}
|
||||
exec flock ${cachedir}/firstrun ${run}
|
||||
'' else "exec ${run}";
|
||||
|
||||
serviceConfig = {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{ config, lib, pkgs, ...}:
|
||||
{ config, lib, options, pkgs, ...}:
|
||||
let
|
||||
cfg = config.services.hadoop;
|
||||
opt = options.services.hadoop;
|
||||
in
|
||||
with lib;
|
||||
{
|
||||
|
@ -44,6 +45,14 @@ with lib;
|
|||
"mapreduce.map.env" = "HADOOP_MAPRED_HOME=${cfg.package}/lib/${cfg.package.untarDir}";
|
||||
"mapreduce.reduce.env" = "HADOOP_MAPRED_HOME=${cfg.package}/lib/${cfg.package.untarDir}";
|
||||
};
|
||||
defaultText = literalExpression ''
|
||||
{
|
||||
"mapreduce.framework.name" = "yarn";
|
||||
"yarn.app.mapreduce.am.env" = "HADOOP_MAPRED_HOME=''${config.${opt.package}}/lib/''${config.${opt.package}.untarDir}";
|
||||
"mapreduce.map.env" = "HADOOP_MAPRED_HOME=''${config.${opt.package}}/lib/''${config.${opt.package}.untarDir}";
|
||||
"mapreduce.reduce.env" = "HADOOP_MAPRED_HOME=''${config.${opt.package}}/lib/''${config.${opt.package}.untarDir}";
|
||||
}
|
||||
'';
|
||||
type = types.attrsOf types.anything;
|
||||
example = literalExpression ''
|
||||
options.services.hadoop.mapredSite.default // {
|
||||
|
@ -98,6 +107,9 @@ with lib;
|
|||
|
||||
log4jProperties = mkOption {
|
||||
default = "${cfg.package}/lib/${cfg.package.untarDir}/etc/hadoop/log4j.properties";
|
||||
defaultText = literalExpression ''
|
||||
"''${config.${opt.package}}/lib/''${config.${opt.package}.untarDir}/etc/hadoop/log4j.properties"
|
||||
'';
|
||||
type = types.path;
|
||||
example = literalExpression ''
|
||||
"''${pkgs.hadoop}/lib/''${pkgs.hadoop.untarDir}/etc/hadoop/log4j.properties";
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
{ config, options, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.kubernetes.addons.dashboard;
|
||||
opt = options.services.kubernetes.addons.dashboard;
|
||||
in {
|
||||
imports = [
|
||||
(mkRenamedOptionModule [ "services" "kubernetes" "addons" "dashboard" "enableRBAC" ] [ "services" "kubernetes" "addons" "dashboard" "rbac" "enable" ])
|
||||
|
@ -28,6 +29,9 @@ in {
|
|||
description = "Whether to enable role based access control is enabled for kubernetes dashboard";
|
||||
type = types.bool;
|
||||
default = elem "RBAC" config.services.kubernetes.apiserver.authorizationMode;
|
||||
defaultText = literalExpression ''
|
||||
elem "RBAC" config.${options.services.kubernetes.apiserver.authorizationMode}
|
||||
'';
|
||||
};
|
||||
|
||||
clusterAdmin = mkOption {
|
||||
|
@ -54,6 +58,14 @@ in {
|
|||
finalImageTag = cfg.version;
|
||||
sha256 = "01xrr4pwgr2hcjrjsi3d14ifpzdfbxzqpzxbk2fkbjb9zkv38zxy";
|
||||
};
|
||||
defaultText = literalExpression ''
|
||||
{
|
||||
imageName = "k8s.gcr.io/kubernetes-dashboard-amd64";
|
||||
imageDigest = "sha256:0ae6b69432e78069c5ce2bcde0fe409c5c4d6f0f4d9cd50a17974fea38898747";
|
||||
finalImageTag = config.${opt.version};
|
||||
sha256 = "01xrr4pwgr2hcjrjsi3d14ifpzdfbxzqpzxbk2fkbjb9zkv38zxy";
|
||||
};
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
{ config, options, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
|
@ -23,6 +23,10 @@ in {
|
|||
take 3 (splitString "." config.services.kubernetes.apiserver.serviceClusterIpRange
|
||||
))
|
||||
) + ".254";
|
||||
defaultText = literalDocBook ''
|
||||
The <literal>x.y.z.254</literal> IP of
|
||||
<literal>config.${options.services.kubernetes.apiserver.serviceClusterIpRange}</literal>.
|
||||
'';
|
||||
type = types.str;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
top = config.services.kubernetes;
|
||||
otop = options.services.kubernetes;
|
||||
cfg = top.apiserver;
|
||||
|
||||
isRBACEnabled = elem "RBAC" cfg.authorizationMode;
|
||||
|
@ -84,6 +85,7 @@ in
|
|||
clientCaFile = mkOption {
|
||||
description = "Kubernetes apiserver CA file for client auth.";
|
||||
default = top.caFile;
|
||||
defaultText = literalExpression "config.${otop.caFile}";
|
||||
type = nullOr path;
|
||||
};
|
||||
|
||||
|
@ -138,6 +140,7 @@ in
|
|||
caFile = mkOption {
|
||||
description = "Etcd ca file.";
|
||||
default = top.caFile;
|
||||
defaultText = literalExpression "config.${otop.caFile}";
|
||||
type = types.nullOr types.path;
|
||||
};
|
||||
};
|
||||
|
@ -157,6 +160,7 @@ in
|
|||
featureGates = mkOption {
|
||||
description = "List set of feature gates";
|
||||
default = top.featureGates;
|
||||
defaultText = literalExpression "config.${otop.featureGates}";
|
||||
type = listOf str;
|
||||
};
|
||||
|
||||
|
@ -175,6 +179,7 @@ in
|
|||
kubeletClientCaFile = mkOption {
|
||||
description = "Path to a cert file for connecting to kubelet.";
|
||||
default = top.caFile;
|
||||
defaultText = literalExpression "config.${otop.caFile}";
|
||||
type = nullOr path;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
top = config.services.kubernetes;
|
||||
otop = options.services.kubernetes;
|
||||
cfg = top.controllerManager;
|
||||
in
|
||||
{
|
||||
|
@ -30,6 +31,7 @@ in
|
|||
clusterCidr = mkOption {
|
||||
description = "Kubernetes CIDR Range for Pods in cluster.";
|
||||
default = top.clusterCidr;
|
||||
defaultText = literalExpression "config.${otop.clusterCidr}";
|
||||
type = str;
|
||||
};
|
||||
|
||||
|
@ -44,6 +46,7 @@ in
|
|||
featureGates = mkOption {
|
||||
description = "List set of feature gates";
|
||||
default = top.featureGates;
|
||||
defaultText = literalExpression "config.${otop.featureGates}";
|
||||
type = listOf str;
|
||||
};
|
||||
|
||||
|
@ -67,6 +70,7 @@ in
|
|||
service account's token secret.
|
||||
'';
|
||||
default = top.caFile;
|
||||
defaultText = literalExpression "config.${otop.caFile}";
|
||||
type = nullOr path;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.kubernetes;
|
||||
opt = options.services.kubernetes;
|
||||
|
||||
defaultContainerdSettings = {
|
||||
version = 2;
|
||||
|
@ -87,6 +88,7 @@ let
|
|||
description = "${prefix} certificate authority file used to connect to kube-apiserver.";
|
||||
type = types.nullOr types.path;
|
||||
default = cfg.caFile;
|
||||
defaultText = literalExpression "config.${opt.caFile}";
|
||||
};
|
||||
|
||||
certFile = mkOption {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
top = config.services.kubernetes;
|
||||
otop = options.services.kubernetes;
|
||||
cfg = top.kubelet;
|
||||
|
||||
cniConfig =
|
||||
|
@ -35,6 +36,7 @@ let
|
|||
key = mkOption {
|
||||
description = "Key of taint.";
|
||||
default = name;
|
||||
defaultText = literalDocBook "Name of this submodule.";
|
||||
type = str;
|
||||
};
|
||||
value = mkOption {
|
||||
|
@ -76,12 +78,14 @@ in
|
|||
clusterDomain = mkOption {
|
||||
description = "Use alternative domain.";
|
||||
default = config.services.kubernetes.addons.dns.clusterDomain;
|
||||
defaultText = literalExpression "config.${options.services.kubernetes.addons.dns.clusterDomain}";
|
||||
type = str;
|
||||
};
|
||||
|
||||
clientCaFile = mkOption {
|
||||
description = "Kubernetes apiserver CA file for client authentication.";
|
||||
default = top.caFile;
|
||||
defaultText = literalExpression "config.${otop.caFile}";
|
||||
type = nullOr path;
|
||||
};
|
||||
|
||||
|
@ -148,6 +152,7 @@ in
|
|||
featureGates = mkOption {
|
||||
description = "List set of feature gates";
|
||||
default = top.featureGates;
|
||||
defaultText = literalExpression "config.${otop.featureGates}";
|
||||
type = listOf str;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
top = config.services.kubernetes;
|
||||
otop = options.services.kubernetes;
|
||||
cfg = top.proxy;
|
||||
in
|
||||
{
|
||||
|
@ -31,6 +32,7 @@ in
|
|||
featureGates = mkOption {
|
||||
description = "List set of feature gates";
|
||||
default = top.featureGates;
|
||||
defaultText = literalExpression "config.${otop.featureGates}";
|
||||
type = listOf str;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
top = config.services.kubernetes;
|
||||
otop = options.services.kubernetes;
|
||||
cfg = top.scheduler;
|
||||
in
|
||||
{
|
||||
|
@ -27,6 +28,7 @@ in
|
|||
featureGates = mkOption {
|
||||
description = "List set of feature gates";
|
||||
default = top.featureGates;
|
||||
defaultText = literalExpression "config.${otop.featureGates}";
|
||||
type = listOf str;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.services.slurm;
|
||||
opt = options.services.slurm;
|
||||
# configuration file can be generated by http://slurm.schedmd.com/configurator.html
|
||||
|
||||
defaultUser = "slurm";
|
||||
|
@ -90,6 +91,7 @@ in
|
|||
storageUser = mkOption {
|
||||
type = types.str;
|
||||
default = cfg.user;
|
||||
defaultText = literalExpression "config.${opt.user}";
|
||||
description = ''
|
||||
Database user name.
|
||||
'';
|
||||
|
@ -154,6 +156,7 @@ in
|
|||
controlAddr = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = cfg.controlMachine;
|
||||
defaultText = literalExpression "config.${opt.controlMachine}";
|
||||
example = null;
|
||||
description = ''
|
||||
Name that ControlMachine should be referred to in establishing a
|
||||
|
@ -279,6 +282,10 @@ in
|
|||
type = types.path;
|
||||
internal = true;
|
||||
default = etcSlurm;
|
||||
defaultText = literalDocBook ''
|
||||
Directory created from generated config files and
|
||||
<literal>config.${opt.extraConfigPaths}</literal>.
|
||||
'';
|
||||
description = ''
|
||||
Path to directory with slurm config files. This option is set by default from the
|
||||
Slurm module and is meant to make the Slurm config file available to other modules.
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
# NixOS module for Buildbot continous integration server.
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.buildbot-master;
|
||||
opt = options.services.buildbot-master;
|
||||
|
||||
python = cfg.package.pythonModule;
|
||||
|
||||
|
@ -152,6 +153,7 @@ in {
|
|||
|
||||
buildbotDir = mkOption {
|
||||
default = "${cfg.home}/master";
|
||||
defaultText = literalExpression ''"''${config.${opt.home}}/master"'';
|
||||
type = types.path;
|
||||
description = "Specifies the Buildbot directory.";
|
||||
};
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
# NixOS module for Buildbot Worker.
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.buildbot-worker;
|
||||
opt = options.services.buildbot-worker;
|
||||
|
||||
python = cfg.package.pythonModule;
|
||||
|
||||
|
@ -77,6 +78,7 @@ in {
|
|||
|
||||
buildbotDir = mkOption {
|
||||
default = "${cfg.home}/worker";
|
||||
defaultText = literalExpression ''"''${config.${opt.home}}/worker"'';
|
||||
type = types.path;
|
||||
description = "Specifies the Buildbot directory.";
|
||||
};
|
||||
|
|
|
@ -10,6 +10,8 @@ let
|
|||
stateDir = "%S/${systemdDir}";
|
||||
# %L: Log directory root (usually /var/log); see systemd.unit(5)
|
||||
logsDir = "%L/${systemdDir}";
|
||||
# Name of file stored in service state directory
|
||||
currentConfigTokenFilename = ".current-token";
|
||||
in
|
||||
{
|
||||
options.services.github-runner = {
|
||||
|
@ -144,13 +146,11 @@ in
|
|||
ExecStart = "${cfg.package}/bin/runsvc.sh";
|
||||
|
||||
# Does the following, sequentially:
|
||||
# - Copy the current and the previous `tokenFile` to the $RUNTIME_DIRECTORY
|
||||
# and make it accessible to the service user to allow for a content
|
||||
# comparison.
|
||||
# - If the module configuration or the token has changed, clear the state directory.
|
||||
# - Configure the runner.
|
||||
# - Copy the configured `tokenFile` to the $STATE_DIRECTORY and make it
|
||||
# inaccessible to the service user.
|
||||
# - If the module configuration or the token has changed, purge the state directory,
|
||||
# and create the current and the new token file with the contents of the configured
|
||||
# token. While both files have the same content, only the later is accessible by
|
||||
# the service user.
|
||||
# - Configure the runner using the new token file. When finished, delete it.
|
||||
# - Set up the directory structure by creating the necessary symlinks.
|
||||
ExecStartPre =
|
||||
let
|
||||
|
@ -173,37 +173,20 @@ in
|
|||
currentConfigPath = "$STATE_DIRECTORY/.nixos-current-config.json";
|
||||
runnerRegistrationConfig = getAttrs [ "name" "tokenFile" "url" "runnerGroup" "extraLabels" ] cfg;
|
||||
newConfigPath = builtins.toFile "${svcName}-config.json" (builtins.toJSON runnerRegistrationConfig);
|
||||
currentConfigTokenFilename = ".current-token";
|
||||
newConfigTokenFilename = ".new-token";
|
||||
runnerCredFiles = [
|
||||
".credentials"
|
||||
".credentials_rsaparams"
|
||||
".runner"
|
||||
];
|
||||
ownConfigTokens = writeScript "own-config-tokens" ''
|
||||
# Copy current and new token file to runtime dir and make it accessible to the service user
|
||||
cp ${escapeShellArg cfg.tokenFile} "$RUNTIME_DIRECTORY/${newConfigTokenFilename}"
|
||||
chmod 600 "$RUNTIME_DIRECTORY/${newConfigTokenFilename}"
|
||||
chown "$USER" "$RUNTIME_DIRECTORY/${newConfigTokenFilename}"
|
||||
|
||||
if [[ -e "$STATE_DIRECTORY/${currentConfigTokenFilename}" ]]; then
|
||||
cp "$STATE_DIRECTORY/${currentConfigTokenFilename}" "$RUNTIME_DIRECTORY/${currentConfigTokenFilename}"
|
||||
chmod 600 "$RUNTIME_DIRECTORY/${currentConfigTokenFilename}"
|
||||
chown "$USER" "$RUNTIME_DIRECTORY/${currentConfigTokenFilename}"
|
||||
fi
|
||||
'';
|
||||
disownConfigTokens = writeScript "disown-config-tokens" ''
|
||||
# Make the token inaccessible to the runner service user
|
||||
chmod 600 "$STATE_DIRECTORY/${currentConfigTokenFilename}"
|
||||
chown root:root "$STATE_DIRECTORY/${currentConfigTokenFilename}"
|
||||
'';
|
||||
unconfigureRunner = writeScript "unconfigure" ''
|
||||
differs=
|
||||
# Set `differs = 1` if current and new runner config differ or if `currentConfigPath` does not exist
|
||||
${pkgs.diffutils}/bin/diff -q '${newConfigPath}' "${currentConfigPath}" >/dev/null 2>&1 || differs=1
|
||||
# Also trigger a registration if the token content changed
|
||||
${pkgs.diffutils}/bin/diff -q \
|
||||
"$RUNTIME_DIRECTORY"/{${currentConfigTokenFilename},${newConfigTokenFilename}} \
|
||||
"$STATE_DIRECTORY"/${currentConfigTokenFilename} \
|
||||
${escapeShellArg cfg.tokenFile} \
|
||||
>/dev/null 2>&1 || differs=1
|
||||
|
||||
if [[ -n "$differs" ]]; then
|
||||
|
@ -211,13 +194,18 @@ in
|
|||
echo "The old runner will still appear in the GitHub Actions UI." \
|
||||
"You have to remove it manually."
|
||||
find "$STATE_DIRECTORY/" -mindepth 1 -delete
|
||||
|
||||
# Copy the configured token file to the state dir and allow the service user to read the file
|
||||
install --mode=666 ${escapeShellArg cfg.tokenFile} "$STATE_DIRECTORY/${newConfigTokenFilename}"
|
||||
# Also copy current file to allow for a diff on the next start
|
||||
install --mode=600 ${escapeShellArg cfg.tokenFile} "$STATE_DIRECTORY/${currentConfigTokenFilename}"
|
||||
fi
|
||||
'';
|
||||
configureRunner = writeScript "configure" ''
|
||||
empty=$(ls -A "$STATE_DIRECTORY")
|
||||
if [[ -z "$empty" ]]; then
|
||||
if [[ -e "$STATE_DIRECTORY/${newConfigTokenFilename}" ]]; then
|
||||
echo "Configuring GitHub Actions Runner"
|
||||
token=$(< "$RUNTIME_DIRECTORY"/${newConfigTokenFilename})
|
||||
|
||||
token=$(< "$STATE_DIRECTORY"/${newConfigTokenFilename})
|
||||
RUNNER_ROOT="$STATE_DIRECTORY" ${cfg.package}/bin/config.sh \
|
||||
--unattended \
|
||||
--work "$RUNTIME_DIRECTORY" \
|
||||
|
@ -234,8 +222,7 @@ in
|
|||
rm -rf "$STATE_DIRECTORY/_diag/"
|
||||
|
||||
# Cleanup token from config
|
||||
rm -f "$RUNTIME_DIRECTORY"/${currentConfigTokenFilename}
|
||||
mv "$RUNTIME_DIRECTORY"/${newConfigTokenFilename} "$STATE_DIRECTORY/${currentConfigTokenFilename}"
|
||||
rm "$STATE_DIRECTORY/${newConfigTokenFilename}"
|
||||
|
||||
# Symlink to new config
|
||||
ln -s '${newConfigPath}' "${currentConfigPath}"
|
||||
|
@ -250,10 +237,8 @@ in
|
|||
'';
|
||||
in
|
||||
map (x: "${x} ${escapeShellArgs [ stateDir runtimeDir logsDir ]}") [
|
||||
"+${ownConfigTokens}" # runs as root
|
||||
unconfigureRunner
|
||||
"+${unconfigureRunner}" # runs as root
|
||||
configureRunner
|
||||
"+${disownConfigTokens}" # runs as root
|
||||
setupRuntimeDir
|
||||
];
|
||||
|
||||
|
@ -266,6 +251,13 @@ in
|
|||
StateDirectoryMode = "0700";
|
||||
WorkingDirectory = runtimeDir;
|
||||
|
||||
InaccessiblePaths = [
|
||||
# Token file path given in the configuration
|
||||
cfg.tokenFile
|
||||
# Token file in the state directory
|
||||
"${stateDir}/${currentConfigTokenFilename}"
|
||||
];
|
||||
|
||||
# By default, use a dynamically allocated user
|
||||
DynamicUser = true;
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.gocd-agent;
|
||||
opt = options.services.gocd-agent;
|
||||
in {
|
||||
options = {
|
||||
services.gocd-agent = {
|
||||
|
@ -98,6 +99,15 @@ in {
|
|||
"-Dcruise.console.publish.interval=10"
|
||||
"-Djava.security.egd=file:/dev/./urandom"
|
||||
];
|
||||
defaultText = literalExpression ''
|
||||
[
|
||||
"-Xms''${config.${opt.initialJavaHeapSize}}"
|
||||
"-Xmx''${config.${opt.maxJavaHeapMemory}}"
|
||||
"-Djava.io.tmpdir=/tmp"
|
||||
"-Dcruise.console.publish.interval=10"
|
||||
"-Djava.security.egd=file:/dev/./urandom"
|
||||
]
|
||||
'';
|
||||
description = ''
|
||||
Specifies startup command line arguments to pass to Go.CD agent
|
||||
java process.
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.gocd-server;
|
||||
opt = options.services.gocd-server;
|
||||
in {
|
||||
options = {
|
||||
services.gocd-server = {
|
||||
|
@ -106,6 +107,20 @@ in {
|
|||
"-Dcruise.server.port=${toString cfg.port}"
|
||||
"-Dcruise.server.ssl.port=${toString cfg.sslPort}"
|
||||
];
|
||||
defaultText = literalExpression ''
|
||||
[
|
||||
"-Xms''${config.${opt.initialJavaHeapSize}}"
|
||||
"-Xmx''${config.${opt.maxJavaHeapMemory}}"
|
||||
"-Dcruise.listen.host=''${config.${opt.listenAddress}}"
|
||||
"-Duser.language=en"
|
||||
"-Djruby.rack.request.size.threshold.bytes=30000000"
|
||||
"-Duser.country=US"
|
||||
"-Dcruise.config.dir=''${config.${opt.workDir}}/conf"
|
||||
"-Dcruise.config.file=''${config.${opt.workDir}}/conf/cruise-config.xml"
|
||||
"-Dcruise.server.port=''${toString config.${opt.port}}"
|
||||
"-Dcruise.server.ssl.port=''${toString config.${opt.sslPort}}"
|
||||
]
|
||||
'';
|
||||
|
||||
description = ''
|
||||
Specifies startup command line arguments to pass to Go.CD server
|
||||
|
|
|
@ -43,8 +43,8 @@ in {
|
|||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.couchdb;
|
||||
defaultText = literalExpression "pkgs.couchdb";
|
||||
default = pkgs.couchdb3;
|
||||
defaultText = literalExpression "pkgs.couchdb3";
|
||||
description = ''
|
||||
CouchDB package to use.
|
||||
'';
|
||||
|
@ -150,6 +150,14 @@ in {
|
|||
'';
|
||||
};
|
||||
|
||||
argsFile = mkOption {
|
||||
type = types.path;
|
||||
default = "${cfg.package}/etc/vm.args";
|
||||
description = ''
|
||||
vm.args configuration. Overrides Couchdb's Erlang VM parameters file.
|
||||
'';
|
||||
};
|
||||
|
||||
configFile = mkOption {
|
||||
type = types.path;
|
||||
description = ''
|
||||
|
@ -186,12 +194,14 @@ in {
|
|||
'';
|
||||
|
||||
environment = {
|
||||
# we are actually specifying 4 configuration files:
|
||||
# we are actually specifying 5 configuration files:
|
||||
# 1. the preinstalled default.ini
|
||||
# 2. the module configuration
|
||||
# 3. the extraConfig from the module options
|
||||
# 4. the locally writable config file, which couchdb itself writes to
|
||||
ERL_FLAGS= ''-couch_ini ${cfg.package}/etc/default.ini ${configFile} ${pkgs.writeText "couchdb-extra.ini" cfg.extraConfig} ${cfg.configFile}'';
|
||||
# 5. the vm.args file
|
||||
COUCHDB_ARGS_FILE=''${cfg.argsFile}'';
|
||||
};
|
||||
|
||||
serviceConfig = {
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{ config, options, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.hbase;
|
||||
|
||||
defaultConfig = {
|
||||
"hbase.rootdir" = "file://${cfg.dataDir}/hbase";
|
||||
"hbase.zookeeper.property.dataDir" = "${cfg.dataDir}/zookeeper";
|
||||
};
|
||||
opt = options.services.hbase;
|
||||
|
||||
buildProperty = configAttr:
|
||||
(builtins.concatStringsSep "\n"
|
||||
|
@ -23,7 +19,7 @@ let
|
|||
|
||||
configFile = pkgs.writeText "hbase-site.xml"
|
||||
''<configuration>
|
||||
${buildProperty (defaultConfig // cfg.settings)}
|
||||
${buildProperty (opt.settings.default // cfg.settings)}
|
||||
</configuration>
|
||||
'';
|
||||
|
||||
|
@ -96,7 +92,16 @@ in {
|
|||
|
||||
settings = mkOption {
|
||||
type = with lib.types; attrsOf (oneOf [ str int bool ]);
|
||||
default = defaultConfig;
|
||||
default = {
|
||||
"hbase.rootdir" = "file://${cfg.dataDir}/hbase";
|
||||
"hbase.zookeeper.property.dataDir" = "${cfg.dataDir}/zookeeper";
|
||||
};
|
||||
defaultText = literalExpression ''
|
||||
{
|
||||
"hbase.rootdir" = "file://''${config.${opt.dataDir}}/hbase";
|
||||
"hbase.zookeeper.property.dataDir" = "''${config.${opt.dataDir}}/zookeeper";
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
configurations in hbase-site.xml, see <link xlink:href="https://github.com/apache/hbase/blob/master/hbase-server/src/test/resources/hbase-site.xml"/> for details.
|
||||
'';
|
||||
|
|
|
@ -10,7 +10,7 @@ in
|
|||
services.influxdb2 = {
|
||||
enable = mkEnableOption "the influxdb2 server";
|
||||
package = mkOption {
|
||||
default = pkgs.influxdb2;
|
||||
default = pkgs.influxdb2-server;
|
||||
defaultText = literalExpression "pkgs.influxdb2";
|
||||
description = "influxdb2 derivation to use.";
|
||||
type = types.package;
|
||||
|
|
|
@ -4,6 +4,7 @@ with lib;
|
|||
|
||||
let
|
||||
cfg = config.services.neo4j;
|
||||
opt = options.services.neo4j;
|
||||
certDirOpt = options.services.neo4j.directories.certificates;
|
||||
isDefaultPathOption = opt: isOption opt && opt.type == types.path && opt.highestPrio >= 1500;
|
||||
|
||||
|
@ -256,6 +257,7 @@ in {
|
|||
certificates = mkOption {
|
||||
type = types.path;
|
||||
default = "${cfg.directories.home}/certificates";
|
||||
defaultText = literalExpression ''"''${config.${opt.directories.home}}/certificates"'';
|
||||
description = ''
|
||||
Directory for storing certificates to be used by Neo4j for
|
||||
TLS connections.
|
||||
|
@ -280,6 +282,7 @@ in {
|
|||
data = mkOption {
|
||||
type = types.path;
|
||||
default = "${cfg.directories.home}/data";
|
||||
defaultText = literalExpression ''"''${config.${opt.directories.home}}/data"'';
|
||||
description = ''
|
||||
Path of the data directory. You must not configure more than one
|
||||
Neo4j installation to use the same data directory.
|
||||
|
@ -305,6 +308,7 @@ in {
|
|||
imports = mkOption {
|
||||
type = types.path;
|
||||
default = "${cfg.directories.home}/import";
|
||||
defaultText = literalExpression ''"''${config.${opt.directories.home}}/import"'';
|
||||
description = ''
|
||||
The root directory for file URLs used with the Cypher
|
||||
<literal>LOAD CSV</literal> clause. Only meaningful when
|
||||
|
@ -321,6 +325,7 @@ in {
|
|||
plugins = mkOption {
|
||||
type = types.path;
|
||||
default = "${cfg.directories.home}/plugins";
|
||||
defaultText = literalExpression ''"''${config.${opt.directories.home}}/plugins"'';
|
||||
description = ''
|
||||
Path of the database plugin directory. Compiled Java JAR files that
|
||||
contain database procedures will be loaded if they are placed in
|
||||
|
@ -432,6 +437,7 @@ in {
|
|||
baseDirectory = mkOption {
|
||||
type = types.path;
|
||||
default = "${cfg.directories.certificates}/${name}";
|
||||
defaultText = literalExpression ''"''${config.${opt.directories.certificates}}/''${name}"'';
|
||||
description = ''
|
||||
The mandatory base directory for cryptographic objects of this
|
||||
policy. This path is only automatically generated when this
|
||||
|
@ -493,6 +499,7 @@ in {
|
|||
revokedDir = mkOption {
|
||||
type = types.path;
|
||||
default = "${config.baseDirectory}/revoked";
|
||||
defaultText = literalExpression ''"''${config.${options.baseDirectory}}/revoked"'';
|
||||
description = ''
|
||||
Path to directory of CRLs (Certificate Revocation Lists) in
|
||||
PEM format. Must be an absolute path. The existence of this
|
||||
|
@ -528,6 +535,7 @@ in {
|
|||
trustedDir = mkOption {
|
||||
type = types.path;
|
||||
default = "${config.baseDirectory}/trusted";
|
||||
defaultText = literalExpression ''"''${config.${options.baseDirectory}}/trusted"'';
|
||||
description = ''
|
||||
Path to directory of X.509 certificates in PEM format for
|
||||
trusted parties. Must be an absolute path. The existence of this
|
||||
|
|
|
@ -289,14 +289,16 @@ in
|
|||
port = cfg.port;
|
||||
};
|
||||
|
||||
services.postgresql.package =
|
||||
services.postgresql.package = let
|
||||
mkThrow = ver: throw "postgresql_${ver} was removed, please upgrade your postgresql version.";
|
||||
in
|
||||
# Note: when changing the default, make it conditional on
|
||||
# ‘system.stateVersion’ to maintain compatibility with existing
|
||||
# systems!
|
||||
mkDefault (if versionAtLeast config.system.stateVersion "21.11" then pkgs.postgresql_13
|
||||
else if versionAtLeast config.system.stateVersion "20.03" then pkgs.postgresql_11
|
||||
else if versionAtLeast config.system.stateVersion "17.09" then pkgs.postgresql_9_6
|
||||
else throw "postgresql_9_5 was removed, please upgrade your postgresql version.");
|
||||
else if versionAtLeast config.system.stateVersion "17.09" then mkThrow "9_6"
|
||||
else mkThrow "9_5");
|
||||
|
||||
services.postgresql.dataDir = mkDefault "/var/lib/postgresql/${cfg.package.psqlSchema}";
|
||||
|
||||
|
|
|
@ -52,37 +52,51 @@ Type "help" for help.
|
|||
<section xml:id="module-services-postgres-upgrading">
|
||||
<title>Upgrading</title>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Major PostgreSQL upgrade requires PostgreSQL downtime and a few imperative steps to be called. To simplify this process, use the following NixOS module:
|
||||
The steps below demonstrate how to upgrade from an older version to <package>pkgs.postgresql_13</package>.
|
||||
These instructions are also applicable to other versions.
|
||||
</para>
|
||||
</note>
|
||||
<para>
|
||||
Major PostgreSQL upgrades require a downtime and a few imperative steps to be called. This is the case because
|
||||
each major version has some internal changes in the databases' state during major releases. Because of that,
|
||||
NixOS places the state into <filename>/var/lib/postgresql/<version></filename> where each <literal>version</literal>
|
||||
can be obtained like this:
|
||||
<programlisting>
|
||||
containers.temp-pg.config.services.postgresql = {
|
||||
enable = true;
|
||||
package = pkgs.postgresql_12;
|
||||
## set a custom new dataDir
|
||||
# dataDir = "/some/data/dir";
|
||||
};
|
||||
environment.systemPackages =
|
||||
let newpg = config.containers.temp-pg.config.services.postgresql;
|
||||
in [
|
||||
<prompt>$ </prompt>nix-instantiate --eval -A postgresql_13.psqlSchema
|
||||
"13"
|
||||
</programlisting>
|
||||
For an upgrade, a script like this can be used to simplify the process:
|
||||
<programlisting>
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
<xref linkend="opt-environment.systemPackages" /> = [
|
||||
(pkgs.writeScriptBin "upgrade-pg-cluster" ''
|
||||
set -x
|
||||
export OLDDATA="${config.services.postgresql.dataDir}"
|
||||
export NEWDATA="${newpg.dataDir}"
|
||||
export OLDBIN="${config.services.postgresql.package}/bin"
|
||||
export NEWBIN="${newpg.package}/bin"
|
||||
set -eux
|
||||
# XXX it's perhaps advisable to stop all services that depend on postgresql
|
||||
systemctl stop postgresql
|
||||
|
||||
# XXX replace `<new version>` with the psqlSchema here
|
||||
export NEWDATA="/var/lib/postgresql/<new version>"
|
||||
|
||||
# XXX specify the postgresql package you'd like to upgrade to
|
||||
export NEWBIN="${pkgs.postgresql_13}/bin"
|
||||
|
||||
export OLDDATA="${config.<xref linkend="opt-services.postgresql.dataDir"/>}"
|
||||
export OLDBIN="${config.<xref linkend="opt-services.postgresql.package"/>}/bin"
|
||||
|
||||
install -d -m 0700 -o postgres -g postgres "$NEWDATA"
|
||||
cd "$NEWDATA"
|
||||
sudo -u postgres $NEWBIN/initdb -D "$NEWDATA"
|
||||
|
||||
systemctl stop postgresql # old one
|
||||
|
||||
sudo -u postgres $NEWBIN/pg_upgrade \
|
||||
--old-datadir "$OLDDATA" --new-datadir "$NEWDATA" \
|
||||
--old-bindir $OLDBIN --new-bindir $NEWBIN \
|
||||
"$@"
|
||||
'')
|
||||
];
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
|
@ -103,17 +117,25 @@ Type "help" for help.
|
|||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Run <literal>upgrade-pg-cluster</literal>. It will stop old postgresql, initialize new one and migrate old one to new one. You may supply arguments like <literal>--jobs 4</literal> and <literal>--link</literal> to speedup migration process. See <link xlink:href="https://www.postgresql.org/docs/current/pgupgrade.html" /> for details.
|
||||
Run <literal>upgrade-pg-cluster</literal>. It will stop old postgresql, initialize a new one and migrate the old one to the new one. You may supply arguments like <literal>--jobs 4</literal> and <literal>--link</literal> to speedup migration process. See <link xlink:href="https://www.postgresql.org/docs/current/pgupgrade.html" /> for details.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Change postgresql package in NixOS configuration to the one you were upgrading to, and change <literal>dataDir</literal> to the one you have migrated to. Rebuild NixOS. This should start new postgres using upgraded data directory.
|
||||
Change postgresql package in NixOS configuration to the one you were upgrading to via <xref linkend="opt-services.postgresql.package" />. Rebuild NixOS. This should start new postgres using upgraded data directory and all services you stopped during the upgrade.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
After upgrade you may want to <literal>ANALYZE</literal> new db.
|
||||
After the upgrade it's advisable to analyze the new cluster (as <literal>su -l postgres</literal> in the
|
||||
<xref linkend="opt-services.postgresql.dataDir" />, in this example <filename>/var/lib/postgresql/13</filename>):
|
||||
<programlisting>
|
||||
<prompt>$ </prompt>./analyze_new_cluster.sh
|
||||
</programlisting>
|
||||
<warning><para>The next step removes the old state-directory!</para></warning>
|
||||
<programlisting>
|
||||
<prompt>$ </prompt>./delete_old_cluster.sh
|
||||
</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
|
|
|
@ -5,17 +5,18 @@ with lib;
|
|||
let
|
||||
cfg = config.services.redis;
|
||||
|
||||
ulimitNofile = cfg.maxclients + 32;
|
||||
|
||||
mkValueString = value:
|
||||
if value == true then "yes"
|
||||
else if value == false then "no"
|
||||
else generators.mkValueStringDefault { } value;
|
||||
|
||||
redisConfig = pkgs.writeText "redis.conf" (generators.toKeyValue {
|
||||
redisConfig = settings: pkgs.writeText "redis.conf" (generators.toKeyValue {
|
||||
listsAsDuplicateKeys = true;
|
||||
mkKeyValue = generators.mkKeyValueDefault { inherit mkValueString; } " ";
|
||||
} cfg.settings);
|
||||
} settings);
|
||||
|
||||
redisName = name: "redis" + optionalString (name != "") ("-"+name);
|
||||
enabledServers = filterAttrs (name: conf: conf.enable) config.services.redis.servers;
|
||||
|
||||
in {
|
||||
imports = [
|
||||
|
@ -24,7 +25,28 @@ in {
|
|||
(mkRemovedOptionModule [ "services" "redis" "dbFilename" ] "The redis module now uses /var/lib/redis/dump.rdb as database dump location.")
|
||||
(mkRemovedOptionModule [ "services" "redis" "appendOnlyFilename" ] "This option was never used.")
|
||||
(mkRemovedOptionModule [ "services" "redis" "pidFile" ] "This option was removed.")
|
||||
(mkRemovedOptionModule [ "services" "redis" "extraConfig" ] "Use services.redis.settings instead.")
|
||||
(mkRemovedOptionModule [ "services" "redis" "extraConfig" ] "Use services.redis.servers.*.settings instead.")
|
||||
(mkRenamedOptionModule [ "services" "redis" "enable"] [ "services" "redis" "servers" "" "enable" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "port"] [ "services" "redis" "servers" "" "port" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "openFirewall"] [ "services" "redis" "servers" "" "openFirewall" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "bind"] [ "services" "redis" "servers" "" "bind" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "unixSocket"] [ "services" "redis" "servers" "" "unixSocket" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "unixSocketPerm"] [ "services" "redis" "servers" "" "unixSocketPerm" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "logLevel"] [ "services" "redis" "servers" "" "logLevel" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "logfile"] [ "services" "redis" "servers" "" "logfile" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "syslog"] [ "services" "redis" "servers" "" "syslog" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "databases"] [ "services" "redis" "servers" "" "databases" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "maxclients"] [ "services" "redis" "servers" "" "maxclients" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "save"] [ "services" "redis" "servers" "" "save" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "slaveOf"] [ "services" "redis" "servers" "" "slaveOf" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "masterAuth"] [ "services" "redis" "servers" "" "masterAuth" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "requirePass"] [ "services" "redis" "servers" "" "requirePass" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "requirePassFile"] [ "services" "redis" "servers" "" "requirePassFile" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "appendOnly"] [ "services" "redis" "servers" "" "appendOnly" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "appendFsync"] [ "services" "redis" "servers" "" "appendFsync" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "slowLogLogSlowerThan"] [ "services" "redis" "servers" "" "slowLogLogSlowerThan" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "slowLogMaxLen"] [ "services" "redis" "servers" "" "slowLogMaxLen" ])
|
||||
(mkRenamedOptionModule [ "services" "redis" "settings"] [ "services" "redis" "servers" "" "settings" ])
|
||||
];
|
||||
|
||||
###### interface
|
||||
|
@ -32,18 +54,6 @@ in {
|
|||
options = {
|
||||
|
||||
services.redis = {
|
||||
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to enable the Redis server. Note that the NixOS module for
|
||||
Redis disables kernel support for Transparent Huge Pages (THP),
|
||||
because this features causes major performance problems for Redis,
|
||||
e.g. (https://redis.io/topics/latency).
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.redis;
|
||||
|
@ -51,20 +61,36 @@ in {
|
|||
description = "Which Redis derivation to use.";
|
||||
};
|
||||
|
||||
vmOverCommit = mkEnableOption ''
|
||||
setting of vm.overcommit_memory to 1
|
||||
(Suggested for Background Saving: http://redis.io/topics/faq)
|
||||
'';
|
||||
|
||||
servers = mkOption {
|
||||
type = with types; attrsOf (submodule ({config, name, ...}@args: {
|
||||
options = {
|
||||
enable = mkEnableOption ''
|
||||
Redis server.
|
||||
|
||||
Note that the NixOS module for Redis disables kernel support
|
||||
for Transparent Huge Pages (THP),
|
||||
because this features causes major performance problems for Redis,
|
||||
e.g. (https://redis.io/topics/latency).
|
||||
'';
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = redisName name;
|
||||
defaultText = "\"redis\" or \"redis-\${name}\" if name != \"\"";
|
||||
description = "The username and groupname for redis-server.";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 6379;
|
||||
description = "The port for Redis to listen to.";
|
||||
};
|
||||
|
||||
vmOverCommit = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Set vm.overcommit_memory to 1 (Suggested for Background Saving: http://redis.io/topics/faq)
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
|
@ -75,7 +101,8 @@ in {
|
|||
|
||||
bind = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = "127.0.0.1";
|
||||
default = if name == "" then "127.0.0.1" else null;
|
||||
defaultText = "127.0.0.1 or null if name != \"\"";
|
||||
description = ''
|
||||
The IP interface to bind to.
|
||||
<literal>null</literal> means "all interfaces".
|
||||
|
@ -85,16 +112,16 @@ in {
|
|||
|
||||
unixSocket = mkOption {
|
||||
type = with types; nullOr path;
|
||||
default = null;
|
||||
default = "/run/${redisName name}/redis.sock";
|
||||
defaultText = "\"/run/redis/redis.sock\" or \"/run/redis-\${name}/redis.sock\" if name != \"\"";
|
||||
description = "The path to the socket to bind to.";
|
||||
example = "/run/redis/redis.sock";
|
||||
};
|
||||
|
||||
unixSocketPerm = mkOption {
|
||||
type = types.int;
|
||||
default = 750;
|
||||
default = 660;
|
||||
description = "Change permissions for the socket";
|
||||
example = 700;
|
||||
example = 600;
|
||||
};
|
||||
|
||||
logLevel = mkOption {
|
||||
|
@ -209,6 +236,7 @@ in {
|
|||
};
|
||||
|
||||
settings = mkOption {
|
||||
# TODO: this should be converted to freeformType
|
||||
type = with types; attrsOf (oneOf [ bool int str (listOf str) ]);
|
||||
default = {};
|
||||
description = ''
|
||||
|
@ -223,84 +251,99 @@ in {
|
|||
'';
|
||||
};
|
||||
};
|
||||
config.settings = mkMerge [
|
||||
{
|
||||
port = if config.bind == null then 0 else config.port;
|
||||
daemonize = false;
|
||||
supervised = "systemd";
|
||||
loglevel = config.logLevel;
|
||||
logfile = config.logfile;
|
||||
syslog-enabled = config.syslog;
|
||||
databases = config.databases;
|
||||
maxclients = config.maxclients;
|
||||
save = map (d: "${toString (builtins.elemAt d 0)} ${toString (builtins.elemAt d 1)}") config.save;
|
||||
dbfilename = "dump.rdb";
|
||||
dir = "/var/lib/${redisName name}";
|
||||
appendOnly = config.appendOnly;
|
||||
appendfsync = config.appendFsync;
|
||||
slowlog-log-slower-than = config.slowLogLogSlowerThan;
|
||||
slowlog-max-len = config.slowLogMaxLen;
|
||||
}
|
||||
(mkIf (config.bind != null) { bind = config.bind; })
|
||||
(mkIf (config.unixSocket != null) {
|
||||
unixsocket = config.unixSocket;
|
||||
unixsocketperm = toString config.unixSocketPerm;
|
||||
})
|
||||
(mkIf (config.slaveOf != null) { slaveof = "${config.slaveOf.ip} ${toString config.slaveOf.port}"; })
|
||||
(mkIf (config.masterAuth != null) { masterauth = config.masterAuth; })
|
||||
(mkIf (config.requirePass != null) { requirepass = config.requirePass; })
|
||||
];
|
||||
}));
|
||||
description = "Configuration of multiple <literal>redis-server</literal> instances.";
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf config.services.redis.enable {
|
||||
assertions = [{
|
||||
assertion = cfg.requirePass != null -> cfg.requirePassFile == null;
|
||||
message = "You can only set one services.redis.requirePass or services.redis.requirePassFile";
|
||||
}];
|
||||
boot.kernel.sysctl = (mkMerge [
|
||||
config = mkIf (enabledServers != {}) {
|
||||
|
||||
assertions = attrValues (mapAttrs (name: conf: {
|
||||
assertion = conf.requirePass != null -> conf.requirePassFile == null;
|
||||
message = ''
|
||||
You can only set one services.redis.servers.${name}.requirePass
|
||||
or services.redis.servers.${name}.requirePassFile
|
||||
'';
|
||||
}) enabledServers);
|
||||
|
||||
boot.kernel.sysctl = mkMerge [
|
||||
{ "vm.nr_hugepages" = "0"; }
|
||||
( mkIf cfg.vmOverCommit { "vm.overcommit_memory" = "1"; } )
|
||||
]);
|
||||
];
|
||||
|
||||
networking.firewall = mkIf cfg.openFirewall {
|
||||
allowedTCPPorts = [ cfg.port ];
|
||||
};
|
||||
|
||||
users.users.redis = {
|
||||
description = "Redis database user";
|
||||
group = "redis";
|
||||
isSystemUser = true;
|
||||
};
|
||||
users.groups.redis = {};
|
||||
networking.firewall.allowedTCPPorts = concatMap (conf:
|
||||
optional conf.openFirewall conf.port
|
||||
) (attrValues enabledServers);
|
||||
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
services.redis.settings = mkMerge [
|
||||
{
|
||||
port = cfg.port;
|
||||
daemonize = false;
|
||||
supervised = "systemd";
|
||||
loglevel = cfg.logLevel;
|
||||
logfile = cfg.logfile;
|
||||
syslog-enabled = cfg.syslog;
|
||||
databases = cfg.databases;
|
||||
maxclients = cfg.maxclients;
|
||||
save = map (d: "${toString (builtins.elemAt d 0)} ${toString (builtins.elemAt d 1)}") cfg.save;
|
||||
dbfilename = "dump.rdb";
|
||||
dir = "/var/lib/redis";
|
||||
appendOnly = cfg.appendOnly;
|
||||
appendfsync = cfg.appendFsync;
|
||||
slowlog-log-slower-than = cfg.slowLogLogSlowerThan;
|
||||
slowlog-max-len = cfg.slowLogMaxLen;
|
||||
}
|
||||
(mkIf (cfg.bind != null) { bind = cfg.bind; })
|
||||
(mkIf (cfg.unixSocket != null) { unixsocket = cfg.unixSocket; unixsocketperm = "${toString cfg.unixSocketPerm}"; })
|
||||
(mkIf (cfg.slaveOf != null) { slaveof = "${cfg.slaveOf.ip} ${toString cfg.slaveOf.port}"; })
|
||||
(mkIf (cfg.masterAuth != null) { masterauth = cfg.masterAuth; })
|
||||
(mkIf (cfg.requirePass != null) { requirepass = cfg.requirePass; })
|
||||
];
|
||||
users.users = mapAttrs' (name: conf: nameValuePair (redisName name) {
|
||||
description = "System user for the redis-server instance ${name}";
|
||||
isSystemUser = true;
|
||||
group = redisName name;
|
||||
}) enabledServers;
|
||||
users.groups = mapAttrs' (name: conf: nameValuePair (redisName name) {
|
||||
}) enabledServers;
|
||||
|
||||
systemd.services.redis = {
|
||||
description = "Redis Server";
|
||||
systemd.services = mapAttrs' (name: conf: nameValuePair (redisName name) {
|
||||
description = "Redis Server - ${redisName name}";
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
|
||||
preStart = ''
|
||||
install -m 600 ${redisConfig} /run/redis/redis.conf
|
||||
'' + optionalString (cfg.requirePassFile != null) ''
|
||||
password=$(cat ${escapeShellArg cfg.requirePassFile})
|
||||
echo "requirePass $password" >> /run/redis/redis.conf
|
||||
'';
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${cfg.package}/bin/redis-server /run/redis/redis.conf";
|
||||
ExecStart = "${cfg.package}/bin/redis-server /run/${redisName name}/redis.conf";
|
||||
ExecStartPre = [("+"+pkgs.writeShellScript "${redisName name}-credentials" (''
|
||||
install -o '${conf.user}' -m 600 ${redisConfig conf.settings} /run/${redisName name}/redis.conf
|
||||
'' + optionalString (conf.requirePassFile != null) ''
|
||||
{
|
||||
printf requirePass' '
|
||||
cat ${escapeShellArg conf.requirePassFile}
|
||||
} >>/run/${redisName name}/redis.conf
|
||||
'')
|
||||
)];
|
||||
Type = "notify";
|
||||
# User and group
|
||||
User = "redis";
|
||||
Group = "redis";
|
||||
User = conf.user;
|
||||
Group = conf.user;
|
||||
# Runtime directory and mode
|
||||
RuntimeDirectory = "redis";
|
||||
RuntimeDirectory = redisName name;
|
||||
RuntimeDirectoryMode = "0750";
|
||||
# State directory and mode
|
||||
StateDirectory = "redis";
|
||||
StateDirectory = redisName name;
|
||||
StateDirectoryMode = "0700";
|
||||
# Access write directories
|
||||
UMask = "0077";
|
||||
|
@ -309,7 +352,7 @@ in {
|
|||
# Security
|
||||
NoNewPrivileges = true;
|
||||
# Process Properties
|
||||
LimitNOFILE = "${toString ulimitNofile}";
|
||||
LimitNOFILE = mkDefault "${toString (conf.maxclients + 32)}";
|
||||
# Sandboxing
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
|
@ -322,7 +365,9 @@ in {
|
|||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
|
||||
RestrictAddressFamilies =
|
||||
optionals (conf.bind != null) ["AF_INET" "AF_INET6"] ++
|
||||
optional (conf.unixSocket != null) "AF_UNIX";
|
||||
RestrictNamespaces = true;
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
|
@ -333,6 +378,7 @@ in {
|
|||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = "~@cpu-emulation @debug @keyring @memlock @mount @obsolete @privileged @resources @setuid";
|
||||
};
|
||||
};
|
||||
}) enabledServers;
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ with lib;
|
|||
|
||||
systemd.packages = [ pkgs.glib-networking ];
|
||||
|
||||
environment.sessionVariables.GIO_EXTRA_MODULES = [ "${pkgs.glib-networking.out}/lib/gio/modules" ];
|
||||
environment.variables.GIO_EXTRA_MODULES = [ "${pkgs.glib-networking.out}/lib/gio/modules" ];
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ in
|
|||
services.udev.packages = [ pkgs.libmtp.bin ];
|
||||
|
||||
# Needed for unwrapped applications
|
||||
environment.sessionVariables.GIO_EXTRA_MODULES = [ "${cfg.package}/lib/gio/modules" ];
|
||||
environment.variables.GIO_EXTRA_MODULES = [ "${cfg.package}/lib/gio/modules" ];
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ in {
|
|||
|
||||
haskellPackages = mkOption {
|
||||
description = "Which haskell package set to use.";
|
||||
type = types.attrs;
|
||||
default = pkgs.haskellPackages;
|
||||
defaultText = literalExpression "pkgs.haskellPackages";
|
||||
};
|
||||
|
|
|
@ -71,6 +71,7 @@ in {
|
|||
baseq3 = mkOption {
|
||||
type = types.either types.package types.path;
|
||||
default = defaultBaseq3;
|
||||
defaultText = literalDocBook "Manually downloaded Quake 3 installation directory.";
|
||||
example = "/var/lib/q3ds";
|
||||
description = ''
|
||||
Path to the baseq3 files (pak*.pk3). If this is on the nix store (type = package) all .pk3 files should be saved
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.terraria;
|
||||
opt = options.services.terraria;
|
||||
worldSizeMap = { small = 1; medium = 2; large = 3; };
|
||||
valFlag = name: val: optionalString (val != null) "-${name} \"${escape ["\\" "\""] (toString val)}\"";
|
||||
boolFlag = name: val: optionalString val "-${name}";
|
||||
|
@ -36,7 +37,7 @@ in
|
|||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
If enabled, starts a Terraria server. The server can be connected to via <literal>tmux -S ${cfg.dataDir}/terraria.sock attach</literal>
|
||||
If enabled, starts a Terraria server. The server can be connected to via <literal>tmux -S ''${config.${opt.dataDir}}/terraria.sock attach</literal>
|
||||
for administration by users who are a part of the <literal>terraria</literal> group (use <literal>C-b d</literal> shortcut to detach again).
|
||||
'';
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue